From 03a419404734dde97302f4800888f8c4b60ea235 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 14 Dec 2021 14:44:09 +0300 Subject: [PATCH 001/222] Add location attachment icon with required permissions. --- vector/src/main/AndroidManifest.xml | 4 ++++ .../vector/app/core/utils/PermissionsTools.kt | 1 + .../attachments/AttachmentTypeSelectorView.kt | 23 +++++++++++-------- .../home/room/detail/RoomDetailFragment.kt | 15 ++++++------ .../drawable/ic_attachment_location_white.xml | 9 ++++++++ .../layout/view_attachment_type_selector.xml | 21 +++++++++++++++++ vector/src/main/res/values/strings.xml | 1 + 7 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_attachment_location_white.xml diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 93f4ac7632..f03b8735b4 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -42,6 +42,10 @@ android:name="android.permission.WRITE_CALENDAR" tools:node="remove" /> + + + + diff --git a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt index ba396ed252..5fc5e0de84 100644 --- a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt +++ b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt @@ -40,6 +40,7 @@ val PERMISSIONS_FOR_MEMBERS_SEARCH = listOf(Manifest.permission.READ_CONTACTS) val PERMISSIONS_FOR_ROOM_AVATAR = listOf(Manifest.permission.CAMERA) val PERMISSIONS_FOR_WRITING_FILES = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) val PERMISSIONS_FOR_PICKING_CONTACT = listOf(Manifest.permission.READ_CONTACTS) +val PERMISSIONS_FOR_LOCATION_SHARING = listOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) val PERMISSIONS_EMPTY = emptyList() diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt index ccc07ef118..da3d40b36e 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt @@ -40,6 +40,7 @@ import com.amulyakhare.textdrawable.util.ColorGenerator import im.vector.app.R import im.vector.app.core.extensions.getMeasurements import im.vector.app.core.utils.PERMISSIONS_EMPTY +import im.vector.app.core.utils.PERMISSIONS_FOR_LOCATION_SHARING import im.vector.app.core.utils.PERMISSIONS_FOR_PICKING_CONTACT import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO import im.vector.app.databinding.ViewAttachmentTypeSelectorBinding @@ -77,6 +78,7 @@ class AttachmentTypeSelectorView(context: Context, views.attachmentAudioButton.configure(Type.AUDIO) views.attachmentContactButton.configure(Type.CONTACT) views.attachmentPollButton.configure(Type.POLL) + views.attachmentLocationButton.configure(Type.LOCATION) width = LinearLayout.LayoutParams.MATCH_PARENT height = LinearLayout.LayoutParams.WRAP_CONTENT animationStyle = 0 @@ -110,7 +112,8 @@ class AttachmentTypeSelectorView(context: Context, animateButtonIn(views.attachmentAudioButton, 0) animateButtonIn(views.attachmentContactButton, ANIMATION_DURATION / 4) animateButtonIn(views.attachmentStickersButton, ANIMATION_DURATION / 2) - animateButtonIn(views.attachmentPollButton, ANIMATION_DURATION / 4) + animateButtonIn(views.attachmentPollButton, ANIMATION_DURATION / 2) + animateButtonIn(views.attachmentLocationButton, ANIMATION_DURATION / 4) } override fun dismiss() { @@ -124,13 +127,14 @@ class AttachmentTypeSelectorView(context: Context, fun setAttachmentVisibility(type: Type, isVisible: Boolean) { when (type) { - Type.CAMERA -> views.attachmentCameraButtonContainer - Type.GALLERY -> views.attachmentGalleryButtonContainer - Type.FILE -> views.attachmentFileButtonContainer - Type.STICKER -> views.attachmentStickersButtonContainer - Type.AUDIO -> views.attachmentAudioButtonContainer - Type.CONTACT -> views.attachmentContactButtonContainer - Type.POLL -> views.attachmentPollButtonContainer + Type.CAMERA -> views.attachmentCameraButtonContainer + Type.GALLERY -> views.attachmentGalleryButtonContainer + Type.FILE -> views.attachmentFileButtonContainer + Type.STICKER -> views.attachmentStickersButtonContainer + Type.AUDIO -> views.attachmentAudioButtonContainer + Type.CONTACT -> views.attachmentContactButtonContainer + Type.POLL -> views.attachmentPollButtonContainer + Type.LOCATION -> views.attachmentLocationButtonContainer }.let { it.isVisible = isVisible } @@ -230,6 +234,7 @@ class AttachmentTypeSelectorView(context: Context, STICKER(PERMISSIONS_EMPTY), AUDIO(PERMISSIONS_EMPTY), CONTACT(PERMISSIONS_FOR_PICKING_CONTACT), - POLL(PERMISSIONS_EMPTY) + POLL(PERMISSIONS_EMPTY), + LOCATION(PERMISSIONS_FOR_LOCATION_SHARING) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index a77899a8b0..455f93f973 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -2207,18 +2207,19 @@ class RoomDetailFragment @Inject constructor( private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) { when (type) { - AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera( + AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera( activity = requireActivity(), vectorPreferences = vectorPreferences, cameraActivityResultLauncher = attachmentCameraActivityResultLauncher, cameraVideoActivityResultLauncher = attachmentCameraVideoActivityResultLauncher ) - AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher) - AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher) - AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher) - AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher) - AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment) - AttachmentTypeSelectorView.Type.POLL -> navigator.openCreatePoll(requireContext(), roomDetailArgs.roomId) + AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher) + AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher) + AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher) + AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher) + AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment) + AttachmentTypeSelectorView.Type.POLL -> navigator.openCreatePoll(requireContext(), roomDetailArgs.roomId) + AttachmentTypeSelectorView.Type.LOCATION -> Timber.d("On location attachment clicked") }.exhaustive } diff --git a/vector/src/main/res/drawable/ic_attachment_location_white.xml b/vector/src/main/res/drawable/ic_attachment_location_white.xml new file mode 100644 index 0000000000..865362312b --- /dev/null +++ b/vector/src/main/res/drawable/ic_attachment_location_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/layout/view_attachment_type_selector.xml b/vector/src/main/res/layout/view_attachment_type_selector.xml index 4cd5e1910d..9ca7b8cdb0 100644 --- a/vector/src/main/res/layout/view_attachment_type_selector.xml +++ b/vector/src/main/res/layout/view_attachment_type_selector.xml @@ -194,6 +194,27 @@ android:importantForAccessibility="no" android:text="@string/attachment_type_poll" /> + + + + + + + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 34ac5fcddc..38c7d355c3 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2466,6 +2466,7 @@ "Gallery" "Sticker" Poll + Location Rotate and crop Couldn\'t handle share data From bf48617fc6354ed0f88a03e13b0ff1fb41525b28 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 15 Dec 2021 00:13:52 +0300 Subject: [PATCH 002/222] Create base UI components of location sharing screen. --- vector/src/main/AndroidManifest.xml | 1 + .../app/core/di/MavericksViewModelModule.kt | 6 ++ .../home/room/detail/RoomDetailFragment.kt | 5 +- .../location/LocationSharingAction.kt | 23 ++++++ .../location/LocationSharingActivity.kt | 80 +++++++++++++++++++ .../location/LocationSharingFragment.kt | 40 ++++++++++ .../location/LocationSharingViewEvents.kt | 23 ++++++ .../location/LocationSharingViewModel.kt | 41 ++++++++++ .../location/LocationSharingViewState.kt | 37 +++++++++ .../features/navigation/DefaultNavigator.kt | 11 +++ .../app/features/navigation/Navigator.kt | 3 + .../res/layout/activity_location_sharing.xml | 26 ++++++ .../res/layout/fragment_location_sharing.xml | 6 ++ vector/src/main/res/values/strings.xml | 4 + 14 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt create mode 100755 vector/src/main/res/layout/activity_location_sharing.xml create mode 100644 vector/src/main/res/layout/fragment_location_sharing.xml diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index f03b8735b4..28833ab333 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -336,6 +336,7 @@ + diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index d09cd21d19..b9757078ea 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -53,6 +53,7 @@ import im.vector.app.features.home.room.detail.upgrade.MigrateRoomViewModel import im.vector.app.features.home.room.list.RoomListViewModel import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel import im.vector.app.features.invite.InviteUsersToRoomViewModel +import im.vector.app.features.location.LocationSharingViewModel import im.vector.app.features.login.LoginViewModel import im.vector.app.features.login2.LoginViewModel2 import im.vector.app.features.login2.created.AccountCreatedViewModel @@ -576,4 +577,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(CreatePollViewModel::class) fun createPollViewModelFactory(factory: CreatePollViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(LocationSharingViewModel::class) + fun createLocationSharingViewModelFactory(factory: LocationSharingViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 455f93f973..22eeb7759b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -165,6 +165,7 @@ import im.vector.app.features.html.EventHtmlRenderer import im.vector.app.features.html.PillImageSpan import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.invite.VectorInviteView +import im.vector.app.features.location.LocationSharingMode import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import im.vector.app.features.notifications.NotificationDrawerManager @@ -2219,7 +2220,9 @@ class RoomDetailFragment @Inject constructor( AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher) AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment) AttachmentTypeSelectorView.Type.POLL -> navigator.openCreatePoll(requireContext(), roomDetailArgs.roomId) - AttachmentTypeSelectorView.Type.LOCATION -> Timber.d("On location attachment clicked") + AttachmentTypeSelectorView.Type.LOCATION -> { + navigator.openLocationSharing(requireContext(), roomDetailArgs.roomId, LocationSharingMode.STATIC_SHARING) + } }.exhaustive } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt new file mode 100644 index 0000000000..5139888b08 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 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.location + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class LocationSharingAction : VectorViewModelAction { + data class OnShareLocation(val latitude: Double, val longitude: Double) : LocationSharingAction() +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt new file mode 100644 index 0000000000..fc685815db --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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.location + +import android.content.Context +import android.content.Intent +import android.os.Parcelable +import com.google.android.material.appbar.MaterialToolbar +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.extensions.addFragment +import im.vector.app.core.platform.ToolbarConfigurable +import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.databinding.ActivityLocationSharingBinding +import kotlinx.parcelize.Parcelize + +@Parcelize +data class LocationSharingArgs( + val roomId: String, + val mode: LocationSharingMode +) : Parcelable + +@AndroidEntryPoint +class LocationSharingActivity : VectorBaseActivity(), + ToolbarConfigurable { + + override fun getBinding() = ActivityLocationSharingBinding.inflate(layoutInflater) + + override fun configure(toolbar: MaterialToolbar) { + configureToolbar(toolbar) + } + + override fun initUiAndData() { + val locationSharingArgs: LocationSharingArgs? = intent?.extras?.getParcelable(EXTRA_LOCATION_SHARING_ARGS) + if (locationSharingArgs == null) { + finish() + return + } + configure(views.toolbar) + supportActionBar?.title = getString(locationSharingArgs.mode.titleRes) + + if (isFirstCreation()) { + when (locationSharingArgs.mode) { + LocationSharingMode.STATIC_SHARING -> { + addFragment( + views.fragmentContainer, + LocationSharingFragment::class.java, + locationSharingArgs + ) + } + LocationSharingMode.PREVIEW -> { + } + } + } + } + + companion object { + + private const val EXTRA_LOCATION_SHARING_ARGS = "EXTRA_LOCATION_SHARING_ARGS" + + fun getIntent(context: Context, locationSharingArgs: LocationSharingArgs): Intent { + return Intent(context, LocationSharingActivity::class.java).apply { + putExtra(EXTRA_LOCATION_SHARING_ARGS, locationSharingArgs) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt new file mode 100644 index 0000000000..fd2e48546d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 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.location + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.airbnb.mvrx.activityViewModel +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentLocationSharingBinding +import javax.inject.Inject + +class LocationSharingFragment @Inject constructor() : + VectorBaseFragment() { + + private val viewModel: LocationSharingViewModel by activityViewModel() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding { + return FragmentLocationSharingBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt new file mode 100644 index 0000000000..1032a696ff --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 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.location + +import im.vector.app.core.platform.VectorViewEvents + +sealed class LocationSharingViewEvents : VectorViewEvents { + object Close : LocationSharingViewEvents() +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt new file mode 100644 index 0000000000..6da00f176d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 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.location + +import com.airbnb.mvrx.MavericksViewModelFactory +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.platform.VectorViewModel + +class LocationSharingViewModel @AssistedInject constructor( + @Assisted private val initialState: LocationSharingViewState +) : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: LocationSharingViewState): LocationSharingViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { + } + + override fun handle(action: LocationSharingAction) { + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt new file mode 100644 index 0000000000..d62e568fb2 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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.location + +import androidx.annotation.StringRes +import com.airbnb.mvrx.MavericksState +import im.vector.app.R + +enum class LocationSharingMode(@StringRes val titleRes: Int) { + STATIC_SHARING(R.string.location_activity_title_static_sharing), + PREVIEW(R.string.location_activity_title_preview) +} + +data class LocationSharingViewState( + val roomId: String, + val mode: LocationSharingMode +) : MavericksState { + + constructor(locationSharingArgs: LocationSharingArgs) : this( + roomId = locationSharingArgs.roomId, + mode = locationSharingArgs.mode + ) +} 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 6b035e7d49..16c50daf94 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 @@ -57,6 +57,9 @@ import im.vector.app.features.home.room.detail.search.SearchActivity import im.vector.app.features.home.room.detail.search.SearchArgs import im.vector.app.features.home.room.filtered.FilteredRoomsActivity import im.vector.app.features.invite.InviteUsersToRoomActivity +import im.vector.app.features.location.LocationSharingActivity +import im.vector.app.features.location.LocationSharingArgs +import im.vector.app.features.location.LocationSharingMode import im.vector.app.features.login.LoginActivity import im.vector.app.features.login.LoginConfig import im.vector.app.features.login2.LoginActivity2 @@ -533,6 +536,14 @@ class DefaultNavigator @Inject constructor( context.startActivity(intent) } + override fun openLocationSharing(context: Context, roomId: String, mode: LocationSharingMode) { + val intent = LocationSharingActivity.getIntent( + context, + LocationSharingArgs(roomId = roomId, mode = mode) + ) + context.startActivity(intent) + } + private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) { if (buildTask) { val stackBuilder = TaskStackBuilder.create(context) diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 6778c39a22..2668e10694 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -25,6 +25,7 @@ import androidx.activity.result.ActivityResultLauncher import androidx.core.util.Pair import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.displayname.getBestName +import im.vector.app.features.location.LocationSharingMode import im.vector.app.features.login.LoginConfig import im.vector.app.features.media.AttachmentData import im.vector.app.features.pin.PinMode @@ -149,4 +150,6 @@ interface Navigator { fun openCallTransfer(context: Context, callId: String) fun openCreatePoll(context: Context, roomId: String) + + fun openLocationSharing(context: Context, roomId: String, mode: LocationSharingMode) } diff --git a/vector/src/main/res/layout/activity_location_sharing.xml b/vector/src/main/res/layout/activity_location_sharing.xml new file mode 100755 index 0000000000..b278bb5a1a --- /dev/null +++ b/vector/src/main/res/layout/activity_location_sharing.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/fragment_location_sharing.xml b/vector/src/main/res/layout/fragment_location_sharing.xml new file mode 100644 index 0000000000..77d9ef65f8 --- /dev/null +++ b/vector/src/main/res/layout/fragment_location_sharing.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 38c7d355c3..0f26861d36 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3702,4 +3702,8 @@ Poll ended Remove poll Are you sure you want to remove this poll? You won\'t be able to recover it once removed. + + + Share location + Location From 824e713c51c5aa5b89a85ed5e4c105f5e76a4ba8 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 15 Dec 2021 13:57:43 +0300 Subject: [PATCH 003/222] Add mapview to the layout. --- build.gradle | 2 ++ vector/build.gradle | 3 +++ .../location/LocationSharingFragment.kt | 19 +++++++++++++++++++ .../res/layout/fragment_location_sharing.xml | 5 +++++ 4 files changed, 29 insertions(+) diff --git a/build.gradle b/build.gradle index e17f357905..29c3e61a44 100644 --- a/build.gradle +++ b/build.gradle @@ -61,6 +61,8 @@ allprojects { groups.jitsi.group.each { includeGroup it } } } + // TODO. MapTiler + mavenCentral() google { content { groups.google.regex.each { includeGroupByRegex it } diff --git a/vector/build.gradle b/vector/build.gradle index a578fdb52f..c3dd6ba50c 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -486,6 +486,9 @@ dependencies { } implementation 'commons-codec:commons-codec:1.15' + // MapTiler + implementation 'org.maplibre.gl:android-sdk:9.5.2' + // TESTS testImplementation libs.tests.junit diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index fd2e48546d..7c59972871 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -21,6 +21,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.airbnb.mvrx.activityViewModel +import com.mapbox.mapboxsdk.Mapbox +import im.vector.app.BuildConfig import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLocationSharingBinding import javax.inject.Inject @@ -34,7 +36,24 @@ class LocationSharingFragment @Inject constructor() : return FragmentLocationSharingBinding.inflate(inflater, container, false) } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // Initialize Mapbox before inflating mapView + Mapbox.getInstance(requireContext()) + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + initMapView(savedInstanceState) + } + + private fun initMapView(savedInstanceState: Bundle?) { + val key = BuildConfig.mapTilerKey + val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=${key}" + views.mapView.onCreate(savedInstanceState) + views.mapView.getMapAsync { map -> + map.setStyle(styleUrl) + } } } diff --git a/vector/src/main/res/layout/fragment_location_sharing.xml b/vector/src/main/res/layout/fragment_location_sharing.xml index 77d9ef65f8..6399b41796 100644 --- a/vector/src/main/res/layout/fragment_location_sharing.xml +++ b/vector/src/main/res/layout/fragment_location_sharing.xml @@ -3,4 +3,9 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + \ No newline at end of file From 5904a5955fed630169ee8ee669407e2412204e6c Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 15 Dec 2021 21:07:16 +0300 Subject: [PATCH 004/222] Show and track the current location of the user on map. --- vector/build.gradle | 1 + .../im/vector/app/core/di/FragmentModule.kt | 6 ++ .../location/LocationSharingFragment.kt | 102 +++++++++++++++++- .../app/features/location/LocationTracker.kt | 80 ++++++++++++++ .../src/main/res/drawable/bg_map_user_pin.xml | 10 ++ .../res/layout/fragment_location_sharing.xml | 38 +++++++ vector/src/main/res/values/strings.xml | 2 + 7 files changed, 235 insertions(+), 4 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationTracker.kt create mode 100644 vector/src/main/res/drawable/bg_map_user_pin.xml diff --git a/vector/build.gradle b/vector/build.gradle index c3dd6ba50c..197349f0f1 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -488,6 +488,7 @@ dependencies { // MapTiler implementation 'org.maplibre.gl:android-sdk:9.5.2' + implementation 'org.maplibre.gl:android-plugin-annotation-v9:1.0.0' // TESTS diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index ff84a46dab..3314c0565e 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -61,6 +61,7 @@ import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment import im.vector.app.features.home.room.detail.RoomDetailFragment import im.vector.app.features.home.room.detail.search.SearchFragment import im.vector.app.features.home.room.list.RoomListFragment +import im.vector.app.features.location.LocationSharingFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment import im.vector.app.features.login.LoginGenericTextInputFormFragment @@ -855,4 +856,9 @@ interface FragmentModule { @IntoMap @FragmentKey(CreatePollFragment::class) fun bindCreatePollFragment(fragment: CreatePollFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(LocationSharingFragment::class) + fun bindLocationSharingFragment(fragment: LocationSharingFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index 7c59972871..390d1aafa5 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -16,22 +16,55 @@ package im.vector.app.features.location +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.content.ContextCompat import com.airbnb.mvrx.activityViewModel +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition import com.mapbox.mapboxsdk.Mapbox +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.maps.Style +import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager +import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions +import com.mapbox.mapboxsdk.style.layers.Property import im.vector.app.BuildConfig +import im.vector.app.R +import im.vector.app.core.glide.GlideApp import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLocationSharingBinding +import im.vector.app.features.home.AvatarRenderer +import org.billcarsonfr.jsonviewer.Utils +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject -class LocationSharingFragment @Inject constructor() : - VectorBaseFragment() { +class LocationSharingFragment @Inject constructor( + private val locationTracker: LocationTracker, + private val session: Session, + private val avatarRenderer: AvatarRenderer +) : VectorBaseFragment(), LocationTracker.Callback { + + init { + locationTracker.callback = this + } private val viewModel: LocationSharingViewModel by activityViewModel() + private val glideRequests by lazy { + GlideApp.with(this) + } + + private var map: MapboxMap? = null + private var symbolManager: SymbolManager? = null + private var lastZoomValue: Double = -1.0 + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding { return FragmentLocationSharingBinding.inflate(inflater, container, false) } @@ -48,12 +81,73 @@ class LocationSharingFragment @Inject constructor() : initMapView(savedInstanceState) } + override fun onDestroyView() { + super.onDestroyView() + locationTracker.stop() + } + private fun initMapView(savedInstanceState: Bundle?) { val key = BuildConfig.mapTilerKey - val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=${key}" + val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=$key" views.mapView.onCreate(savedInstanceState) views.mapView.getMapAsync { map -> - map.setStyle(styleUrl) + map.setStyle(styleUrl) { style -> + addUserPinToMap(style) + this.symbolManager = SymbolManager(views.mapView, map, style) + this.map = map + // All set, start location tracker + locationTracker.start() + } } } + + private fun addUserPinToMap(style: Style) { + session.getUser(session.myUserId)?.toMatrixItem()?.let { + val size = Utils.dpToPx(44, requireContext()) + avatarRenderer.render(glideRequests, it, object : CustomTarget(size, size) { + override fun onResourceReady(resource: Drawable, transition: Transition?) { + val bgUserPin = ContextCompat.getDrawable(requireActivity(), R.drawable.bg_map_user_pin)!! + val layerDrawable = LayerDrawable(arrayOf(bgUserPin, resource)) + val horizontalInset = Utils.dpToPx(4, requireContext()) + val topInset = Utils.dpToPx(4, requireContext()) + val bottomInset = Utils.dpToPx(8, requireContext()) + layerDrawable.setLayerInset(1, horizontalInset, topInset, horizontalInset, bottomInset) + + style.addImage( + USER_PIN_NAME, + layerDrawable + ) + } + + override fun onLoadCleared(placeholder: Drawable?) { + // Is it possible? Put placeholder instead? + } + }) + } + } + + override fun onLocationUpdate(latitude: Double, longitude: Double) { + lastZoomValue = if (lastZoomValue == -1.0) INITIAL_ZOOM else map?.cameraPosition?.zoom ?: INITIAL_ZOOM + + val latLng = LatLng(latitude, longitude) + + map?.cameraPosition = CameraPosition.Builder() + .target(latLng) + .zoom(lastZoomValue) + .build() + + symbolManager?.deleteAll() + + symbolManager?.create( + SymbolOptions() + .withLatLng(latLng) + .withIconImage(USER_PIN_NAME) + .withIconAnchor(Property.ICON_ANCHOR_BOTTOM) + ) + } + + companion object { + const val INITIAL_ZOOM = 12.0 + const val USER_PIN_NAME = "USER_PIN_NAME" + } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt new file mode 100644 index 0000000000..3cf2689aee --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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.location + +import android.content.Context +import android.location.Location +import android.location.LocationListener +import android.location.LocationManager +import timber.log.Timber +import javax.inject.Inject + +class LocationTracker @Inject constructor( + private val context: Context) : LocationListener { + + interface Callback { + fun onLocationUpdate(latitude: Double, longitude: Double) + } + + private var locationManager: LocationManager? = null + var callback: Callback? = null + + fun start() { + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as? LocationManager + + locationManager?.let { + val isGpsEnabled = it.isProviderEnabled(LocationManager.GPS_PROVIDER) + val isNetworkEnabled = it.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + + val provider = when { + isGpsEnabled -> LocationManager.GPS_PROVIDER + isNetworkEnabled -> LocationManager.NETWORK_PROVIDER + else -> { + Timber.v("## LocationTracker. There is no location provider available") + return + } + } + + // Send last known location without waiting location updates + it.getLastKnownLocation(provider)?.let { lastKnownLocation -> + callback?.onLocationUpdate(lastKnownLocation.latitude, lastKnownLocation.longitude) + } + + it.requestLocationUpdates( + provider, + MIN_TIME_MILLIS_TO_UPDATE, + MIN_DISTANCE_METERS_TO_UPDATE, + this + ) + } ?: run { + Timber.v("## LocationTracker. LocationManager is not available") + } + } + + fun stop() { + locationManager?.removeUpdates(this) + } + + override fun onLocationChanged(location: Location) { + callback?.onLocationUpdate(location.latitude, location.longitude) + } + + companion object { + const val MIN_TIME_MILLIS_TO_UPDATE = 1 * 60 * 1000L // every 1 minute + const val MIN_DISTANCE_METERS_TO_UPDATE = 10f + } +} diff --git a/vector/src/main/res/drawable/bg_map_user_pin.xml b/vector/src/main/res/drawable/bg_map_user_pin.xml new file mode 100644 index 0000000000..148d3cfa29 --- /dev/null +++ b/vector/src/main/res/drawable/bg_map_user_pin.xml @@ -0,0 +1,10 @@ + + + diff --git a/vector/src/main/res/layout/fragment_location_sharing.xml b/vector/src/main/res/layout/fragment_location_sharing.xml index 6399b41796..bc587dc182 100644 --- a/vector/src/main/res/layout/fragment_location_sharing.xml +++ b/vector/src/main/res/layout/fragment_location_sharing.xml @@ -1,5 +1,6 @@ @@ -8,4 +9,41 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 0f26861d36..166f25c053 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3706,4 +3706,6 @@ Share location Location + Share location + Share location From 6495bd9e5ed373c33047a4135ec11d469cac8ecb Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 17 Dec 2021 15:09:02 +0300 Subject: [PATCH 005/222] Send location event. --- .../room/model/message/LocationInfo.kt | 22 +++--------- .../model/message/MessageLocationContent.kt | 8 ++--- .../sdk/api/session/room/send/SendService.kt | 8 +++++ .../session/room/send/DefaultSendService.kt | 6 ++++ .../room/send/LocalEchoEventFactory.kt | 35 +++++++++++++++++++ .../app/features/location/LocationData.kt | 24 +++++++++++++ .../location/LocationSharingAction.kt | 3 +- .../location/LocationSharingFragment.kt | 28 +++++++++++++-- .../location/LocationSharingViewEvents.kt | 1 + .../location/LocationSharingViewModel.kt | 29 ++++++++++++++- .../location/LocationSharingViewState.kt | 3 +- .../app/features/location/LocationTracker.kt | 6 ++-- vector/src/main/res/values/strings.xml | 2 ++ 13 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationData.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt index a76c3c5b64..5110926294 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt @@ -18,29 +18,17 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class LocationInfo( /** - * The URL to the thumbnail of the file. Only present if the thumbnail is unencrypted. + * Required. Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location. */ - @Json(name = "thumbnail_url") val thumbnailUrl: String? = null, + @Json(name = "uri") val geoUri: String? = null, /** - * Metadata about the image referred to in thumbnail_url. + * Required. A description of the location e.g. 'Big Ben, London, UK', or some kind + * of content description for accessibility e.g. 'location attachment'. */ - @Json(name = "thumbnail_info") val thumbnailInfo: ThumbnailInfo? = null, - - /** - * Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted. - */ - @Json(name = "thumbnail_file") val thumbnailFile: EncryptedFileInfo? = null + @Json(name = "description") val description: String? = null ) - -/** - * Get the url of the encrypted thumbnail or of the thumbnail - */ -fun LocationInfo.getThumbnailUrl(): String? { - return thumbnailFile?.url ?: thumbnailUrl -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt index 6881c09924..9571cc4280 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt @@ -26,7 +26,7 @@ data class MessageLocationContent( /** * Required. Must be 'm.location'. */ - @Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String, + @Json(name = MessageContent.MSG_TYPE_JSON_KEY) override val msgType: String = MessageType.MSGTYPE_LOCATION, /** * Required. A description of the location e.g. 'Big Ben, London, UK', or some kind @@ -35,14 +35,14 @@ data class MessageLocationContent( @Json(name = "body") override val body: String, /** - * Required. A geo URI representing this location. + * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location. */ @Json(name = "geo_uri") val geoUri: String, /** - * + * See https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md */ - @Json(name = "info") val locationInfo: LocationInfo? = null, + @Json(name = "org.matrix.msc3488.location") val locationInfo: LocationInfo? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null 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 5b387c3413..7983ad7068 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 @@ -122,6 +122,14 @@ interface SendService { */ fun resendMediaMessage(localEcho: TimelineEvent): Cancelable + /** + * Send a location event to the room + * @param latitude required latitude of the location + * @param longitude required longitude of the location + * @param uncertainty Accuracy of the location in meters + */ + fun sendLocation(latitude: Double, longitude: Double, uncertainty: Double?): Cancelable + /** * Remove this failed message from the timeline * @param localEcho the unsent local echo 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 d3162aef79..dbe4d5eb73 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 @@ -115,6 +115,12 @@ internal class DefaultSendService @AssistedInject constructor( .let { sendEvent(it) } } + override fun sendLocation(latitude: Double, longitude: Double, uncertainty: Double?): Cancelable { + return localEchoEventFactory.createLocationEvent(roomId, latitude, longitude, uncertainty) + .also { createLocalEcho(it) } + .let { sendEvent(it) } + } + override fun redactEvent(event: Event, reason: String?): Cancelable { // TODO manage media/attachements? val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason) 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 85b22628d7..179df22326 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 @@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.message.AudioInfo import org.matrix.android.sdk.api.session.room.model.message.AudioWaveformInfo import org.matrix.android.sdk.api.session.room.model.message.FileInfo import org.matrix.android.sdk.api.session.room.model.message.ImageInfo +import org.matrix.android.sdk.api.session.room.model.message.LocationInfo import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody @@ -39,6 +40,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollConte import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent import org.matrix.android.sdk.api.session.room.model.message.MessageFormat import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent +import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent @@ -194,6 +196,22 @@ internal class LocalEchoEventFactory @Inject constructor( unsignedData = UnsignedData(age = null, transactionId = localId)) } + fun createLocationEvent(roomId: String, + latitude: Double, + longitude: Double, + uncertainty: Double?): Event { + val geoUri = buildGeoUri(latitude, longitude, uncertainty) + val content = MessageLocationContent( + geoUri = geoUri, + body = geoUri, + locationInfo = LocationInfo( + geoUri = geoUri, + description = geoUri + ) + ) + return createMessageEvent(roomId, content) + } + fun createReplaceTextOfReply(roomId: String, eventReplaced: TimelineEvent, originalEvent: TimelineEvent, @@ -463,6 +481,23 @@ internal class LocalEchoEventFactory @Inject constructor( } } + /** + * Returns RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' + * Uncertainty of the location is in meters and not required. + */ + private fun buildGeoUri(latitude: Double, longitude: Double, uncertainty: Double?): String { + return buildString { + append("geo:") + append(latitude) + append(",") + append(longitude) + uncertainty?.let { + append(";") + append(it) + } + } + } + /* * { "content": { diff --git a/vector/src/main/java/im/vector/app/features/location/LocationData.kt b/vector/src/main/java/im/vector/app/features/location/LocationData.kt new file mode 100644 index 0000000000..f85b8713d9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationData.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 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.location + +data class LocationData( + val latitude: Double, + val longitude: Double, + val uncertainty: Double? +) + diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt index 5139888b08..0efaefaa5b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt @@ -19,5 +19,6 @@ package im.vector.app.features.location import im.vector.app.core.platform.VectorViewModelAction sealed class LocationSharingAction : VectorViewModelAction { - data class OnShareLocation(val latitude: Double, val longitude: Double) : LocationSharingAction() + data class OnLocationUpdate(val locationData: LocationData) : LocationSharingAction() + object OnShareLocation : LocationSharingAction() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index 390d1aafa5..8cd86a2356 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -26,6 +26,7 @@ import androidx.core.content.ContextCompat import com.airbnb.mvrx.activityViewModel import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.mapbox.mapboxsdk.Mapbox import com.mapbox.mapboxsdk.camera.CameraPosition import com.mapbox.mapboxsdk.geometry.LatLng @@ -79,6 +80,17 @@ class LocationSharingFragment @Inject constructor( super.onViewCreated(view, savedInstanceState) initMapView(savedInstanceState) + + views.shareLocationContainer.debouncedClicks { + viewModel.handle(LocationSharingAction.OnShareLocation) + } + + viewModel.observeViewEvents { + when (it) { + LocationSharingViewEvents.LocationNotAvailableError -> handleLocationNotAvailableError() + LocationSharingViewEvents.Close -> activity?.finish() + } + } } override fun onDestroyView() { @@ -126,10 +138,10 @@ class LocationSharingFragment @Inject constructor( } } - override fun onLocationUpdate(latitude: Double, longitude: Double) { + override fun onLocationUpdate(locationData: LocationData) { lastZoomValue = if (lastZoomValue == -1.0) INITIAL_ZOOM else map?.cameraPosition?.zoom ?: INITIAL_ZOOM - val latLng = LatLng(latitude, longitude) + val latLng = LatLng(locationData.latitude, locationData.longitude) map?.cameraPosition = CameraPosition.Builder() .target(latLng) @@ -144,10 +156,20 @@ class LocationSharingFragment @Inject constructor( .withIconImage(USER_PIN_NAME) .withIconAnchor(Property.ICON_ANCHOR_BOTTOM) ) + + viewModel.handle(LocationSharingAction.OnLocationUpdate(locationData)) + } + + private fun handleLocationNotAvailableError() { + MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.location_not_available_dialog_title) + .setMessage(R.string.location_not_available_dialog_content) + .setPositiveButton(R.string.ok, null) + .show() } companion object { - const val INITIAL_ZOOM = 12.0 + const val INITIAL_ZOOM = 15.0 const val USER_PIN_NAME = "USER_PIN_NAME" } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt index 1032a696ff..743daaf5e0 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt @@ -20,4 +20,5 @@ import im.vector.app.core.platform.VectorViewEvents sealed class LocationSharingViewEvents : VectorViewEvents { object Close : LocationSharingViewEvents() + object LocationNotAvailableError : LocationSharingViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt index 6da00f176d..4525cac446 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt @@ -23,11 +23,15 @@ import dagger.assisted.AssistedInject import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel +import org.matrix.android.sdk.api.session.Session class LocationSharingViewModel @AssistedInject constructor( - @Assisted private val initialState: LocationSharingViewState + @Assisted private val initialState: LocationSharingViewState, + session: Session ) : VectorViewModel(initialState) { + private val room = session.getRoom(initialState.roomId)!! + @AssistedFactory interface Factory : MavericksAssistedViewModelFactory { override fun create(initialState: LocationSharingViewState): LocationSharingViewModel @@ -37,5 +41,28 @@ class LocationSharingViewModel @AssistedInject constructor( } override fun handle(action: LocationSharingAction) { + when (action) { + is LocationSharingAction.OnLocationUpdate -> handleLocationUpdate(action.locationData) + LocationSharingAction.OnShareLocation -> handleShareLocation() + } + } + + private fun handleShareLocation() = withState { state -> + state.lastKnownLocation?.let { location -> + room.sendLocation( + latitude = location.latitude, + longitude = location.longitude, + uncertainty = location.uncertainty + ) + _viewEvents.post(LocationSharingViewEvents.Close) + } ?: run { + _viewEvents.post(LocationSharingViewEvents.LocationNotAvailableError) + } + } + + private fun handleLocationUpdate(locationData: LocationData) { + setState { + copy(lastKnownLocation = locationData) + } } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt index d62e568fb2..2869929b12 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt @@ -27,7 +27,8 @@ enum class LocationSharingMode(@StringRes val titleRes: Int) { data class LocationSharingViewState( val roomId: String, - val mode: LocationSharingMode + val mode: LocationSharingMode, + val lastKnownLocation: LocationData? = null ) : MavericksState { constructor(locationSharingArgs: LocationSharingArgs) : this( diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt index 3cf2689aee..93993245f8 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -27,7 +27,7 @@ class LocationTracker @Inject constructor( private val context: Context) : LocationListener { interface Callback { - fun onLocationUpdate(latitude: Double, longitude: Double) + fun onLocationUpdate(locationData: LocationData) } private var locationManager: LocationManager? = null @@ -51,7 +51,7 @@ class LocationTracker @Inject constructor( // Send last known location without waiting location updates it.getLastKnownLocation(provider)?.let { lastKnownLocation -> - callback?.onLocationUpdate(lastKnownLocation.latitude, lastKnownLocation.longitude) + callback?.onLocationUpdate(LocationData(lastKnownLocation.latitude, lastKnownLocation.longitude, lastKnownLocation.accuracy.toDouble())) } it.requestLocationUpdates( @@ -70,7 +70,7 @@ class LocationTracker @Inject constructor( } override fun onLocationChanged(location: Location) { - callback?.onLocationUpdate(location.latitude, location.longitude) + callback?.onLocationUpdate(LocationData(location.latitude, location.longitude, location.accuracy.toDouble())) } companion object { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 166f25c053..086469a1fd 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3708,4 +3708,6 @@ Location Share location Share location + Element could not access your location + Element could not access your location. Please try again later. From a0afab45fbc421e86e0647d96fa9aa37a0aec64f Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 27 Dec 2021 14:03:59 +0300 Subject: [PATCH 006/222] Show location preview and allow to share with external apps. --- .../java/im/vector/app/VectorApplication.kt | 4 + .../im/vector/app/core/di/FragmentModule.kt | 6 ++ .../core/utils/ExternalApplicationsUtil.kt | 20 ++++ .../home/room/detail/RoomDetailAction.kt | 4 + .../home/room/detail/RoomDetailFragment.kt | 21 +++- .../home/room/detail/RoomDetailViewEvents.kt | 3 + .../home/room/detail/RoomDetailViewModel.kt | 6 ++ .../timeline/factory/MessageItemFactory.kt | 40 +++++-- .../timeline/helper/LocationPinProvider.kt | 74 +++++++++++++ .../timeline/item/MessageLocationItem.kt | 80 ++++++++++++++ .../app/features/location/LocationData.kt | 49 ++++++++- .../location/LocationPreviewFragment.kt | 85 +++++++++++++++ .../location/LocationSharingActivity.kt | 9 +- .../location/LocationSharingFragment.kt | 102 +++--------------- .../app/features/location/LocationTracker.kt | 1 + .../app/features/location/MapTilerMapView.kt | 92 ++++++++++++++++ .../app/features/location/VectorMapView.kt | 36 +++++++ .../features/navigation/DefaultNavigator.kt | 9 +- .../app/features/navigation/Navigator.kt | 7 +- .../main/res/drawable/ic_share_external.xml | 5 + .../res/layout/fragment_location_preview.xml | 11 ++ .../res/layout/fragment_location_sharing.xml | 2 +- .../res/layout/item_timeline_event_base.xml | 5 + .../item_timeline_event_location_stub.xml | 17 +++ .../main/res/menu/menu_location_preview.xml | 12 +++ vector/src/main/res/values/strings.xml | 1 + 26 files changed, 601 insertions(+), 100 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt create mode 100644 vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt create mode 100644 vector/src/main/java/im/vector/app/features/location/VectorMapView.kt create mode 100644 vector/src/main/res/drawable/ic_share_external.xml create mode 100644 vector/src/main/res/layout/fragment_location_preview.xml create mode 100644 vector/src/main/res/layout/item_timeline_event_location_stub.xml create mode 100644 vector/src/main/res/menu/menu_location_preview.xml diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index 400fb7eb89..52de28a1cf 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -36,6 +36,7 @@ import com.airbnb.epoxy.EpoxyController import com.airbnb.mvrx.Mavericks import com.facebook.stetho.Stetho import com.gabrielittner.threetenbp.LazyThreeTen +import com.mapbox.mapboxsdk.Mapbox import com.vanniktech.emoji.EmojiManager import com.vanniktech.emoji.google.GoogleEmojiProvider import dagger.hilt.android.HiltAndroidApp @@ -195,6 +196,9 @@ class VectorApplication : }) EmojiManager.install(GoogleEmojiProvider()) + + // Initialize Mapbox before inflating mapViews + Mapbox.getInstance(this) } private val startSyncOnFirstStart = object : DefaultLifecycleObserver { diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 3314c0565e..4d70f49186 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -61,6 +61,7 @@ import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment import im.vector.app.features.home.room.detail.RoomDetailFragment import im.vector.app.features.home.room.detail.search.SearchFragment import im.vector.app.features.home.room.list.RoomListFragment +import im.vector.app.features.location.LocationPreviewFragment import im.vector.app.features.location.LocationSharingFragment import im.vector.app.features.login.LoginCaptchaFragment import im.vector.app.features.login.LoginFragment @@ -861,4 +862,9 @@ interface FragmentModule { @IntoMap @FragmentKey(LocationSharingFragment::class) fun bindLocationSharingFragment(fragment: LocationSharingFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(LocationPreviewFragment::class) + fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt index bdaf520ba1..f3138218eb 100644 --- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt +++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt @@ -297,6 +297,26 @@ fun openMedia(activity: Activity, savedMediaPath: String, mimeType: String) { } } +/** + * Open external location + * @param activity the activity + * @param latitude latitude of the location + * @param longitude longitude of the location + */ +fun openLocation(activity: Activity, latitude: Double, longitude: Double) { + val locationUri = buildString { + append("geo:") + append(latitude) + append(",") + append(longitude) + append("?q=") // This is required to drop a pin to the location + append(latitude) + append(",") + append(longitude) + } + openUri(activity, locationUri) +} + fun shareMedia(context: Context, file: File, mediaMimeType: String?) { val mediaUri = try { FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt index f20a32848c..ce04b6812d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt @@ -20,6 +20,7 @@ import android.net.Uri import android.view.View import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.features.call.conference.ConferenceEvent +import im.vector.app.features.location.LocationData import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent @@ -110,4 +111,7 @@ sealed class RoomDetailAction : VectorViewModelAction { // Poll data class EndPoll(val eventId: String) : RoomDetailAction() + + // Location + data class ShowLocation(val locationData: LocationData, val userId: String) : RoomDetailAction() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 22eeb7759b..d530b35c0c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -465,6 +465,7 @@ class RoomDetailFragment @Inject constructor( RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects() is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it) RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement() + is RoomDetailViewEvents.ShowLocation -> handleShowLocationPreview(it) }.exhaustive } @@ -596,6 +597,17 @@ class RoomDetailFragment @Inject constructor( } } + private fun handleShowLocationPreview(viewEvent: RoomDetailViewEvents.ShowLocation) { + navigator + .openLocationSharing( + context = requireContext(), + roomId = roomDetailArgs.roomId, + mode = LocationSharingMode.PREVIEW, + initialLocationData = viewEvent.locationData, + locationOwnerId = viewEvent.userId + ) + } + private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) { val tag = RoomWidgetPermissionBottomSheet::class.java.name val dFrag = childFragmentManager.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet @@ -2221,7 +2233,14 @@ class RoomDetailFragment @Inject constructor( AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment) AttachmentTypeSelectorView.Type.POLL -> navigator.openCreatePoll(requireContext(), roomDetailArgs.roomId) AttachmentTypeSelectorView.Type.LOCATION -> { - navigator.openLocationSharing(requireContext(), roomDetailArgs.roomId, LocationSharingMode.STATIC_SHARING) + navigator + .openLocationSharing( + context = requireContext(), + roomId = roomDetailArgs.roomId, + mode = LocationSharingMode.STATIC_SHARING, + initialLocationData = null, + locationOwnerId = session.myUserId + ) } }.exhaustive } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt index 2e7f2bfd63..de1110dfcb 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt @@ -20,6 +20,7 @@ import android.net.Uri import android.view.View import im.vector.app.core.platform.VectorViewEvents import im.vector.app.features.call.webrtc.WebRtcCall +import im.vector.app.features.location.LocationData import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode @@ -81,4 +82,6 @@ sealed class RoomDetailViewEvents : VectorViewEvents { data class StartChatEffect(val type: ChatEffect) : RoomDetailViewEvents() object StopChatEffects : RoomDetailViewEvents() object RoomReplacementStarted : RoomDetailViewEvents() + + data class ShowLocation(val locationData: LocationData, val userId: String) : RoomDetailViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt index f438c6e1e4..0c67c66af8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt @@ -50,6 +50,7 @@ import im.vector.app.features.home.room.detail.sticker.StickerPickerActionHandle import im.vector.app.features.home.room.detail.timeline.factory.TimelineFactory import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever import im.vector.app.features.home.room.typing.TypingHelper +import im.vector.app.features.location.LocationData import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorDataStore @@ -330,9 +331,14 @@ class RoomDetailViewModel @AssistedInject constructor( _viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true)) } is RoomDetailAction.EndPoll -> handleEndPoll(action.eventId) + is RoomDetailAction.ShowLocation -> handleShowLocation(action.locationData, action.userId) }.exhaustive } + private fun handleShowLocation(locationData: LocationData, userId: String) { + _viewEvents.post(RoomDetailViewEvents.ShowLocation(locationData, userId)) + } + private fun handleJitsiCallJoinStatus(action: RoomDetailAction.UpdateJoinJitsiCallStatus) = withState { state -> if (state.jitsiState.confId == null) { // If jitsi widget is removed while on the call 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 22d282d567..76e8908d2d 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 @@ -37,6 +37,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory import im.vector.app.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider @@ -49,6 +50,8 @@ import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem_ import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem_ import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.app.features.home.room.detail.timeline.item.MessageLocationItem +import im.vector.app.features.home.room.detail.timeline.item.MessageLocationItem_ import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem_ import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceItem @@ -67,6 +70,7 @@ import im.vector.app.features.html.EventHtmlRenderer import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.VectorHtmlCompressor +import im.vector.app.features.location.LocationData import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import me.gujun.android.span.span @@ -82,6 +86,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithF import org.matrix.android.sdk.api.session.room.model.message.MessageEmoteContent import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent +import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessageNoticeContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent @@ -116,7 +121,8 @@ class MessageItemFactory @Inject constructor( private val pillsPostProcessorFactory: PillsPostProcessor.Factory, private val spanUtils: SpanUtils, private val session: Session, - private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker) { + private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker, + private val locationPinProvider: LocationPinProvider) { // TODO inject this properly? private var roomId: String = "" @@ -168,16 +174,36 @@ class MessageItemFactory @Inject constructor( } } is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessagePollContent -> buildPollContent(messageContent, informationData, highlight, callback, attributes) + is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes) + is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, callback, attributes) else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes) } } - private fun buildPollContent(pollContent: MessagePollContent, - informationData: MessageInformationData, - highlight: Boolean, - callback: TimelineEventController.Callback?, - attributes: AbsMessageItem.Attributes): PollItem? { + private fun buildLocationItem(locationContent: MessageLocationContent, + informationData: MessageInformationData, + highlight: Boolean, + callback: TimelineEventController.Callback?, + attributes: AbsMessageItem.Attributes): MessageLocationItem? { + + val geoUri = locationContent.locationInfo?.geoUri ?: locationContent.geoUri + val locationData = LocationData.create(geoUri) + + return MessageLocationItem_() + .attributes(attributes) + .locationData(locationData) + .userId(informationData.senderId) + .locationPinProvider(locationPinProvider) + .highlighted(highlight) + .leftGuideline(avatarSizeProvider.leftGuideline) + .callback(callback) + } + + private fun buildPollItem(pollContent: MessagePollContent, + informationData: MessageInformationData, + highlight: Boolean, + callback: TimelineEventController.Callback?, + attributes: AbsMessageItem.Attributes): PollItem? { val optionViewStates = mutableListOf() val pollResponseSummary = informationData.pollResponseAggregatedSummary diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt new file mode 100644 index 0000000000..92a4bb8473 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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.timeline.helper + +import android.content.Context +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable +import androidx.core.content.ContextCompat +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition +import im.vector.app.R +import im.vector.app.core.glide.GlideApp +import im.vector.app.features.home.AvatarRenderer +import org.billcarsonfr.jsonviewer.Utils +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.util.toMatrixItem +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class LocationPinProvider @Inject constructor( + private val context: Context, + private val session: Session, + private val avatarRenderer: AvatarRenderer +) { + private val cache = mutableMapOf() + + private val glideRequests by lazy { + GlideApp.with(context) + } + + fun create(userId: String, callback: (Drawable) -> Unit) { + if (cache.contains(userId)) { + callback(cache[userId]!!) + return + } + + session.getUser(userId)?.toMatrixItem()?.let { + val size = Utils.dpToPx(44, context) + avatarRenderer.render(glideRequests, it, object : CustomTarget(size, size) { + override fun onResourceReady(resource: Drawable, transition: Transition?) { + val bgUserPin = ContextCompat.getDrawable(context, R.drawable.bg_map_user_pin)!! + val layerDrawable = LayerDrawable(arrayOf(bgUserPin, resource)) + val horizontalInset = Utils.dpToPx(4, context) + val topInset = Utils.dpToPx(4, context) + val bottomInset = Utils.dpToPx(8, context) + layerDrawable.setLayerInset(1, horizontalInset, topInset, horizontalInset, bottomInset) + + cache[userId] = layerDrawable + + callback(layerDrawable) + } + + override fun onLoadCleared(placeholder: Drawable?) { + // Is it possible? Put placeholder instead? + } + }) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt new file mode 100644 index 0000000000..d4995d3fad --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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.timeline.item + +import androidx.constraintlayout.widget.ConstraintLayout +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.onClick +import im.vector.app.features.home.room.detail.RoomDetailAction +import im.vector.app.features.home.room.detail.timeline.TimelineEventController +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import im.vector.app.features.location.LocationData +import im.vector.app.features.location.MapTilerMapView +import im.vector.app.features.location.VectorMapListener + +@EpoxyModelClass(layout = R.layout.item_timeline_event_base) +abstract class MessageLocationItem : AbsMessageItem() { + + @EpoxyAttribute + var callback: TimelineEventController.Callback? = null + + @EpoxyAttribute + var locationData: LocationData? = null + + @EpoxyAttribute + var userId: String? = null + + @EpoxyAttribute + var locationPinProvider: LocationPinProvider? = null + + override fun bind(holder: Holder) { + super.bind(holder) + renderSendState(holder.mapViewContainer, null) + + val location = locationData ?: return + val locationOwnerId = userId ?: return + + holder.mapView.initialize(object : VectorMapListener { + override fun onMapReady() { + holder.mapView.zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) + + locationPinProvider?.create(locationOwnerId) { pinDrawable -> + holder.mapView.addPinToMap(locationOwnerId, pinDrawable) + holder.mapView.updatePinLocation(locationOwnerId, location.latitude, location.longitude) + } + + holder.mapView.onClick { + callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(location, locationOwnerId)) + } + } + }) + } + + override fun getViewType() = STUB_ID + + class Holder : AbsMessageItem.Holder(STUB_ID) { + val mapViewContainer by bind(R.id.mapViewContainer) + val mapView by bind(R.id.mapView) + } + + companion object { + private const val STUB_ID = R.id.messageContentLocationStub + private const val INITIAL_ZOOM = 15.0 + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationData.kt b/vector/src/main/java/im/vector/app/features/location/LocationData.kt index f85b8713d9..874e159e80 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationData.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationData.kt @@ -16,9 +16,56 @@ package im.vector.app.features.location +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class LocationData( val latitude: Double, val longitude: Double, val uncertainty: Double? -) +) : Parcelable { + + fun toGeoUri(): String { + return buildString { + append("geo:") + append(latitude) + append(",") + append(longitude) + append("?q=") + append(latitude) + append(",") + append(longitude) + } + } + + companion object { + + /** + * Creates location data from geo uri + * @param geoUri geo:latitude,longitude;uncertainty + * @return location data or null if geo uri is not valid + */ + fun create(geoUri: String): LocationData? { + val geoParts = geoUri + .split(":") + .takeIf { it.firstOrNull() == "geo" } + ?.getOrNull(1) + ?.split(",") + + val latitude = geoParts?.firstOrNull() + val geoTailParts = geoParts?.getOrNull(1)?.split(";") + val longitude = geoTailParts?.firstOrNull() + val uncertainty = geoTailParts?.getOrNull(1) + + return if (latitude != null && longitude != null) { + LocationData( + latitude = latitude.toDouble(), + longitude = longitude.toDouble(), + uncertainty = uncertainty?.toDouble() + ) + } else null + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt new file mode 100644 index 0000000000..e13456dbdc --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 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.location + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentLocationPreviewBinding +import javax.inject.Inject +import com.airbnb.mvrx.args +import im.vector.app.R +import im.vector.app.core.utils.openLocation +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider +import org.matrix.android.sdk.api.extensions.tryOrNull + +class LocationPreviewFragment @Inject constructor( + private val locationPinProvider: LocationPinProvider +) : VectorBaseFragment(), VectorMapListener { + + private val args: LocationSharingArgs by args() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationPreviewBinding { + return FragmentLocationPreviewBinding.inflate(layoutInflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + views.mapView.initialize(this) + } + + override fun getMenuRes() = R.menu.menu_location_preview + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.share_external -> { + onShareLocationExternal() + return true + } + } + return super.onOptionsItemSelected(item) + } + + private fun onShareLocationExternal() { + val location = args.initialLocationData ?: return + openLocation(requireActivity(), location.latitude, location.longitude) + } + + override fun onMapReady() { + val location = args.initialLocationData ?: return + val userId = args.locationOwnerId + + locationPinProvider.create(userId) { pinDrawable -> + views.mapView.apply { + zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) + deleteAllPins() + addPinToMap(userId, pinDrawable) + updatePinLocation(userId, location.latitude, location.longitude) + } + } + } + + companion object { + const val INITIAL_ZOOM = 15.0 + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt index fc685815db..6a200435dc 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingActivity.kt @@ -30,7 +30,9 @@ import kotlinx.parcelize.Parcelize @Parcelize data class LocationSharingArgs( val roomId: String, - val mode: LocationSharingMode + val mode: LocationSharingMode, + val initialLocationData: LocationData?, + val locationOwnerId: String ) : Parcelable @AndroidEntryPoint @@ -62,6 +64,11 @@ class LocationSharingActivity : VectorBaseActivity { + addFragment( + views.fragmentContainer, + LocationPreviewFragment::class.java, + locationSharingArgs + ) } } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index 8cd86a2356..c7c4c0fed1 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -16,41 +16,24 @@ package im.vector.app.features.location -import android.graphics.drawable.Drawable -import android.graphics.drawable.LayerDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.content.ContextCompat import com.airbnb.mvrx.activityViewModel -import com.bumptech.glide.request.target.CustomTarget -import com.bumptech.glide.request.transition.Transition import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.mapbox.mapboxsdk.Mapbox -import com.mapbox.mapboxsdk.camera.CameraPosition -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.maps.Style -import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager -import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions -import com.mapbox.mapboxsdk.style.layers.Property -import im.vector.app.BuildConfig import im.vector.app.R -import im.vector.app.core.glide.GlideApp import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLocationSharingBinding -import im.vector.app.features.home.AvatarRenderer -import org.billcarsonfr.jsonviewer.Utils +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject class LocationSharingFragment @Inject constructor( private val locationTracker: LocationTracker, private val session: Session, - private val avatarRenderer: AvatarRenderer -) : VectorBaseFragment(), LocationTracker.Callback { + private val locationPinProvider: LocationPinProvider +) : VectorBaseFragment(), LocationTracker.Callback, VectorMapListener { init { locationTracker.callback = this @@ -58,28 +41,16 @@ class LocationSharingFragment @Inject constructor( private val viewModel: LocationSharingViewModel by activityViewModel() - private val glideRequests by lazy { - GlideApp.with(this) - } - - private var map: MapboxMap? = null - private var symbolManager: SymbolManager? = null private var lastZoomValue: Double = -1.0 override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding { return FragmentLocationSharingBinding.inflate(inflater, container, false) } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // Initialize Mapbox before inflating mapView - Mapbox.getInstance(requireContext()) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - initMapView(savedInstanceState) + views.mapView.initialize(this) views.shareLocationContainer.debouncedClicks { viewModel.handle(LocationSharingAction.OnShareLocation) @@ -98,64 +69,23 @@ class LocationSharingFragment @Inject constructor( locationTracker.stop() } - private fun initMapView(savedInstanceState: Bundle?) { - val key = BuildConfig.mapTilerKey - val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=$key" - views.mapView.onCreate(savedInstanceState) - views.mapView.getMapAsync { map -> - map.setStyle(styleUrl) { style -> - addUserPinToMap(style) - this.symbolManager = SymbolManager(views.mapView, map, style) - this.map = map - // All set, start location tracker - locationTracker.start() - } - } - } - - private fun addUserPinToMap(style: Style) { - session.getUser(session.myUserId)?.toMatrixItem()?.let { - val size = Utils.dpToPx(44, requireContext()) - avatarRenderer.render(glideRequests, it, object : CustomTarget(size, size) { - override fun onResourceReady(resource: Drawable, transition: Transition?) { - val bgUserPin = ContextCompat.getDrawable(requireActivity(), R.drawable.bg_map_user_pin)!! - val layerDrawable = LayerDrawable(arrayOf(bgUserPin, resource)) - val horizontalInset = Utils.dpToPx(4, requireContext()) - val topInset = Utils.dpToPx(4, requireContext()) - val bottomInset = Utils.dpToPx(8, requireContext()) - layerDrawable.setLayerInset(1, horizontalInset, topInset, horizontalInset, bottomInset) - - style.addImage( - USER_PIN_NAME, - layerDrawable - ) - } - - override fun onLoadCleared(placeholder: Drawable?) { - // Is it possible? Put placeholder instead? - } - }) + override fun onMapReady() { + locationPinProvider.create(session.myUserId) { + views.mapView.addPinToMap( + pinId = USER_PIN_NAME, + image = it, + ) + // All set, start location tracker + locationTracker.start() } } override fun onLocationUpdate(locationData: LocationData) { - lastZoomValue = if (lastZoomValue == -1.0) INITIAL_ZOOM else map?.cameraPosition?.zoom ?: INITIAL_ZOOM + lastZoomValue = if (lastZoomValue == -1.0) INITIAL_ZOOM else views.mapView.getCurrentZoom() ?: INITIAL_ZOOM - val latLng = LatLng(locationData.latitude, locationData.longitude) - - map?.cameraPosition = CameraPosition.Builder() - .target(latLng) - .zoom(lastZoomValue) - .build() - - symbolManager?.deleteAll() - - symbolManager?.create( - SymbolOptions() - .withLatLng(latLng) - .withIconImage(USER_PIN_NAME) - .withIconAnchor(Property.ICON_ANCHOR_BOTTOM) - ) + views.mapView.zoomToLocation(locationData.latitude, locationData.longitude, lastZoomValue) + views.mapView.deleteAllPins() + views.mapView.updatePinLocation(USER_PIN_NAME, locationData.latitude, locationData.longitude) viewModel.handle(LocationSharingAction.OnLocationUpdate(locationData)) } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt index 93993245f8..0ea1e6810b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -67,6 +67,7 @@ class LocationTracker @Inject constructor( fun stop() { locationManager?.removeUpdates(this) + callback = null } override fun onLocationChanged(location: Location) { diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt new file mode 100644 index 0000000000..627b9e5ec3 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 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.location + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import com.mapbox.mapboxsdk.Mapbox +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.maps.Style +import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager +import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions +import com.mapbox.mapboxsdk.style.layers.Property +import im.vector.app.BuildConfig + +class MapTilerMapView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : MapView(context, attrs, defStyleAttr), VectorMapView { + + private var map: MapboxMap? = null + private var symbolManager: SymbolManager? = null + private var style: Style? = null + + override fun initialize(listener: VectorMapListener) { + getMapAsync { map -> + map.setStyle(styleUrl) { style -> + this.symbolManager = SymbolManager(this, map, style) + this.map = map + this.style = style + listener.onMapReady() + } + } + } + + override fun addPinToMap(pinId: String, image: Drawable) { + style?.addImage(pinId, image) + } + + override fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) { + symbolManager?.create( + SymbolOptions() + .withLatLng(LatLng(latitude, longitude)) + .withIconImage(pinId) + .withIconAnchor(Property.ICON_ANCHOR_BOTTOM) + ) + } + + override fun deleteAllPins() { + symbolManager?.deleteAll() + } + + override fun zoomToLocation(latitude: Double, longitude: Double, zoom: Double) { + map?.cameraPosition = CameraPosition.Builder() + .target(LatLng(latitude, longitude)) + .zoom(zoom) + .build() + } + + override fun getCurrentZoom(): Double? { + return map?.cameraPosition?.zoom + } + + override fun onClick(callback: () -> Unit) { + map?.addOnMapClickListener { + callback() + true + } + } + + companion object { + private const val styleUrl = "https://api.maptiler.com/maps/streets/style.json?key=${BuildConfig.mapTilerKey}" + } +} diff --git a/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt b/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt new file mode 100644 index 0000000000..5dbeced175 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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.location + +import android.graphics.drawable.Drawable + +interface VectorMapListener { + fun onMapReady() +} + +interface VectorMapView { + fun initialize(listener: VectorMapListener) + + fun addPinToMap(pinId: String, image: Drawable) + fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) + fun deleteAllPins() + + fun zoomToLocation(latitude: Double, longitude: Double, zoom: Double) + fun getCurrentZoom(): Double? + + fun onClick(callback: () -> Unit) +} 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 16c50daf94..fb923dabb2 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 @@ -57,6 +57,7 @@ import im.vector.app.features.home.room.detail.search.SearchActivity import im.vector.app.features.home.room.detail.search.SearchArgs import im.vector.app.features.home.room.filtered.FilteredRoomsActivity import im.vector.app.features.invite.InviteUsersToRoomActivity +import im.vector.app.features.location.LocationData import im.vector.app.features.location.LocationSharingActivity import im.vector.app.features.location.LocationSharingArgs import im.vector.app.features.location.LocationSharingMode @@ -536,10 +537,14 @@ class DefaultNavigator @Inject constructor( context.startActivity(intent) } - override fun openLocationSharing(context: Context, roomId: String, mode: LocationSharingMode) { + override fun openLocationSharing(context: Context, + roomId: String, + mode: LocationSharingMode, + initialLocationData: LocationData?, + locationOwnerId: String) { val intent = LocationSharingActivity.getIntent( context, - LocationSharingArgs(roomId = roomId, mode = mode) + LocationSharingArgs(roomId = roomId, mode = mode, initialLocationData = initialLocationData, locationOwnerId = locationOwnerId) ) context.startActivity(intent) } diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 2668e10694..06f38b381d 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -25,6 +25,7 @@ import androidx.activity.result.ActivityResultLauncher import androidx.core.util.Pair import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.displayname.getBestName +import im.vector.app.features.location.LocationData import im.vector.app.features.location.LocationSharingMode import im.vector.app.features.login.LoginConfig import im.vector.app.features.media.AttachmentData @@ -151,5 +152,9 @@ interface Navigator { fun openCreatePoll(context: Context, roomId: String) - fun openLocationSharing(context: Context, roomId: String, mode: LocationSharingMode) + fun openLocationSharing(context: Context, + roomId: String, + mode: LocationSharingMode, + initialLocationData: LocationData?, + locationOwnerId: String) } diff --git a/vector/src/main/res/drawable/ic_share_external.xml b/vector/src/main/res/drawable/ic_share_external.xml new file mode 100644 index 0000000000..c4b78c8a83 --- /dev/null +++ b/vector/src/main/res/drawable/ic_share_external.xml @@ -0,0 +1,5 @@ + + + diff --git a/vector/src/main/res/layout/fragment_location_preview.xml b/vector/src/main/res/layout/fragment_location_preview.xml new file mode 100644 index 0000000000..ae3e8f1778 --- /dev/null +++ b/vector/src/main/res/layout/fragment_location_preview.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/fragment_location_sharing.xml b/vector/src/main/res/layout/fragment_location_sharing.xml index bc587dc182..8122b5def5 100644 --- a/vector/src/main/res/layout/fragment_location_sharing.xml +++ b/vector/src/main/res/layout/fragment_location_sharing.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml index 5a04acf677..6360b287d0 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -130,6 +130,11 @@ style="@style/TimelineContentStubBaseParams" android:layout="@layout/item_timeline_event_poll" /> + + + + + + + diff --git a/vector/src/main/res/menu/menu_location_preview.xml b/vector/src/main/res/menu/menu_location_preview.xml new file mode 100644 index 0000000000..2616674b8a --- /dev/null +++ b/vector/src/main/res/menu/menu_location_preview.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 086469a1fd..e5fe5ad5c7 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3710,4 +3710,5 @@ Share location Element could not access your location Element could not access your location. Please try again later. + Open with From ccd4396336927dc165374743e60e3ef285121788 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 27 Dec 2021 14:04:36 +0300 Subject: [PATCH 007/222] Allow to reply location messages. --- .../BottomSheetMessagePreviewItem.kt | 27 +++++++++++++++++++ .../action/MessageActionsEpoxyController.kt | 13 ++++++++- .../action/MessageActionsViewModel.kt | 5 ++-- .../item_bottom_sheet_message_preview.xml | 13 +++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index eef057efd4..efa4702532 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -30,10 +30,16 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.util.preventMutation import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess +import im.vector.app.features.location.LocationData +import im.vector.app.features.location.MapTilerMapView +import im.vector.app.features.location.VectorMapListener import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.session.room.model.message.LocationInfo +import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.util.MatrixItem /** @@ -66,6 +72,12 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel + holder.mapView.initialize(object : VectorMapListener { + override fun onMapReady() { + holder.mapView.zoomToLocation(location.latitude, location.longitude, 15.0) + locationPinProvider?.create(matrixItem.id) { pinDrawable -> + holder.mapView.addPinToMap(matrixItem.id, pinDrawable) + holder.mapView.updatePinLocation(matrixItem.id, location.latitude, location.longitude) + } + } + }) + } } override fun unbind(holder: Holder) { @@ -105,5 +131,6 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel(R.id.bottom_sheet_message_preview_body_details) val timestamp by bind(R.id.bottom_sheet_message_preview_timestamp) val imagePreview by bind(R.id.bottom_sheet_message_preview_image) + val mapView by bind(R.id.bottom_sheet_message_preview_location) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 3826c4cbad..0bd4f1bf21 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -33,14 +33,19 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.format.EventDetailsFormatter +import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.home.room.detail.timeline.tools.linkify import im.vector.app.features.html.SpanUtils +import im.vector.app.features.location.LocationData import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.send.SendState import javax.inject.Inject @@ -56,7 +61,8 @@ class MessageActionsEpoxyController @Inject constructor( private val errorFormatter: ErrorFormatter, private val spanUtils: SpanUtils, private val eventDetailsFormatter: EventDetailsFormatter, - private val dateFormatter: VectorDateFormatter + private val dateFormatter: VectorDateFormatter, + private val locationPinProvider: LocationPinProvider ) : TypedEpoxyController() { var listener: MessageActionsEpoxyControllerListener? = null @@ -68,6 +74,9 @@ class MessageActionsEpoxyController @Inject constructor( val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL) val body = state.messageBody.linkify(host.listener) val bindingOptions = spanUtils.getBindingOptions(body) + val locationData = state.timelineEvent()?.root?.getClearContent()?.toModel(catchError = true)?.let { + LocationData.create(it.locationInfo?.geoUri ?: it.geoUri) + } bottomSheetMessagePreviewItem { id("preview") avatarRenderer(host.avatarRenderer) @@ -80,6 +89,8 @@ class MessageActionsEpoxyController @Inject constructor( body(body) bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)) time(formattedDate) + locationData(locationData) + locationPinProvider(host.locationPinProvider) } // Send state diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index ff7d555ee3..2b3d391634 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -424,8 +424,9 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted MessageType.MSGTYPE_VIDEO, MessageType.MSGTYPE_AUDIO, MessageType.MSGTYPE_FILE, - MessageType.MSGTYPE_POLL_START -> true - else -> false + MessageType.MSGTYPE_POLL_START, + MessageType.MSGTYPE_LOCATION -> true + else -> false } } diff --git a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml index 771d4d10f0..1959cfc3ba 100644 --- a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml +++ b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml @@ -103,4 +103,17 @@ tools:text="1080 x 1024 - 43s - 12kB" tools:visibility="visible" /> + + From de809d6013098011b7da929d5c2c9380d9a2b736 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 27 Dec 2021 17:17:20 +0300 Subject: [PATCH 008/222] Add settings item to allow location sharing. --- .../app/features/home/room/detail/RoomDetailFragment.kt | 1 + .../im/vector/app/features/settings/VectorPreferences.kt | 7 +++++++ vector/src/main/res/values/strings.xml | 1 + vector/src/main/res/xml/vector_settings_preferences.xml | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index d530b35c0c..25bd5877f5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -1379,6 +1379,7 @@ class RoomDetailFragment @Inject constructor( if (!::attachmentTypeSelector.isInitialized) { attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@RoomDetailFragment) attachmentTypeSelector.setAttachmentVisibility(AttachmentTypeSelectorView.Type.POLL, vectorPreferences.labsEnablePolls()) + attachmentTypeSelector.setAttachmentVisibility(AttachmentTypeSelectorView.Type.LOCATION, vectorPreferences.isLocationSharingEnabled()) } attachmentTypeSelector.show(views.composerLayout.views.attachmentButton, keyboardStateUtils.isKeyboardShowing) } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 64561cbc12..c367d628bd 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -185,6 +185,9 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val DID_ASK_TO_ENABLE_SESSION_PUSH = "DID_ASK_TO_ENABLE_SESSION_PUSH" private const val DID_PROMOTE_NEW_RESTRICTED_JOIN_RULE = "DID_PROMOTE_NEW_RESTRICTED_JOIN_RULE" + // Location Sharing + private const val SETTINGS_PREF_ENABLE_LOCATION_SHARING = "SETTINGS_PREF_ENABLE_LOCATION_SHARING" + private const val MEDIA_SAVING_3_DAYS = 0 private const val MEDIA_SAVING_1_WEEK = 1 private const val MEDIA_SAVING_1_MONTH = 2 @@ -990,4 +993,8 @@ class VectorPreferences @Inject constructor(private val context: Context) { fun labsEnablePolls(): Boolean { return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_POLLS, false) } + + fun isLocationSharingEnabled(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_PREF_ENABLE_LOCATION_SHARING, true) + } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index e5fe5ad5c7..1b4d137928 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3711,4 +3711,5 @@ Element could not access your location Element could not access your location. Please try again later. Open with + Enable location sharing diff --git a/vector/src/main/res/xml/vector_settings_preferences.xml b/vector/src/main/res/xml/vector_settings_preferences.xml index 14c7dc7b80..bc9e06f754 100644 --- a/vector/src/main/res/xml/vector_settings_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_preferences.xml @@ -28,6 +28,11 @@ android:persistent="false" android:title="@string/font_size" /> + + From 15fa42ba9b367057d4382f247fc8066a484cca5b Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 27 Dec 2021 17:55:48 +0300 Subject: [PATCH 009/222] Lint fixes. --- .../epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt | 2 -- .../timeline/action/MessageActionsEpoxyController.kt | 1 - .../room/detail/timeline/factory/MessageItemFactory.kt | 1 - .../java/im/vector/app/features/location/LocationData.kt | 1 - .../app/features/location/LocationPreviewFragment.kt | 9 +++------ .../im/vector/app/features/location/LocationTracker.kt | 3 +++ .../im/vector/app/features/location/MapTilerMapView.kt | 1 - 7 files changed, 6 insertions(+), 12 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index ae9efe367a..7c18dd818e 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -39,8 +39,6 @@ import im.vector.app.features.location.MapTilerMapView import im.vector.app.features.location.VectorMapListener import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.session.room.model.message.LocationInfo -import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.util.MatrixItem /** diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 0bd4f1bf21..3e1edfa158 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -43,7 +43,6 @@ import im.vector.app.features.location.LocationData import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure -import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.send.SendState 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 b0df2d6a54..607e4c1252 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 @@ -185,7 +185,6 @@ class MessageItemFactory @Inject constructor( highlight: Boolean, callback: TimelineEventController.Callback?, attributes: AbsMessageItem.Attributes): MessageLocationItem? { - val geoUri = locationContent.locationInfo?.geoUri ?: locationContent.geoUri val locationData = LocationData.create(geoUri) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationData.kt b/vector/src/main/java/im/vector/app/features/location/LocationData.kt index 874e159e80..b790bde710 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationData.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationData.kt @@ -68,4 +68,3 @@ data class LocationData( } } } - diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt index e13456dbdc..1a7ed49209 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt @@ -16,21 +16,18 @@ package im.vector.app.features.location -import android.content.Intent -import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.FragmentLocationPreviewBinding -import javax.inject.Inject import com.airbnb.mvrx.args import im.vector.app.R +import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.openLocation +import im.vector.app.databinding.FragmentLocationPreviewBinding import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider -import org.matrix.android.sdk.api.extensions.tryOrNull +import javax.inject.Inject class LocationPreviewFragment @Inject constructor( private val locationPinProvider: LocationPinProvider diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt index 0ea1e6810b..6e55735f9b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -16,10 +16,12 @@ package im.vector.app.features.location +import android.Manifest import android.content.Context import android.location.Location import android.location.LocationListener import android.location.LocationManager +import androidx.annotation.RequiresPermission import timber.log.Timber import javax.inject.Inject @@ -65,6 +67,7 @@ class LocationTracker @Inject constructor( } } + @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION]) fun stop() { locationManager?.removeUpdates(this) callback = null diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index 627b9e5ec3..386e96988f 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -19,7 +19,6 @@ package im.vector.app.features.location import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet -import com.mapbox.mapboxsdk.Mapbox import com.mapbox.mapboxsdk.camera.CameraPosition import com.mapbox.mapboxsdk.geometry.LatLng import com.mapbox.mapboxsdk.maps.MapView From fc4d18f84e2f51cfb05cb10e3d28730439c49125 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 28 Dec 2021 14:00:37 +0300 Subject: [PATCH 010/222] Dummy maptiler key added for CI. --- vector/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vector/build.gradle b/vector/build.gradle index 562e0af679..2f10695c2f 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -150,6 +150,8 @@ android { // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" + buildConfigField "String", "mapTilerKey", "\"DUMMY_KEY\"" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Keep abiFilter for the universalApk From 6e1911e686a402c8503b0377bbda3bbd65aee4dc Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 28 Dec 2021 17:04:51 +0300 Subject: [PATCH 011/222] Lint fixes. --- .../timeline/factory/MessageItemFactory.kt | 14 ++++++++- .../timeline/item/MessageLocationItem.kt | 29 +++++++++++-------- .../app/features/location/LocationTracker.kt | 3 +- 3 files changed, 32 insertions(+), 14 deletions(-) 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 607e4c1252..e293b1ecbd 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 @@ -33,6 +33,7 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.containsOnlyEmojis +import im.vector.app.features.home.room.detail.RoomDetailAction import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder @@ -71,6 +72,7 @@ import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.VectorHtmlCompressor import im.vector.app.features.location.LocationData +import im.vector.app.features.location.VectorMapView import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import me.gujun.android.span.span @@ -188,6 +190,16 @@ class MessageItemFactory @Inject constructor( val geoUri = locationContent.locationInfo?.geoUri ?: locationContent.geoUri val locationData = LocationData.create(geoUri) + val mapCallback: MessageLocationItem.Callback = object: MessageLocationItem.Callback { + override fun onMapReady(mapView: VectorMapView) { + mapView.onClick { + locationData?.let { + callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(it, informationData.senderId)) + } + } + } + } + return MessageLocationItem_() .attributes(attributes) .locationData(locationData) @@ -195,7 +207,7 @@ class MessageItemFactory @Inject constructor( .locationPinProvider(locationPinProvider) .highlighted(highlight) .leftGuideline(avatarSizeProvider.leftGuideline) - .callback(callback) + .callback(mapCallback) } private fun buildPollItem(pollContent: MessagePollContent, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt index d4995d3fad..2d65fd3131 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -27,12 +27,17 @@ import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvid import im.vector.app.features.location.LocationData import im.vector.app.features.location.MapTilerMapView import im.vector.app.features.location.VectorMapListener +import im.vector.app.features.location.VectorMapView @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageLocationItem : AbsMessageItem() { + interface Callback { + fun onMapReady(mapView: VectorMapView) + } + @EpoxyAttribute - var callback: TimelineEventController.Callback? = null + var callback: Callback? = null @EpoxyAttribute var locationData: LocationData? = null @@ -50,20 +55,20 @@ abstract class MessageLocationItem : AbsMessageItem( val location = locationData ?: return val locationOwnerId = userId ?: return - holder.mapView.initialize(object : VectorMapListener { - override fun onMapReady() { - holder.mapView.zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) + holder.mapView.apply { + initialize(object : VectorMapListener { + override fun onMapReady() { + zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) - locationPinProvider?.create(locationOwnerId) { pinDrawable -> - holder.mapView.addPinToMap(locationOwnerId, pinDrawable) - holder.mapView.updatePinLocation(locationOwnerId, location.latitude, location.longitude) - } + locationPinProvider?.create(locationOwnerId) { pinDrawable -> + addPinToMap(locationOwnerId, pinDrawable) + updatePinLocation(locationOwnerId, location.latitude, location.longitude) + } - holder.mapView.onClick { - callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(location, locationOwnerId)) + callback?.onMapReady(this@apply) } - } - }) + }) + } } override fun getViewType() = STUB_ID diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt index 6e55735f9b..48692ef216 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -24,6 +24,7 @@ import android.location.LocationManager import androidx.annotation.RequiresPermission import timber.log.Timber import javax.inject.Inject +import androidx.core.content.getSystemService class LocationTracker @Inject constructor( private val context: Context) : LocationListener { @@ -36,7 +37,7 @@ class LocationTracker @Inject constructor( var callback: Callback? = null fun start() { - val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as? LocationManager + val locationManager = context.getSystemService() locationManager?.let { val isGpsEnabled = it.isProviderEnabled(LocationManager.GPS_PROVIDER) From 4d6eec8972ebf7fd9eaf31762898538814eeaf0f Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 31 Dec 2021 15:12:46 +0300 Subject: [PATCH 012/222] Rate limited maptiler key is added. --- changelog.d/2210.bugfix | 1 + vector/build.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/2210.bugfix diff --git a/changelog.d/2210.bugfix b/changelog.d/2210.bugfix new file mode 100644 index 0000000000..6f7c09ce26 --- /dev/null +++ b/changelog.d/2210.bugfix @@ -0,0 +1 @@ +Static location sharing and rendering \ No newline at end of file diff --git a/vector/build.gradle b/vector/build.gradle index 2f10695c2f..76fe629d3c 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -150,7 +150,7 @@ android { // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" - buildConfigField "String", "mapTilerKey", "\"DUMMY_KEY\"" + buildConfigField "String", "mapTilerKey", "\"KF6tcY7YuKFgJSZ1EFQ2\"" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" From ae8ca5356ff34947e3f11642f04ef8b7b467a2b8 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 12 Jan 2022 15:14:13 +0300 Subject: [PATCH 013/222] Fix recyclerview issues on async map functions. --- .../detail/timeline/factory/MessageItemFactory.kt | 9 +++------ .../room/detail/timeline/item/MessageLocationItem.kt | 12 ++++++++---- .../res/layout/item_timeline_event_location_stub.xml | 9 +++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) 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 51aa51f070..4070532f80 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 @@ -73,7 +73,6 @@ import im.vector.app.features.html.PillsPostProcessor import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.VectorHtmlCompressor import im.vector.app.features.location.LocationData -import im.vector.app.features.location.VectorMapView import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import me.gujun.android.span.span @@ -192,11 +191,9 @@ class MessageItemFactory @Inject constructor( val locationData = LocationData.create(geoUri) val mapCallback: MessageLocationItem.Callback = object : MessageLocationItem.Callback { - override fun onMapReady(mapView: VectorMapView) { - mapView.onClick { - locationData?.let { - callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(it, informationData.senderId)) - } + override fun onMapClicked() { + locationData?.let { + callback?.onTimelineItemAction(RoomDetailAction.ShowLocation(it, informationData.senderId)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt index cb37901245..d8ccf3761e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -16,21 +16,22 @@ package im.vector.app.features.home.room.detail.timeline.item +import android.widget.FrameLayout import androidx.constraintlayout.widget.ConstraintLayout import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R +import im.vector.app.core.epoxy.onClick import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.location.LocationData import im.vector.app.features.location.MapTilerMapView import im.vector.app.features.location.VectorMapListener -import im.vector.app.features.location.VectorMapView @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageLocationItem : AbsMessageItem() { interface Callback { - fun onMapReady(mapView: VectorMapView) + fun onMapClicked() } @EpoxyAttribute @@ -52,6 +53,10 @@ abstract class MessageLocationItem : AbsMessageItem( val location = locationData ?: return val locationOwnerId = userId ?: return + holder.clickableMapArea.onClick { + callback?.onMapClicked() + } + holder.mapView.apply { initialize(object : VectorMapListener { override fun onMapReady() { @@ -61,8 +66,6 @@ abstract class MessageLocationItem : AbsMessageItem( addPinToMap(locationOwnerId, pinDrawable) updatePinLocation(locationOwnerId, location.latitude, location.longitude) } - - callback?.onMapReady(this@apply) } }) } @@ -73,6 +76,7 @@ abstract class MessageLocationItem : AbsMessageItem( class Holder : AbsMessageItem.Holder(STUB_ID) { val mapViewContainer by bind(R.id.mapViewContainer) val mapView by bind(R.id.mapView) + val clickableMapArea by bind(R.id.clickableMapArea) } companion object { diff --git a/vector/src/main/res/layout/item_timeline_event_location_stub.xml b/vector/src/main/res/layout/item_timeline_event_location_stub.xml index b126231ba1..0b211ec5e0 100644 --- a/vector/src/main/res/layout/item_timeline_event_location_stub.xml +++ b/vector/src/main/res/layout/item_timeline_event_location_stub.xml @@ -14,4 +14,13 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + From cae2011d0e2cc63cc2e2ab58e25cadc447e397fa Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 12 Jan 2022 07:02:37 +0000 Subject: [PATCH 014/222] Translated using Weblate (Czech) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- vector/src/main/res/values-cs/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index d02b80c78a..1b483c6adb 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -3117,4 +3117,22 @@ Restartujte aplikaci, aby se změna projevila. Povolit matematické výrazy LaTeXu Do této místnosti vám není dovoleno vstoupit + Vytvořit hlasování + Otevřít kontakty + Odeslat nálepku + Odeslání souboru + Odesílání obrázků a videí + Otevřít fotoaparát + Váš systém bude automaticky odesílat chybové protokoly, když dojde k chybě dešifrování + Automaticky nahlašovat chyby dešifrování. + Přepsat barvu přezdívky + Již mám účet + Element je stejně univerzální jako e-mail a představuje zcela nový typ spolupráce. + Zlepšete týmovou komunikaci. + Element funguje se všemi aplikacemi založenými na protokolu Matrix a dokáže se propojit i s proprietárními messengery. + Spojte se s kýmkoli. + Element vám umožňuje zvolit si, kde jsou vaše zprávy uložené, takže máte svá data pod kontrolou. + Máte vše pod kontrolou. + Koncově šifrovaná, bezpečná a nezávislá komunikace, připojená přes Matrix. + Vlastněte své konverzace. \ No newline at end of file From bc003a547b5573b4152a65386f214c4e6a605e24 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Tue, 11 Jan 2022 20:59:03 +0000 Subject: [PATCH 015/222] Translated using Weblate (Persian) Currently translated at 99.8% (2726 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- vector/src/main/res/values-fa/strings.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index b3d5c00f2f..a60f6bcbde 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -3058,4 +3058,19 @@ برای اثربخشی تغییر، برنامه را دوباره اجرا کنید. به کار انداختن ریاضیات لاتک مجاز به پیوستن به این گروه نیستید + ایجاد نظرسنجی + گشودن آشنایان + فرستادن عکس‌برگردان + بارگذاری پرونده + فرستادن تصویرها و ویدیوها + گشودن دوربین + سامانه‌تان هنگام‌ مواجهه با خطای ناتوانی در رمزگشایی، گزارش‌ها را به صورت خودکار خواهد فرستاد + گزارش خودکار خطاهای رمزگشایی. + از پیش حساب دارم + المنت با تمامی کاره‌های مبتنی بر ماتریکس کار کرده و حتا می‌تواند به پیام‌رسان‌های مالکیتیتان پل بزند. + ارتباط با هرکسی. + المنت می‌گذارد مکان ذخیرهٔ پیام‌هایتان را برگزینید تا داده‌هایتان را کنترل کنید. + شما کنترل می‌کنید. + پیام‌رسانی رمزنگاشتهٔ سرتاسری برای ارتباط مستقل امن، وصل شده با ماتریکس. + صاحب گفت‌وگوهایتان باشید. \ No newline at end of file From 95496a0cd71963497be79d010d195e91c5335f3b Mon Sep 17 00:00:00 2001 From: Szimszon Date: Tue, 11 Jan 2022 20:43:42 +0000 Subject: [PATCH 016/222] Translated using Weblate (Hungarian) Currently translated at 99.3% (2712 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/hu/ --- vector/src/main/res/values-hu/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index e8bb1c464e..1b01de628f 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -3057,4 +3057,5 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró A változások életbelépéséhez indítsd újra az alkalmazást. LaTeX matematikai szintaxis engedélyezése Nem léphetsz be ebbe a szobába + Az ön beszélgetései csak az öné. \ No newline at end of file From b12cf686ef9cef0edf047789e56223074dd955a8 Mon Sep 17 00:00:00 2001 From: Linerly Date: Tue, 11 Jan 2022 13:50:19 +0000 Subject: [PATCH 017/222] Translated using Weblate (Indonesian) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index 4f774bac76..4502d15c23 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -3003,4 +3003,22 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Mulai ulang aplikasi ini untuk menerapkan perubahan. Aktifkan matematika LaTeX Anda tidak diperbolehkan untuk bergabung ke ruangan ini + Sistem Anda akan mengirimkan log secara otomatis ketika sebuah kesalahan dekripsi terjadi + Buat poll + Buka kontak + Kirim stiker + Unggah file + Kirim gambar dan video + Buka kamera + Laporkan Kesalahan Dekripsi Secara Otomatis. + Ubah warna nama tampilan + Saya sudah punya akun + Universal seperti email, Element adalah jenis kolaborasi yang benar-benar baru. + Bebaskan. + Elemen berfungsi dengan semua aplikasi berbasis Matrix dan bahkan dapat menjembatani ke perpesanan sumber tertutup. + Hubung dengan siapa pun. + Elemen memungkinkan Anda untuk memilih di mana pesan Anda disimpan, membuat Anda tetap mengendali data Anda. + Anda mengendalikannya. + Perpesanan terenkripsi secara ujung-ke-ujung untuk komunikasi aman dan independen, terhubung via Matrix. + Miliki percakapan Anda. \ No newline at end of file From 3f81ec4d868a4ef0b42eca4dd2ccd14a2e94511e Mon Sep 17 00:00:00 2001 From: random Date: Wed, 12 Jan 2022 09:41:02 +0000 Subject: [PATCH 018/222] Translated using Weblate (Italian) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- vector/src/main/res/values-it/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index ec88bbe89d..cfa145c082 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -3048,4 +3048,22 @@ Riavvia l\'applicazione per applicare le modifiche. Attiva la matematica LaTeX Non ti è permesso entrare in questa stanza + Crea sondaggio + Apri i contatti + Invia sticker + Invia file + Invia immagini e video + Apri fotocamera + Il tuo sistema invierà automaticamente i log quando si verifica un errore di decifrazione + Auto-segnala errori di decifrazione. + Sovrascrivi colore nick + Ho già un account + Universale come le email, Element è un tipo di collaborazione completamente nuovo. + Riduci il carico ai team. + Element funziona con tutte le app basate su Matrix e può anche fare da ponte tra messaggistiche proprietarie. + Connettiti con chiunque. + Element ti lascia scegliere dove i messaggi vengono salvati, dandoti il controllo dei tuoi dati. + Tu hai il controllo. + Messaggistica cifrata end-to-end per comunicazioni sicure e indipendenti, connesse via Matrix. + Prendi il controllo delle tue conversazioni. \ No newline at end of file From 099c0ddc36a92a07811db331341dda3964557e7b Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Tue, 11 Jan 2022 14:17:47 +0000 Subject: [PATCH 019/222] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- vector/src/main/res/values-pt-rBR/strings.xml | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index 6c10294c02..4bae8d0640 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -221,18 +221,18 @@ %1$s, %2$s e %3$s 🎉 Todos os servidores estão banidos de participar! Esta sala não pode mais ser usada. Nenhuma mudança. - • Servidores correspondendo a literais de IP estão agora banidos. - • Servidores correspondendo a literais de IP estão agora permitidos. - • Servidores correspondendo a %s foram removidos da lista de permitidos. - • Servidores correspondendo a %s estão agora permitidos. - • Servidores correspondendo a %s foram removidos da lista de banimento. - • Servidores correspondendo a %s estão agora banidos. + • Servidores correspondendo com literais de IP estão agora banidos. + • Servidores correspondendo com literais de IP estão agora permitidos. + • Servidores correspondendo com %s foram removidos da lista de permitidos. + • Servidores correspondendo com %s estão agora permitidos. + • Servidores correspondendo com %s foram removidos da lista de banimento. + • Servidores correspondendo com %s estão agora banidos. Você mudou as LCAs do servidor para esta sala. %s mudou as LCAs do servidor para esta sala. - • Servidores correspondendo a literais de IP estão banidos. - • Servidores correspondendo a literais de IP estão permitidos. - • Servidores correspondendo a %s estão permitidos. - • Servidores correspondendo a %s estão banidos. + • Servidores correspondendo com literais de IP estão banidos. + • Servidores correspondendo com literais de IP estão permitidos. + • Servidores correspondendo com %s estão permitidos. + • Servidores correspondendo com %s estão banidos. Você definiu as LCAs do servidor para esta sala. %s definiu as LCAs do servidor para esta sala. Você mudou os endereços alternativos para esta sala. @@ -549,7 +549,7 @@ Impressão digital (%s): Não foi possível verificar identidade de servidor remoto. Isto poderia significar que alguém está maliciosamente interceptando seu tráfico, ou que seu celular não confia no certificado provido pelo servidor remoto. - Se o/a administrador(a) de servidor tem dito que isto é esperado, assegure que a impressão digital abaixo corresponde à impressão digital provida por ele(a). + Se o/a administrador(a) de servidor tem dito que isto é esperado, assegure que a impressão digital abaixo corresponde com a impressão digital provida por ele(a). O certificado tem mudado de um que era confiado por seu telefone. Isto é ALTAMENTE INCOMUM. É recomendado que você NÃO ACEITE este novo certificado. O certificado tem mudado de um previamente confiado para um que não é confiado. O servidor pode ter renovado seu certificado. Contacte o/a administrador(a) de servidor para a impressão digital esperada. Somente aceite o certificado se o/a administrador(a) de servidor tem publicado uma impressão digital que corresponde com a acima. @@ -759,7 +759,7 @@ Retirar da lista negra Verificar sessão Confirme ao comparar o seguinte com as Configurações de Usuária(o) em sua outra sessão: - Se não corresponderem, a segurança de sua comunicação pode estar comprometida. + Se não correspondem, a segurança de sua comunicação pode estar comprometida. Eu verifico que as chaves correspondem Sala contém sessões desconhecidas Esta sala contém sessões desconhecidas que não têm sido verificadas. @@ -1543,8 +1543,8 @@ O SAS não correspondeu A sessão recebeu uma mensagem inesperada Uma mensagem inválida foi recebida - Disparidade de chave - Disparidade de usuária(o) + Correspondência errada de chave + Correspondência errada de usuária(o) Erro Desconhecido Você não está usando nenhum servidor de identidade Nenhum servidor de identidade está configurado, ele é requerido para resettar sua senha. @@ -3058,4 +3058,22 @@ Recomece o aplicativo para a mudançar tomar efeito. Habilitar matemática LaTeX Você não é permitida(o) a juntar-se a esta sala + Criar sondagem + Abrir contatos + Enviar sticker + Fazer upload de arquivo + Enviar imagens e vídeos + Abrir câmera + Seu sistema vai automaticamente enviar logs quando um erro incapaz de decriptar ocorre + Auro Reportar Erros de Decriptação. + Sobrepor cor de nick + Eu já tenho uma conta + Tão universal quanto email, Element é um tipo de colaboração completamente novo. + Dê liberdade a times. + Element funciona com todos os apps baseados em Matrix e pode até construir pontes para mensageiros proprietários. + Conecte-se com qualquer pessoa. + Element lhe permite escolher onde suas mensagens são armazenadas, mantendo você em controle de seus dados. + Você está em controle. + Mensageria encriptada ponta-a-ponta para comunicação segura e independente, conectada via Matrix. + Tenha posse de suas conversas. \ No newline at end of file From b8f72879d31a44e9bf8976b2c435c2ac4bdb7054 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Tue, 11 Jan 2022 15:03:13 +0000 Subject: [PATCH 020/222] Translated using Weblate (Albanian) Currently translated at 99.4% (2715 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sq/ --- vector/src/main/res/values-sq/strings.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml index 5985bd40fe..08eab1ed6e 100644 --- a/vector/src/main/res/values-sq/strings.xml +++ b/vector/src/main/res/values-sq/strings.xml @@ -3046,4 +3046,21 @@ Që ndryshimi të hyjë në fuqi, rinisni aplikacionin. Aktivizo elementë LaTeX për matematikë S’keni leje të hyni në këtë dhomë + Krijoni anketim + Hap kontakte + Dërgoni ngjitës + Ngarkoni kartelë + Dërgoni figura dhe video + Hapni kamerën + Sistemi juaj do të dërgojë automatikisht regjistra, kur ndodh një gabim “s’arrihet të shfshehtëzohet” + Raporto Vetvetiu Gabime Shfshehtëzimi. + Anashkalo ngjyrë nofke + Kam tashmë një llogari + Po aq universal sa email-i, Element-i është një lloj plotësisht i ri bashkëpunimi. + Element-i funksionon me krejt aplikacionet e bazuar në Matrix dhe mund të shërbejë madje si urë për shkëmbyes pronësorë mesazhesh. + Lidhuni me këdo. + Element-i ju lejon të zgjidhni ku depozitohen mesazhet tuaja, duke ju mbajtur ju në kontroll të të dhënave tuaja. + Kontrollin e keni ju. + Shkëmbim mesazhesh të fshehtëzuar skaj më skaj, për komunikim të siguruar dhe të pavarur, me lidhje përmes Matrix-it. + Jini zot i bisedave tuaja. \ No newline at end of file From 10c6153542d1a6efbfe1f2cda9ab15c23b1a5c86 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Tue, 11 Jan 2022 15:05:30 +0000 Subject: [PATCH 021/222] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- vector/src/main/res/values-uk/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 4ad5ceae60..3003ece5a4 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -3160,4 +3160,22 @@ Перезапустіть застосунок, щоб зміни набули чинності. Увімкнути підтримку LaTeX Вам не дозволено приєднуватися до цієї кімнати + Створити опитування + Відкрити контакти + Надіслати наліпку + Вивантажити файл + Надіслати зображення й відео + Відкрити камеру + Ваша система автоматично надсилатиме журнали, коли виникне помилка неможливості розшифрування + Автозвіт про помилки шифрування. + Замінити колір псевдоніма + Я вже маю обліковий запис + Універсальний, як електронна пошта, Element — це абсолютно новий тип співпраці. + Удоскональте спілкування в команді. + Element працює з усіма застосунками на базі Matrix і може навіть з\'єднуватися з власницькими месенджерами. + З\'єднуйтеся з будь-ким. + Element дає змогу обрати де зберігати повідомлення, надаючи вам контроль над вашими даними. + Ви контролюєте все. + Наскрізно зашифроване спілкування для безпечного та незалежного зв’язку, під\'єднаного через Matrix. + Володійте своїми розмовами. \ No newline at end of file From 97ff707e06032550e0eedc27fd52ef0c65a063da Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 12 Jan 2022 02:18:57 +0000 Subject: [PATCH 022/222] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- vector/src/main/res/values-zh-rTW/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index c5a33b7072..a73871e8c8 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -2999,4 +2999,22 @@ 重新啟動應用程式以讓變更生效。 啟用 LaTeX 數學 您無法加入此聊天室 + 建立投票 + 開啟通訊錄 + 傳送貼圖 + 上傳檔案 + 傳送圖片與影片 + 開啟攝影機 + 發生無法解密錯誤時,您的系統將會自動傳送紀錄檔 + 自動回報解密錯誤。 + 覆寫暱稱色彩 + 我已有一個帳號 + 與電子郵件一樣普遍,Element 是一種全新的協作類型。 + 減少團隊的懈怠。 + Element 適用於所有以 Matrix 為基礎的應用程式,甚至可以橋接到專有的通訊軟體。 + 與任何人聯絡。 + Element 可讓您選擇您要儲存訊息的地方,讓您掌控您自己的資料。 + 您已掌控了您的資料。 + 透過 Matrix 連結的端到端加密訊息傳遞,用於安全與獨立的通訊。 + 擁有您的對話。 \ No newline at end of file From acbfda83c9aabfe869ba507dfc878f2c466b21fa Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Tue, 11 Jan 2022 15:05:55 +0000 Subject: [PATCH 023/222] Translated using Weblate (Albanian) Currently translated at 100.0% (43 of 43 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sq/ --- fastlane/metadata/android/sq/changelogs/40103100.txt | 2 ++ fastlane/metadata/android/sq/changelogs/40103110.txt | 2 ++ fastlane/metadata/android/sq/changelogs/40103120.txt | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 fastlane/metadata/android/sq/changelogs/40103100.txt create mode 100644 fastlane/metadata/android/sq/changelogs/40103110.txt create mode 100644 fastlane/metadata/android/sq/changelogs/40103120.txt diff --git a/fastlane/metadata/android/sq/changelogs/40103100.txt b/fastlane/metadata/android/sq/changelogs/40103100.txt new file mode 100644 index 0000000000..c6916fa0ab --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40103100.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Shtim mbulimi për anketime (në zhvillim). Skemë e re grafike për paraprje URL-sh. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.10 diff --git a/fastlane/metadata/android/sq/changelogs/40103110.txt b/fastlane/metadata/android/sq/changelogs/40103110.txt new file mode 100644 index 0000000000..f66779b5ef --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40103110.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Ndreqje të metash! +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.11 diff --git a/fastlane/metadata/android/sq/changelogs/40103120.txt b/fastlane/metadata/android/sq/changelogs/40103120.txt new file mode 100644 index 0000000000..279c523a82 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40103120.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Ndreqje të metash! +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.12 From f9c5b2021de3859c14d12b4631770c125843942f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 13 Jan 2022 15:09:53 +0100 Subject: [PATCH 024/222] Add groups to mavenCentral white list --- build.gradle | 2 -- dependencies_groups.gradle | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7ace92af9a..b7299b01f7 100644 --- a/build.gradle +++ b/build.gradle @@ -53,8 +53,6 @@ allprojects { groups.jitsi.group.each { includeGroup it } } } - // TODO. MapTiler - mavenCentral() google { content { groups.google.regex.each { includeGroupByRegex it } diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 3853919bcb..9cc5684255 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -84,6 +84,7 @@ ext.groups = [ 'com.jakewharton.android.repackaged', 'com.jakewharton.timber', 'com.linkedin.dexmaker', + 'com.mapbox.mapboxsdk', 'com.nulab-inc', 'com.otaliastudios.opengl', 'com.parse.bolts', @@ -159,6 +160,7 @@ ext.groups = [ 'org.junit.jupiter', 'org.junit.platform', 'org.jvnet.staxex', + 'org.maplibre.gl', 'org.matrix.android', 'org.mockito', 'org.mongodb', From 1d7ce1c794647586a4d08c9766970956573f0697 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 20 Sep 2021 10:03:27 +0200 Subject: [PATCH 025/222] Fix switch to best space when tapping notification --- changelog.d/3839.bugfix | 1 + .../java/im/vector/app/AppStateHandler.kt | 8 ++++++- .../home/room/detail/RoomDetailFragment.kt | 3 ++- .../home/room/detail/RoomDetailViewModel.kt | 23 ++++++++++++++++++- .../home/room/detail/RoomDetailViewState.kt | 6 +++-- .../notifications/NotificationUtils.kt | 2 +- 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 changelog.d/3839.bugfix diff --git a/changelog.d/3839.bugfix b/changelog.d/3839.bugfix new file mode 100644 index 0000000000..a2a4dc6876 --- /dev/null +++ b/changelog.d/3839.bugfix @@ -0,0 +1 @@ + Notification does not take me to the room when another space was last viewed \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index 9ed9dd5b23..63c504caf1 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -78,11 +78,17 @@ class AppStateHandler @Inject constructor( } } - fun setCurrentSpace(spaceId: String?, session: Session? = null) { + fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false) { val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace && spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) } + + if (persistNow) { + uiStateRepository.storeGroupingMethod(true, uSession.sessionId) + uiStateRepository.storeSelectedSpace(spaceSum?.roomId, uSession.sessionId) + } + selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum))) if (spaceId != null) { uSession.coroutineScope.launch(Dispatchers.IO) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index deaa56776e..2209dacd04 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -237,7 +237,8 @@ data class RoomDetailArgs( val roomId: String, val eventId: String? = null, val sharedData: SharedData? = null, - val openShareSpaceForId: String? = null + val openShareSpaceForId: String? = null, + val switchToParentSpace: Boolean = false ) : Parcelable class RoomDetailFragment @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt index aba636309f..0041217ff2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt @@ -28,6 +28,7 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.AppStateHandler import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory @@ -55,6 +56,7 @@ import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorDataStore import im.vector.app.features.settings.VectorPreferences +import im.vector.app.space import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.combine @@ -114,7 +116,8 @@ class RoomDetailViewModel @AssistedInject constructor( private val jitsiService: JitsiService, private val activeConferenceHolder: JitsiActiveConferenceHolder, private val decryptionFailureTracker: DecryptionFailureTracker, - timelineFactory: TimelineFactory + timelineFactory: TimelineFactory, + appStateHandler: AppStateHandler ) : VectorViewModel(initialState), Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener { @@ -179,6 +182,24 @@ class RoomDetailViewModel @AssistedInject constructor( if (OutboundSessionKeySharingStrategy.WhenEnteringRoom == BuildConfig.outboundSessionKeySharingStrategy && room.isEncrypted()) { prepareForEncryption() } + + if (initialState.switchToParentSpace) { + // We are coming from a notification, try to switch to the most relevant space + // so that when hitting back the room will appear in the list + appStateHandler.getCurrentRoomGroupingMethod()?.space().let { currentSpace -> + val currentRoomSummary = room.roomSummary() ?: return@let + // nothing we are good + if (currentSpace == null || !currentRoomSummary.flattenParentIds.contains(currentSpace.roomId)) { + // take first one or switch to home + appStateHandler.setCurrentSpace( + currentRoomSummary + .flattenParentIds.firstOrNull { it.isNotBlank() }, + // force persist, because if not on resume the AppStateHandler will resume + // the current space from what was persisted on enter background + persistNow = true) + } + } + } } private fun observeDataStore() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt index e35d601887..d963030013 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt @@ -66,14 +66,16 @@ data class RoomDetailViewState( val isAllowedToStartWebRTCCall: Boolean = true, val isAllowedToSetupEncryption: Boolean = true, val hasFailedSending: Boolean = false, - val jitsiState: JitsiState = JitsiState() + val jitsiState: JitsiState = JitsiState(), + val switchToParentSpace: Boolean = false ) : MavericksState { constructor(args: RoomDetailArgs) : this( roomId = args.roomId, eventId = args.eventId, // Also highlight the target event, if any - highlightedEventId = args.eventId + highlightedEventId = args.eventId, + switchToParentSpace = args.switchToParentSpace ) fun isWebRTCCallOptionAvailable() = (asyncRoomSummary.invoke()?.joinedMembersCount ?: 0) <= 2 diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index 96e8c2af4b..27568dae95 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -773,7 +773,7 @@ class NotificationUtils @Inject constructor(private val context: Context, } private fun buildOpenRoomIntent(roomId: String): PendingIntent? { - val roomIntentTap = RoomDetailActivity.newIntent(context, RoomDetailArgs(roomId)) + val roomIntentTap = RoomDetailActivity.newIntent(context, RoomDetailArgs(roomId = roomId, switchToParentSpace = true)) roomIntentTap.action = TAP_TO_VIEW_ACTION // pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that roomIntentTap.data = createIgnoredUri("openRoom?$roomId") From 6882f7fc005ca81519c8451ffa1125b8e7814bc5 Mon Sep 17 00:00:00 2001 From: libexus Date: Thu, 13 Jan 2022 17:11:22 +0000 Subject: [PATCH 026/222] Translated using Weblate (German) Currently translated at 97.9% (2673 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 81 ++++++++++++----------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index ec169f36d7..da9bbf4494 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -153,7 +153,7 @@ Du hast das %1$s Widget entfernt %1$s hat das %2$s Widget modifiziert Du hast das %1$s Widget modifiziert - Administrator + Admin Moderator Standard Benutzerdefiniert (%1$d) @@ -764,7 +764,7 @@ \nUnbekannte Sitzungen: Raumverzeichnis auswählen Der Server kann nicht verfügbar oder überlastet sein - Gib einen Home-Server ein, um seine öffentlichen Räume aufzulisten + Gib einen Homeserver ein, um seine öffentlichen Räume aufzulisten Server-Name Alle Räume auf dem %s-Server Alle nativen %s-Räume @@ -937,7 +937,7 @@ Dies App braucht die Berechtigung im Hintergrund zu laufen • Benachrichtigungen werden über Firebase-Cloud-Messaging versendet • Benachrichtigungen enthalten nur Metadaten - • Der Nachrichteninhalt der Benachrichtigung wird sicher vom Matrix-Home-Server abgerufen + • Der Nachrichteninhalt der Benachrichtigung wird sicher vom Homeserver abgerufen • Benachrichtigungen enthalten Metadaten und Nachrichteninhalte • Benachrichtigungen werden den Nachrichteninhalt nicht anzeigen Benachrichtungs-Datenschutz @@ -1041,18 +1041,18 @@ Systembenachrichtigungen Ressourcen-Limit - Kontaktiere Administrator + Administrator kontaktieren kontaktiere deinen Service-Administrator - Dieser Home-Server hat eine seiner Ressourcen-Grenzen erreicht, sodass einige Nutzer sich nicht anmelden können. - Dieser Home-Server hat einen seiner Ressourcen-Limits überschritten. - Dieser Home-Server hat seine Obergrenze an monatlich aktiven Nutzer erreicht, sodass einige Nutzer sich nicht anmelden können. - Dieser Home-Server hat seine Obergrenze an monatlich aktiven Nutzer erreicht. + Dieser Homeserver hat eine seiner Ressourcen-Grenzen erreicht, sodass einige Nutzer sich nicht anmelden können. + Dieser Homeserver hat einen seiner Ressourcen-Limits überschritten. + Dieser Homeserver hat seine Obergrenze an monatlich aktiven Nutzer erreicht, sodass sich einige Nutzer nicht anmelden können. + Dieser Homeserver hat seine Obergrenze an monatlich aktiven Nutzer erreicht. Bitte %s um dieses Limit anheben zu lassen. Bitte %s um diesen Dienst weiter zu nutzen. Fehler Raummitglieder bei Bedarf nachladen Verbessere Performance, indem Raummitglieder erst beim ersten Ansehen geladen werden. - Dein Home-Server unterstützt noch nicht das Nachladen von Raummitgliedern. Versuche es später. + Dein Homeserver unterstützt noch nicht das Nachladen von Raummitgliedern. Versuche es später. Entschuldige, ein Fehler trat auf Version %s Bitte eine Passphrase erstellen um exportierte Schlüssel zu verschlüsseln. Du musst dieselbe Passphrase eingeben um die Schlüssel importieren zu können. @@ -1071,7 +1071,7 @@ Trotzdem anrufen Entfernen Grund - Linkvorschau im Chat aktivieren, falls dein Home-Server diese Funktion unterstützt. + Linkvorschau im Chat aktivieren, falls dein Homeserver diese Funktion unterstützt. Schreibbenachrichtigungen senden Lasse andere Benutzer wissen, dass du tippst. Markdown-Formatierung @@ -1093,7 +1093,7 @@ Klingelton für eingehende Anrufe Wähle Klingelton für Anrufe: Akzeptieren - Bitte lese und akzeptiere die Richtlinien dieses Home-Servers: + Bitte lese und akzeptiere die Richtlinien dieses Homeservers: Tests ausführen Läuft… (%1$d von %2$d) Einer oder mehrere Tests sind fehlgeschlagen. Versuche vorgeschlagene Lösung(en). @@ -1219,7 +1219,7 @@ \n \nWarnung: Diese Datei wird gelöscht, wenn die Anwendung deinstalliert wird. Wiederherstellungsschlüssel aus Passphrase generieren. Dies kann mehrere Sekunden brauchen. - Deine Schlüssel werden nun im Hintergrund auf deinem Home-Server gesichert. Die initiale Sicherung kann mehrere Minuten dauern. + Deine Schlüssel werden nun im Hintergrund auf deinem Homeserver gesichert. Die initiale Sicherung kann mehrere Minuten dauern. Du verlierst möglicherweise den Zugang zu deinen Nachrichten, wenn du dich abmeldest oder das Gerät verlierst. Rufe Backup-Version ab… Nutze deine Wiederherstellungspassphrase, um deinen verschlüsselten Chatverlauf lesen zu können @@ -1273,7 +1273,7 @@ (Erweitert) Schlüssel manuell exportieren Schütze deine Sicherung mit einer Passphrase. - Eine verschlüsselte Kopie deiner Schlüssel wird auf deinem Home-Server gespeichert. Schütze deine Sicherung mit einer Passphrase. + Eine verschlüsselte Kopie deiner Schlüssel wird auf deinem Homeserver gespeichert. Schütze deine Sicherung mit einer Passphrase. \n \nFür maximale Sicherheit sollte diese *nicht* dein Konto-Passwort sein. Erstelle Sicherung @@ -1318,7 +1318,7 @@ Passwort aktualisieren Das Passwort ist ungültig Passwörter stimmen nicht überein - Ungültige Antwort beim Entdecken des Home-Servers + Ungültige Antwort beim Entdecken des Homeservers Serveroptionen vervollständigen ${app_name} hat eine benutzerdefinierte Serverkonfiguration für die Domäne deines Benutzernamens gefunden \"%1$s\": \n%2$s @@ -1522,7 +1522,7 @@ Um fortzufahren, musst du die Nutzungsbedingungen akzeptieren. Du verwendest keinen Identitätsserver Es ist kein Identitätsserver konfiguriert. Du musst dein Kennwort zurücksetzen. - Du versuchst anscheinend, eine Verbindung zu einem anderen Home-Server herzustellen. Möchtest du dich abmelden\? + Du versuchst anscheinend, eine Verbindung zu einem anderen Homeserver herzustellen. Möchtest du dich abmelden\? Push-Key: App-Anzeigename: Url: @@ -1539,12 +1539,12 @@ Erkennungsoptionen werden angezeigt, sobald du eine E-Mail hinzugefügt hast. ausstehend Gib einen neuen Identitätsserver ein - Konnte keine Verbindung zum Home-Server herstellen + Konnte keine Verbindung zum Homeserver herstellen Bitte bitte den Administrator deines Heimservers (%1$s) einen \"TURN-Server\" einzurichten, damit Anrufe zuverlässig funktionieren. \n \nAlternativ kann ein öffentlicher Server auf %2$s genutzt werden. Dies wird jedoch weniger zuverlässig sein und deine IP-Adresse gegenüber diesem Server preisgeben. Du kannst den Server auch in den Einstellungen anpassen. Dies ist keine Adresse eines Matrixservers - Kann Home-Server nicht unter dieser URL erreichen. Bitte überprüfen + Kann Homeserver nicht unter dieser URL erreichen. Bitte überprüfen Wir nutzen %s als Ersatz, wenn dein Heimserver keinen anbietet (Deine IP-Adresse wird während des Anrufs geteilt) Füge einen Identitätsserver in deinen Einstellungen hinzu, um diese Aktion auszuführen. Passwort bestätigen @@ -1594,7 +1594,7 @@ Eine Textnachricht wurde an %s gesendet. Bitte gib den Verifizierungscode ein, den sie enthält. Aktiviere ausführliche Logs. Ausführliche Logs werden der Entwicklung der App dadurch helfen, dass mehr Informationen übertragen werden, wenn du einen Fehlerbericht sendest. Auch wenn dies aktiviert ist, werden keine Nachrichteninhalte oder andere privaten Daten aufgezeichnet. - Bitte erneut versuchen, nachdem du die Nutzungsbedingungen deines Home-Servers akzeptiert hast. + Bitte erneut versuchen, nachdem du die Nutzungsbedingungen deines Homeservers akzeptiert hast. Bei Benutzung könnten Cookies gesetzt werden und es könnten Daten mit %s geteilt werden: Bei Benutzung könnten Daten mit %s geteilt werden: Optionen zum Finden werden erscheinen, sobald du eine Telefonnummer hinzugefügt hast. @@ -1737,8 +1737,8 @@ Es ist deine Konversation. Mache sie dir zu eigen. Premium-Hosting für Organisationen Gib die Adresse des Modular Element oder Servers ein, den du verwenden möchtest - Die Anwendung kann sich nicht bei diesem Home-Server anmelden. Der Home-Server unterstützt die folgenden Anmeldetypen: %1$s. -\n + Die Anwendung kann sich nicht bei diesem Homeserver anmelden. Der Homeserver unterstützt die folgenden Anmeldemöglichkeiten: %1$s. +\n \nMöchtest du dich mit einem Webclient anmelden\? Dir wird eine Bestätigungsmail gesendet, um dein neues Passwort zu bestätigen. Weiter @@ -1758,8 +1758,8 @@ Weiter Warnung Bitte löse das Captcha - Veralteter Home-Server - Auf diesem Home-Server läuft eine zu alte Version, um eine Verbindung herzustellen. Bitte deinen Home-Server-Administrator um ein Upgrade. + Veralteter Homeserver + Dieser Homeserver ist veraltet und wir können dich mit ihm leider nicht verbinden. Kontaktiere die Betreiber und bitte sie, den Server upzudaten. Es wurden zu viele Anfragen gesendet. Versuche es erneut in %1$d Sekunde… Es wurden zu viele Anfragen gesendet. Versuche es erneut in %1$d Sekunden… @@ -1776,7 +1776,7 @@ Melde dich erneut an Du bist abgemeldet Anmelden - Dein Home-Server-Administrator (%1$s) hat dich von deinem Konto %2$s (%3$s) abgemeldet. + Dein Homeserver-Administrator (%1$s) hat dich von deinem Konto %2$s (%3$s) abgemeldet. Melde dich an, um ausschließlich auf diesem Gerät gespeicherte Schlüssel wiederherzustellen. Du benötigst sie, um deine verschlüsselten Nachrichten auf jedem Gerät zu lesen. Anmelden Passwort @@ -1820,11 +1820,11 @@ Für ultimative Sicherheit verwende ein anderes vertrauenswürdiges Kommunikationsmittel oder mache es persönlich. Suche nach dem grünen Schild, um sicherzustellen, dass ein Benutzer vertrauenswürdig ist. Vertraue alle Benutzer in einem Raum, um sicherzustellen, dass der Raum sicher ist. Nicht sicher - Eine der folgenden Möglichkeiten kann beeinträchtigt sein: -\n -\n - Dein Home-Server -\n - Der Home-Server mit dem dein Gegenüber verbunden ist -\n - Deine oder die Internetverbindung des Gegenüber + Eine der folgenden Möglichkeiten kann beeinträchtigt sein: +\n +\n - Dein Homeserver +\n - Der Homeserver mit dem dein Gegenüber verbunden ist +\n - Deine oder die Internetverbindung des Gegenüber \n - Dein Gerät oder das Gerät des Gegenüber Video. Bild. @@ -1982,7 +1982,7 @@ Eines der folgenden könnte kom­pro­mit­tie­rt sein: \n \n- Dein Passwort -\n- Dein Home-Server +\n- Dein Homeserver \n- Dieses Gerät, oder das andere Gerät \n- Die Internetverbindung, die von den Geräten genutzt wird \n @@ -2120,7 +2120,7 @@ Ablehnen Erfolg Echtzeitverbindung konnte nicht hergestellt werden. -\nBitte den Administrator deines Home-Servers, einen TURN-Server zu konfigurieren, dass Anrufe zuverlässig funktionieren. +\nBitte den Administrator deines Homeservers, einen TURN-Server zu konfigurieren, dass Anrufe zuverlässig funktionieren. Audiogerät auswählen Telefonie Lautsprecher @@ -2197,11 +2197,11 @@ Wenn du deine Matrixkennung und dein Passwort weißt, kannst du alternativ diese Methode nutzen: Einloggen mit Matrix-ID Einloggen mit Matrix-ID - Wenn du einen Account auf einem Home-Server eingerichtet hast, benutze deine Matrix-ID (z.B. @benutzer:domain.com) und Passwort. + Wenn du einen Account auf einem Homeserver eingerichtet hast, benutze deine Matrix-ID (z.B. @benutzer:domain.com) und Passwort. Matrix-ID Wenn du dein Passwort nicht weißt, gehe zurück um es zurücksetzen zu lassen. Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@benutzer:homeserver.org\' - Es konnte kein gültiger Home-Server gefunden werden. Bitte prüfe deine Kennung + Es konnte kein gültiger Homeserver gefunden werden. Bitte prüfe deine Kennung Sticker Administrative Aktionen Standard in %1$s @@ -2221,13 +2221,13 @@ Öffne AGBs von %s Trenne Verbindung zu Identitätsserver %s\? Dieser Identitätsserver ist veraltet. ${app_name} unterstützt nur API V2. - Diese Operation ist nicht möglich. Der Home-Server ist veraltet. + Diese Operation ist nicht möglich. Der Homeserver ist veraltet. Bitte konfiguriere zuerst einen Identitätsserver. Bitte akzeptiere zuerst die AGB des Identitätsservers in den Einstellungen. Deiner Privatsphäre wegen unterstützt ${app_name} nur das Senden gehashter E-Mail-Adressen und Telefonnummern. Die Assoziierung ist fehlgeschlagen. Für diese Kennung gibt es aktuell keine Zuordnung. - Dein Home-Server (%1$s) schlägt %2$s als Identitätsserver vor + Dein Homeserver (%1$s) schlägt %2$s als Identitätsserver vor Benutze %1$s Alternativ kannst du die URL eines beliebigen anderen Identitätsservers angeben Gib die URL von einem Identitätsserver ein @@ -2388,7 +2388,7 @@ \n \nDeine Nachrichten sind mit digitalen Schlüsseln gesichert. Nur du und der Empfänger haben die einzigen Schlüssel, um jene zu entsperren. Nachrichten hier sind nicht Ende-zu-Ende-verschlüsselt. - Dieser Home-Server läuft mit einer alten Version. Bitte deinen Home-Server-Administrator um eine Aktualisierung. Du kannst fortfahren, aber einige Funktionen funktionieren möglicherweise nicht richtig. + Dieser Homeserver läuft mit einer alten Version. Bitte deinen Homeserver-Administrator um eine Aktualisierung. Du kannst fortfahren, aber einige Funktionen funktionieren möglicherweise nicht richtig. Du hast dies auf Einladungen beschränkt. %1$s hat dies auf Einladungen beschränkt. Vollständigen Verlauf in verschlüsselten Räumen anzeigen @@ -2621,7 +2621,7 @@ %d Einträge Die Obergrenze ist nicht bekannt. - Dein Home-Server akzeptiert Anhänge (wie Dateien, Medien, etc.) mit einer Größe bis zu %s. + Dein Homeserver akzeptiert Anhänge (wie Dateien, Medien, etc.) mit einer Größe bis zu %s. Datei-Upload-Obergrenze des Servers Serverversion Servername @@ -2712,7 +2712,7 @@ Welche Art von Space möchtest du erstellen\? Space erstellen Space erstellen - Jeder, der sich in einem Space mit diesem Raum befindet, kann diesen Raum finden und ihm beitreten. Nur die Administratoren des Raums können diesen zu einem Space hinzufügen. + Jeder, der sich in einem Space mit diesem Raum befindet, kann diesen Raum finden und ihm beitreten. Nur die Admins des Raums können diesen zu einem Space hinzufügen. Nur Space-Mitglieder %d Person, die du kennst, ist bereits beigetreten @@ -3003,4 +3003,11 @@ hier Hilf mit, Element zu verbessern Aktivieren + Farbe des Nicknamens ändern + Universell wie Email. Element ist eine gänzlich neue Art zusammenzuarbeiten. + Element funktioniert mit allen Matrix-basierten Apps. Es kann sich sogar mit vollkommen anderen Messengern verbinden. + Du kannst dir aussuchen, wo deine Nachrichten gespeichert werden. Deine Daten gehören dir. + Du hast die volle Kontrolle. + Ende-zu-Ende-Verschlüsselter Messenger für sichere und unabhängige Kommunikation, verbunden mit Matrix. + Du hast nicht die Berechtigung um diesen Raum zu betreten \ No newline at end of file From bd24b0db95247361548774a2533fb1b69378f272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 12 Jan 2022 22:10:30 +0000 Subject: [PATCH 027/222] Translated using Weblate (Estonian) Currently translated at 99.9% (2727 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index 2863162ac1..663212727d 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -3057,4 +3057,23 @@ Muudatuste jõustamiseks käivita rakendus uuesti. Kasuta LaTeX-vorminduses matemaatika märgistust Sul pole luba selle jututoaga liitumiseks + Koosta üks küsitlus + Ava kontaktide vaade + Saada kleeps + Laadi fail üles + Saada pilte ja videosid + Ava kaamera + populaarsem valik + Kui sõnumite dekrüptimisel tekib viga, siis rakendus saadab selle kohta automaatse teate arendajatele + Automaatselt teata dekrüptimise vigadest. + Asenda hüüdnime värvid + Mul on kasutajakonto juba olemas + Olles ühelt poolt sama universaalne kui e-post, on Element teisalt uus ja tõhus viis ühistöö korraldamiseks. + Lase tiimidel vabalt tegutseda. + Element võimaldub suhelda kõikide teiste kasutusel olevate Matrixi-põhiste rakendustega ning lisaks ka paljude suletud suhtlusrakendustega. + Suhtle kellega soovid. + Sul on kontroll oma andmete üle. + Element võimaldab sul valida, kus sinu sõnumeid salvestatakse ja seega on sul kontroll oma andmete üle. + Matrix\'i võrgul põhinev läbivat krüptimist kasutav turvaline ja sõltumatu suhtluslahendus. + Vestlused, mida sa tegelikult ka omad. \ No newline at end of file From 3b7098c48482b20be5b85e5c6dbbc95913b2421f Mon Sep 17 00:00:00 2001 From: Glandos Date: Wed, 12 Jan 2022 21:46:59 +0000 Subject: [PATCH 028/222] Translated using Weblate (French) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- vector/src/main/res/values-fr/strings.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index 2e99edd792..047260f8fa 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -3056,4 +3056,25 @@ \nVous pouvez lire toutes les conditions %s. Aider à améliorer Element Activer + Créer un sondage + Ouvrir les contacts + Envoyer un autocollant + Envoyer un fichier + Envoyer des images et vidéos + Ouvrir la caméra + Redémarrez l’application pour appliquer les changements. + Activer les mathématiques LaTeX + Votre système enverra automatiquement des informations dès qu’une erreur de déchiffrement de message se présente + Signalement automatique des erreurs de déchiffrement. + Outrepasser la couleur du pseudo + J’ai déjà un compte + Aussi universel que le courriel, Element est une forme de collaboration complètement nouvelle. + Être vicTeams, ce n’est pas Slack vous voulez. + Element fonctionne avec toutes les apps basées sur Matrix et peut même être relié à des messageries propriétaires. + Se connecter avec qui vous voulez. + Element vous laisse choisir où sont stockés vos messages, vous laissant le contrôle sur vos données. + Vous êtes aux commandes. + Messagerie chiffrée de bout en bout pour une communication sécurisée et indépendante, connectée via Matrix. + Contrôlez vos conversations. + Vous n’êtes pas autorisé à rejoindre ce salon \ No newline at end of file From db14451d92f4f862d5c6efb08a1ec577eb07d5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Metehan=20=C3=96zy=C3=BCrek?= Date: Thu, 13 Jan 2022 16:28:45 +0000 Subject: [PATCH 029/222] Translated using Weblate (Turkish) Currently translated at 58.3% (1592 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/tr/ --- vector/src/main/res/values-tr/strings.xml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-tr/strings.xml b/vector/src/main/res/values-tr/strings.xml index de0762f3cf..6c00b9104b 100644 --- a/vector/src/main/res/values-tr/strings.xml +++ b/vector/src/main/res/values-tr/strings.xml @@ -1808,13 +1808,22 @@ %1$s %2$s widgetını kaldırdı %1$s uçtan uca şifrelemeyi etkinleştirdi (%2$s) bilinmeyen (%s). - %s güncellendi. + %s burada yükseltildi. birisi. Gelecek mesajları %1$s için görünür yaptınız. %1$s, gelecek mesajları %2$s için görünür hale getirdi. Oda geçmişini %1$s için görünür yaptınız. %1$s oda geçmişini %2$s \'ye görünür yaptı. Çağrı kurulumu için verileri gönderdiniz. - %s kurulumu çağrı verileri gönderildi. - %1$s başlıklı görünen ad silindi. + %s çağrıyı ayarlamak için veri gönderdi. + Görünen adınızı kaldırdınız (%1$s) + • IP değişmezleriyle eşleşen sunucular engellendi. + • IP değişmezleriyle eşleşen sunuculara izin verildi. + • %s ile eşleşen sunuculara izin verildi. + • %s ile eşleşen sunucular yasaklandı. + Bu oda için sunucu EKL\'lerini ayarladınız. + %s bu oda için sunucu EKL\'lerini ayarladı. + Burada yükselttiniz. + tüm oda üyeleri, katıldıkları andan itibaren. + tüm oda üyeleri, davet edildikleri andan itibaren. \ No newline at end of file From 65030c2828780ec9d2f22bbe6c8a97540c9e543f Mon Sep 17 00:00:00 2001 From: libexus Date: Thu, 13 Jan 2022 17:17:39 +0000 Subject: [PATCH 030/222] Translated using Weblate (German) Currently translated at 100.0% (43 of 43 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/40103100.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40103110.txt | 2 ++ fastlane/metadata/android/de-DE/changelogs/40103120.txt | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/40103100.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40103110.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/40103120.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/40103100.txt b/fastlane/metadata/android/de-DE/changelogs/40103100.txt new file mode 100644 index 0000000000..8daa7b51a5 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40103100.txt @@ -0,0 +1,2 @@ +Änderungen: Die Websitevorschau hat ein neues Design erhalten. Außerdem gibt es in den experimentellen Einstellungen Abstimmungen. +Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.10 diff --git a/fastlane/metadata/android/de-DE/changelogs/40103110.txt b/fastlane/metadata/android/de-DE/changelogs/40103110.txt new file mode 100644 index 0000000000..a3d6aad6ca --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40103110.txt @@ -0,0 +1,2 @@ +Hauptänderungen: Bugfixes! +Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.11 diff --git a/fastlane/metadata/android/de-DE/changelogs/40103120.txt b/fastlane/metadata/android/de-DE/changelogs/40103120.txt new file mode 100644 index 0000000000..6930764750 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40103120.txt @@ -0,0 +1,2 @@ +Hauptänderungen: Bugfixes! +Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.12 From 9d16e7fd3328f372a54255daf5fc7fa7a3e24846 Mon Sep 17 00:00:00 2001 From: Glandos Date: Wed, 12 Jan 2022 20:53:06 +0000 Subject: [PATCH 031/222] Translated using Weblate (French) Currently translated at 100.0% (43 of 43 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/40103100.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40103110.txt | 2 ++ fastlane/metadata/android/fr-FR/changelogs/40103120.txt | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40103100.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40103110.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40103120.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103100.txt b/fastlane/metadata/android/fr-FR/changelogs/40103100.txt new file mode 100644 index 0000000000..b6484603d4 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40103100.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : prise en charge des sondages (dans les labs). Nouvel affichage des prévisualisations d’URL +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.10 diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103110.txt b/fastlane/metadata/android/fr-FR/changelogs/40103110.txt new file mode 100644 index 0000000000..aef05c238d --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40103110.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : corrections de bugs ! +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.11 diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103120.txt b/fastlane/metadata/android/fr-FR/changelogs/40103120.txt new file mode 100644 index 0000000000..18cba17990 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40103120.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : corrections de bugs ! +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.12 From 2cbc529b67d479a732c958547b6e9d09951ead01 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Jan 2022 13:37:27 +0000 Subject: [PATCH 032/222] Translated using Weblate (German) Currently translated at 98.4% (2688 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index da9bbf4494..a6ff9f7c39 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -3010,4 +3010,43 @@ Du hast die volle Kontrolle. Ende-zu-Ende-Verschlüsselter Messenger für sichere und unabhängige Kommunikation, verbunden mit Matrix. Du hast nicht die Berechtigung um diesen Raum zu betreten + + Keine Stimme abgegeben + %1$d Stimme abgegeben. Stimme ab, um die Ergebnisse zu sehen + + + Basierend auf %1$d Stimme + Basierend auf %1$d Stimmen + + + %1$d Stimme + %1$d Stimmen + + Starten Sie die Anwendung neu, damit die Änderung wirksam wird. + LaTeX-Mathematik aktivieren + %s in den Einstellungen, um Einladungen direkt in Element zu erhalten. + Diese Einladung zu diesem Raum wurde an %s gesendet, der nicht mit Ihrem Konto verbunden ist + Um Spacemitgliedern zu helfen, einen privaten Raum zu finden und ihm beizutreten, gehen Sie zu den Einstellungen des Raums, indem Sie auf den Avatar tippen. + Dies macht es für Räume einfach, privat in einem Space zu bleiben, während die Leute im Space diese finden und ihnen beitreten können. Alle neuen Räume in einem Raum haben diese Option zur Verfügung. + Helfen Sie Personen in Spaces, private Räume selbst zu finden und ihnen beizutreten, damit Sie nicht alle manuell einladen müssen. + Neu: Personen in Spaces können private Räume finden und ihnen beitreten + Das System sendet automatisch Protokolle, wenn ein Fehler bei der Entschlüsselung auftritt. + Automatische Meldung von Entschlüsselungsfehlern. + Auffindbarkeit (%s) + Per E-Mail einladen, finde Kontakte und mehr… + Schließe die Konfiguration des Auffindbarkeitsdienstes ab. + Sie verwenden derzeit keinen Identitätsserver. Um Teammitglieder einzuladen und für sie auffindbar zu sein, müssen Sie einen solchen Server konfigurieren. + Ich habe bereits ein Benutzerkonto + Vernetz dich mit jedem. + Besitze deine Konversationen. + Richtlinie + Um bestehende Kontakte ermitteln zu können, müssen Sie Kontaktinformationen (E-Mails und Telefonnummern) an Ihren Identitätsserver senden. Wir verschlüsseln deine Daten vor dem Senden, um den Datenschutz zu gewährleisten. + Um bestehende Kontakte zu ermitteln, müssen Sie Kontaktinformationen an deinen Identitätsserver senden. +\n +\nWir verschlüsseln deine Daten vor dem Senden, um den Datenschutz zu gewährleisten. Bist du damit einverstanden, diese Informationen zu senden\? + Deine Kontakte sind privat. Um in deinen Kontakten Benutzer erkennen zu können, benötigen wir deine Erlaubnis, Kontaktinformationen an deinen Identitätsserver zu senden. + Dieser Server stellt keine Richtlinie bereit. + Deine Identitätsserver Richtlinie + Deine Heimserver Richtlinie + ${app_name} Richtlinie \ No newline at end of file From ee1c598e54badc3f30ff1b378509dbfced057241 Mon Sep 17 00:00:00 2001 From: libexus Date: Sun, 16 Jan 2022 13:18:59 +0000 Subject: [PATCH 033/222] Translated using Weblate (German) Currently translated at 98.4% (2688 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index a6ff9f7c39..2245b48304 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -306,7 +306,7 @@ Sprachanruf Videoanruf Globale Suche - Alle als gelesen markieren + Alles als gelesen markieren Archiv Antworten Öffnen @@ -496,7 +496,7 @@ Erstellen Online Offline - Untätig + Abwesend ADMIN-WERKZEUGE ANRUFE DIREKT-CHATS @@ -978,8 +978,8 @@ Bitte öffne ${app_name} auf einem anderen Gerät, das die Nachricht entschlüsseln kann, damit es die Schlüssel an diese Sitzung senden kann. Hier tippen… Sprachnachricht senden - Öffnen mit… - Es wurde keine externe Anwendung gefunden, um diese Aktion auszuführen. + Fortfahren mit… + Es wurde keine externe App gefunden, um diese Aktion auszuführen. Sende Sprachnachrichten Bitte gib dein Passwort ein. Schreibe bitte auf Englisch, wenn möglich. @@ -2122,7 +2122,7 @@ Echtzeitverbindung konnte nicht hergestellt werden. \nBitte den Administrator deines Homeservers, einen TURN-Server zu konfigurieren, dass Anrufe zuverlässig funktionieren. Audiogerät auswählen - Telefonie + Telefon Lautsprecher Kopfhörer Drahtloser Kopfhörer @@ -2941,7 +2941,7 @@ Welche Räume willst du verlassen\? Einrichtung beenden Nicht verfügbar - Offline + Abwesend Online %1$s Klicke zum Zurückkehren Nicht erreicht From b193ccd95127edafc576baf99a39839a14dff5ad Mon Sep 17 00:00:00 2001 From: p_0g_8mm3_ Date: Sun, 16 Jan 2022 13:17:24 +0000 Subject: [PATCH 034/222] Translated using Weblate (German) Currently translated at 98.4% (2688 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index 2245b48304..9162c28dcf 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -2161,7 +2161,7 @@ Backup einrichten Backup zurücksetzen Auf diesem Gerät einrichten - Verlust verschlüsselter Nachrichten & Daten verhindern, indem die Schlüssel für die Entschlüsselung am Server gesichert werden. + Verlust verschlüsselter Nachrichten & Daten verhindern, indem die Schlüssel für die Entschlüsselung auf dem Server gesichert werden. Generiere einen neuen Sicherheitsschlüssel oder setze eine neue Sicherheitspassphrase für dein existierendes Backup. Dieses wird deinen aktuellen Schlüssel oder deine aktuelle Phrase ersetzen. Integrationen sind deaktiviert From 0ac2ce10a88eb8ea8e849fe78b88866d27a06e99 Mon Sep 17 00:00:00 2001 From: Lamdarer Date: Sun, 16 Jan 2022 13:16:07 +0000 Subject: [PATCH 035/222] Translated using Weblate (German) Currently translated at 98.4% (2688 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index 9162c28dcf..32a734a7a1 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -2149,9 +2149,9 @@ Bist du dir sicher, dass du die Einladung für diesen Benutzer zurückziehen möchtest\? Benutzer entfernen Grund für das Entfernen - Du entfernst diese Person aus dem Raum. + Dies Entfernen den Benutzer aus diesem Raum. \n -\nBanne sie stattdessen, um erneutes Beitreten zu verhindern. +\nUm einen erneuten Beitritt zu verhindern, solltest du ihn stattdessen bannen. Benutzer bannen Grund für den Bann Bann des Benutzers aufheben From 21bafe3735b8b3856603b70dbfe508083d99b298 Mon Sep 17 00:00:00 2001 From: Dwaris Date: Sun, 16 Jan 2022 13:15:22 +0000 Subject: [PATCH 036/222] Translated using Weblate (German) Currently translated at 98.4% (2688 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index 32a734a7a1..c85847d0c4 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -480,7 +480,7 @@ Betreten Vorschau Ablehnen - Zur ersten ungelesenen Nachricht + Zu ungelesenen Nachrichten springen Du wurdest von %s in diesen Raum eingeladen Diese Einladung wurde an %s gesendet, welche nicht mit diesem Konto verknüpft ist. \nDu kannst dich mit einem anderen Konto anmelden oder diese E-Mail-Adresse zu diesem Konto hinzufügen. From 5581e0b5baa5dbc8119570989f0bd6c21e34690f Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 17 Jan 2022 18:30:04 +0300 Subject: [PATCH 037/222] Code review fixes. --- .../room/model/message/LocationInfo.kt | 2 +- .../BottomSheetMessagePreviewItem.kt | 7 ++- .../format/DisplayableEventFormatter.kt | 3 ++ .../timeline/helper/LocationPinProvider.kt | 6 +-- .../timeline/item/MessageLocationItem.kt | 15 +++--- .../im/vector/app/features/location/Config.kt | 21 ++++++++ .../app/features/location/LocationData.kt | 13 ----- .../location/LocationPreviewFragment.kt | 16 +++---- .../location/LocationSharingAction.kt | 1 + .../location/LocationSharingFragment.kt | 28 +++++++---- .../location/LocationSharingViewModel.kt | 12 +++-- .../app/features/location/LocationTracker.kt | 20 ++++---- .../app/features/location/MapTilerMapView.kt | 4 +- .../app/features/location/VectorMapView.kt | 6 +-- .../features/settings/VectorPreferences.kt | 2 +- .../item_bottom_sheet_message_preview.xml | 2 +- .../item_timeline_event_location_stub.xml | 48 +++++++++++-------- vector/src/main/res/values/strings.xml | 5 +- .../res/xml/vector_settings_preferences.xml | 2 +- 19 files changed, 123 insertions(+), 90 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/location/Config.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt index 5110926294..a1fd3bd2ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationInfo.kt @@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class LocationInfo( /** - * Required. Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location. + * Required. RFC5870 formatted geo uri 'geo:latitude,longitude;uncertainty' like 'geo:40.05,29.24;30' representing this location. */ @Json(name = "uri") val geoUri: String? = null, diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index b5ac82e4e5..beb52d3082 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -36,7 +36,6 @@ import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess import im.vector.app.features.location.LocationData import im.vector.app.features.location.MapTilerMapView -import im.vector.app.features.location.VectorMapListener import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.util.MatrixItem @@ -101,15 +100,15 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel - holder.mapView.initialize(object : VectorMapListener { - override fun onMapReady() { + holder.mapView.initialize { + if (holder.view.isAttachedToWindow) { holder.mapView.zoomToLocation(location.latitude, location.longitude, 15.0) locationPinProvider?.create(matrixItem.id) { pinDrawable -> holder.mapView.addPinToMap(matrixItem.id, pinDrawable) holder.mapView.updatePinLocation(matrixItem.id, location.latitude, location.longitude) } } - }) + } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt index 3892bfff85..d5f3a74e4e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt @@ -89,6 +89,9 @@ class DisplayableEventFormatter @Inject constructor( MessageType.MSGTYPE_FILE -> { simpleFormat(senderName, stringProvider.getString(R.string.sent_a_file), appendAuthor) } + MessageType.MSGTYPE_LOCATION -> { + simpleFormat(senderName, stringProvider.getString(R.string.sent_location), appendAuthor) + } else -> { simpleFormat(senderName, messageContent.body, appendAuthor) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt index 92a4bb8473..2820f07b34 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/LocationPinProvider.kt @@ -23,10 +23,10 @@ import androidx.core.content.ContextCompat import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition import im.vector.app.R +import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.glide.GlideApp import im.vector.app.features.home.AvatarRenderer import org.billcarsonfr.jsonviewer.Utils -import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject import javax.inject.Singleton @@ -34,7 +34,7 @@ import javax.inject.Singleton @Singleton class LocationPinProvider @Inject constructor( private val context: Context, - private val session: Session, + private val activeSessionHolder: ActiveSessionHolder, private val avatarRenderer: AvatarRenderer ) { private val cache = mutableMapOf() @@ -49,7 +49,7 @@ class LocationPinProvider @Inject constructor( return } - session.getUser(userId)?.toMatrixItem()?.let { + activeSessionHolder.getActiveSession().getUser(userId)?.toMatrixItem()?.let { val size = Utils.dpToPx(44, context) avatarRenderer.render(glideRequests, it, object : CustomTarget(size, size) { override fun onResourceReady(resource: Drawable, transition: Transition?) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt index d8ccf3761e..3f030866a5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -25,7 +25,6 @@ import im.vector.app.core.epoxy.onClick import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider import im.vector.app.features.location.LocationData import im.vector.app.features.location.MapTilerMapView -import im.vector.app.features.location.VectorMapListener @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageLocationItem : AbsMessageItem() { @@ -58,16 +57,14 @@ abstract class MessageLocationItem : AbsMessageItem( } holder.mapView.apply { - initialize(object : VectorMapListener { - override fun onMapReady() { - zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) + initialize { + zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) - locationPinProvider?.create(locationOwnerId) { pinDrawable -> - addPinToMap(locationOwnerId, pinDrawable) - updatePinLocation(locationOwnerId, location.latitude, location.longitude) - } + locationPinProvider?.create(locationOwnerId) { pinDrawable -> + addPinToMap(locationOwnerId, pinDrawable) + updatePinLocation(locationOwnerId, location.latitude, location.longitude) } - }) + } } } diff --git a/vector/src/main/java/im/vector/app/features/location/Config.kt b/vector/src/main/java/im/vector/app/features/location/Config.kt new file mode 100644 index 0000000000..630df16a37 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/location/Config.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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.location + +const val INITIAL_MAP_ZOOM = 15.0 +const val MIN_TIME_MILLIS_TO_UPDATE_LOCATION = 1 * 60 * 1000L // every 1 minute +const val MIN_DISTANCE_METERS_TO_UPDATE_LOCATION = 10f diff --git a/vector/src/main/java/im/vector/app/features/location/LocationData.kt b/vector/src/main/java/im/vector/app/features/location/LocationData.kt index b790bde710..3233e8f721 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationData.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationData.kt @@ -26,19 +26,6 @@ data class LocationData( val uncertainty: Double? ) : Parcelable { - fun toGeoUri(): String { - return buildString { - append("geo:") - append(latitude) - append(",") - append(longitude) - append("?q=") - append(latitude) - append(",") - append(longitude) - } - } - companion object { /** diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt index 1a7ed49209..f3914fbc2c 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt @@ -31,7 +31,7 @@ import javax.inject.Inject class LocationPreviewFragment @Inject constructor( private val locationPinProvider: LocationPinProvider -) : VectorBaseFragment(), VectorMapListener { +) : VectorBaseFragment() { private val args: LocationSharingArgs by args() @@ -42,7 +42,11 @@ class LocationPreviewFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.mapView.initialize(this) + views.mapView.initialize { + if (isAdded) { + onMapReady() + } + } } override fun getMenuRes() = R.menu.menu_location_preview @@ -62,21 +66,17 @@ class LocationPreviewFragment @Inject constructor( openLocation(requireActivity(), location.latitude, location.longitude) } - override fun onMapReady() { + private fun onMapReady() { val location = args.initialLocationData ?: return val userId = args.locationOwnerId locationPinProvider.create(userId) { pinDrawable -> views.mapView.apply { - zoomToLocation(location.latitude, location.longitude, INITIAL_ZOOM) + zoomToLocation(location.latitude, location.longitude, INITIAL_MAP_ZOOM) deleteAllPins() addPinToMap(userId, pinDrawable) updatePinLocation(userId, location.latitude, location.longitude) } } } - - companion object { - const val INITIAL_ZOOM = 15.0 - } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt index 0efaefaa5b..71101d0612 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt @@ -21,4 +21,5 @@ import im.vector.app.core.platform.VectorViewModelAction sealed class LocationSharingAction : VectorViewModelAction { data class OnLocationUpdate(val locationData: LocationData) : LocationSharingAction() object OnShareLocation : LocationSharingAction() + object OnLocationProviderIsNotAvailable : LocationSharingAction() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index c7c4c0fed1..d3ccbf914e 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -20,9 +20,10 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.airbnb.mvrx.activityViewModel +import com.airbnb.mvrx.fragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R +import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentLocationSharingBinding import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider @@ -33,13 +34,13 @@ class LocationSharingFragment @Inject constructor( private val locationTracker: LocationTracker, private val session: Session, private val locationPinProvider: LocationPinProvider -) : VectorBaseFragment(), LocationTracker.Callback, VectorMapListener { +) : VectorBaseFragment(), LocationTracker.Callback { init { locationTracker.callback = this } - private val viewModel: LocationSharingViewModel by activityViewModel() + private val viewModel: LocationSharingViewModel by fragmentViewModel() private var lastZoomValue: Double = -1.0 @@ -50,7 +51,11 @@ class LocationSharingFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - views.mapView.initialize(this) + views.mapView.initialize { + if (isAdded) { + onMapReady() + } + } views.shareLocationContainer.debouncedClicks { viewModel.handle(LocationSharingAction.OnShareLocation) @@ -60,7 +65,7 @@ class LocationSharingFragment @Inject constructor( when (it) { LocationSharingViewEvents.LocationNotAvailableError -> handleLocationNotAvailableError() LocationSharingViewEvents.Close -> activity?.finish() - } + }.exhaustive } } @@ -69,7 +74,7 @@ class LocationSharingFragment @Inject constructor( locationTracker.stop() } - override fun onMapReady() { + private fun onMapReady() { locationPinProvider.create(session.myUserId) { views.mapView.addPinToMap( pinId = USER_PIN_NAME, @@ -81,7 +86,7 @@ class LocationSharingFragment @Inject constructor( } override fun onLocationUpdate(locationData: LocationData) { - lastZoomValue = if (lastZoomValue == -1.0) INITIAL_ZOOM else views.mapView.getCurrentZoom() ?: INITIAL_ZOOM + lastZoomValue = if (lastZoomValue == -1.0) INITIAL_MAP_ZOOM else views.mapView.getCurrentZoom() ?: INITIAL_MAP_ZOOM views.mapView.zoomToLocation(locationData.latitude, locationData.longitude, lastZoomValue) views.mapView.deleteAllPins() @@ -90,16 +95,21 @@ class LocationSharingFragment @Inject constructor( viewModel.handle(LocationSharingAction.OnLocationUpdate(locationData)) } + override fun onLocationProviderIsNotAvailable() { + viewModel.handle(LocationSharingAction.OnLocationProviderIsNotAvailable) + } + private fun handleLocationNotAvailableError() { MaterialAlertDialogBuilder(requireActivity()) .setTitle(R.string.location_not_available_dialog_title) .setMessage(R.string.location_not_available_dialog_content) - .setPositiveButton(R.string.ok, null) + .setPositiveButton(R.string.ok) { _, _ -> + activity?.finish() + } .show() } companion object { - const val INITIAL_ZOOM = 15.0 const val USER_PIN_NAME = "USER_PIN_NAME" } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt index 4525cac446..b3c97310e1 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt @@ -22,6 +22,7 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.session.Session @@ -42,9 +43,10 @@ class LocationSharingViewModel @AssistedInject constructor( override fun handle(action: LocationSharingAction) { when (action) { - is LocationSharingAction.OnLocationUpdate -> handleLocationUpdate(action.locationData) - LocationSharingAction.OnShareLocation -> handleShareLocation() - } + is LocationSharingAction.OnLocationUpdate -> handleLocationUpdate(action.locationData) + LocationSharingAction.OnShareLocation -> handleShareLocation() + LocationSharingAction.OnLocationProviderIsNotAvailable -> handleLocationProviderIsNotAvailable() + }.exhaustive } private fun handleShareLocation() = withState { state -> @@ -65,4 +67,8 @@ class LocationSharingViewModel @AssistedInject constructor( copy(lastKnownLocation = locationData) } } + + private fun handleLocationProviderIsNotAvailable() { + _viewEvents.post(LocationSharingViewEvents.LocationNotAvailableError) + } } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt index a669381981..0c0315cf34 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationTracker.kt @@ -27,15 +27,18 @@ import timber.log.Timber import javax.inject.Inject class LocationTracker @Inject constructor( - private val context: Context) : LocationListener { + private val context: Context +) : LocationListener { interface Callback { fun onLocationUpdate(locationData: LocationData) + fun onLocationProviderIsNotAvailable() } private var locationManager: LocationManager? = null var callback: Callback? = null + @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION]) fun start() { val locationManager = context.getSystemService() @@ -47,6 +50,7 @@ class LocationTracker @Inject constructor( isGpsEnabled -> LocationManager.GPS_PROVIDER isNetworkEnabled -> LocationManager.NETWORK_PROVIDER else -> { + callback?.onLocationProviderIsNotAvailable() Timber.v("## LocationTracker. There is no location provider available") return } @@ -54,16 +58,17 @@ class LocationTracker @Inject constructor( // Send last known location without waiting location updates it.getLastKnownLocation(provider)?.let { lastKnownLocation -> - callback?.onLocationUpdate(LocationData(lastKnownLocation.latitude, lastKnownLocation.longitude, lastKnownLocation.accuracy.toDouble())) + callback?.onLocationUpdate(lastKnownLocation.toLocationData()) } it.requestLocationUpdates( provider, - MIN_TIME_MILLIS_TO_UPDATE, - MIN_DISTANCE_METERS_TO_UPDATE, + MIN_TIME_MILLIS_TO_UPDATE_LOCATION, + MIN_DISTANCE_METERS_TO_UPDATE_LOCATION, this ) } ?: run { + callback?.onLocationProviderIsNotAvailable() Timber.v("## LocationTracker. LocationManager is not available") } } @@ -75,11 +80,10 @@ class LocationTracker @Inject constructor( } override fun onLocationChanged(location: Location) { - callback?.onLocationUpdate(LocationData(location.latitude, location.longitude, location.accuracy.toDouble())) + callback?.onLocationUpdate(location.toLocationData()) } - companion object { - const val MIN_TIME_MILLIS_TO_UPDATE = 1 * 60 * 1000L // every 1 minute - const val MIN_DISTANCE_METERS_TO_UPDATE = 10f + private fun Location.toLocationData(): LocationData { + return LocationData(latitude, longitude, accuracy.toDouble()) } } diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index 386e96988f..c64af1ebaa 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -39,13 +39,13 @@ class MapTilerMapView @JvmOverloads constructor( private var symbolManager: SymbolManager? = null private var style: Style? = null - override fun initialize(listener: VectorMapListener) { + override fun initialize(onMapReady: () -> Unit) { getMapAsync { map -> map.setStyle(styleUrl) { style -> this.symbolManager = SymbolManager(this, map, style) this.map = map this.style = style - listener.onMapReady() + onMapReady() } } } diff --git a/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt b/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt index 5dbeced175..23b59bf99a 100644 --- a/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/VectorMapView.kt @@ -18,12 +18,8 @@ package im.vector.app.features.location import android.graphics.drawable.Drawable -interface VectorMapListener { - fun onMapReady() -} - interface VectorMapView { - fun initialize(listener: VectorMapListener) + fun initialize(onMapReady: () -> Unit) fun addPinToMap(pinId: String, image: Drawable) fun updatePinLocation(pinId: String, latitude: Double, longitude: Double) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 4db99c9a74..67d26231b2 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1000,6 +1000,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { } fun isLocationSharingEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_PREF_ENABLE_LOCATION_SHARING, true) + return defaultPrefs.getBoolean(SETTINGS_PREF_ENABLE_LOCATION_SHARING, false) } } diff --git a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml index 1959cfc3ba..0b61ae2548 100644 --- a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml +++ b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml @@ -108,7 +108,7 @@ android:layout_width="0dp" android:layout_height="200dp" android:layout_marginTop="6dp" - android:importantForAccessibility="no" + android:contentDescription="@string/attachment_type_location" android:scaleType="centerCrop" android:visibility="gone" app:layout_constraintEnd_toEndOf="@id/bottom_sheet_message_preview_timestamp" diff --git a/vector/src/main/res/layout/item_timeline_event_location_stub.xml b/vector/src/main/res/layout/item_timeline_event_location_stub.xml index 0b211ec5e0..d989ad72af 100644 --- a/vector/src/main/res/layout/item_timeline_event_location_stub.xml +++ b/vector/src/main/res/layout/item_timeline_event_location_stub.xml @@ -1,26 +1,34 @@ - + android:layout_height="wrap_content" + app:cardCornerRadius="8dp"> - + - + - + + + + + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 78f6c9209a..2720b3c20b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2755,6 +2755,7 @@ Poll Reacted with: %s Verification Conclusion + Shared their location Waiting… %s cancelled @@ -3704,8 +3705,8 @@ Location Share location Share location - Element could not access your location - Element could not access your location. Please try again later. + ${app_name} could not access your location + ${app_name} could not access your location. Please try again later. Open with Enable location sharing diff --git a/vector/src/main/res/xml/vector_settings_preferences.xml b/vector/src/main/res/xml/vector_settings_preferences.xml index bc9e06f754..fd5c6f6062 100644 --- a/vector/src/main/res/xml/vector_settings_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_preferences.xml @@ -29,7 +29,7 @@ android:title="@string/font_size" /> From 23eb8ead4f2dcf6e5465f3b286ef06f8fe2c6333 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Jan 2022 16:30:43 +0100 Subject: [PATCH 038/222] Add case for local or non public homeserver. --- .github/ISSUE_TEMPLATE/bug.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index c4eccd5b1f..6b9e31071f 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -57,8 +57,9 @@ body: id: homeserver attributes: label: Homeserver - description: Which server is your account registered on? - placeholder: e.g. matrix.org + description: | + Which server is your account registered on? If it is a local or non public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and its version. + placeholder: e.g. matrix.org or Synapse 1.50.0rc1 validations: required: false - type: dropdown From 5ce2d4bcd3971c9386564e1179b12f17d82eda63 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Jan 2022 19:16:38 +0000 Subject: [PATCH 039/222] Translated using Weblate (German) Currently translated at 98.9% (2700 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- vector/src/main/res/values-de/strings.xml | 28 +++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index c85847d0c4..d98eeec339 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -2149,9 +2149,9 @@ Bist du dir sicher, dass du die Einladung für diesen Benutzer zurückziehen möchtest\? Benutzer entfernen Grund für das Entfernen - Dies Entfernen den Benutzer aus diesem Raum. + Dies entfernt den Benutzer aus diesem Raum. \n -\nUm einen erneuten Beitritt zu verhindern, solltest du ihn stattdessen bannen. +\nUm einen erneuten Beitritt zu verhindern, solltest du diesen stattdessen bannen. Benutzer bannen Grund für den Bann Bann des Benutzers aufheben @@ -2944,7 +2944,7 @@ Abwesend Online %1$s Klicke zum Zurückkehren - Nicht erreicht + Nicht abgenommen Nachricht mit ( ͡° ͜ʖ ͡°) beginnen Zeigt Information über die Person an Ändert dein Profilbild im aktuellen Raum @@ -3030,7 +3030,7 @@ Dies macht es für Räume einfach, privat in einem Space zu bleiben, während die Leute im Space diese finden und ihnen beitreten können. Alle neuen Räume in einem Raum haben diese Option zur Verfügung. Helfen Sie Personen in Spaces, private Räume selbst zu finden und ihnen beizutreten, damit Sie nicht alle manuell einladen müssen. Neu: Personen in Spaces können private Räume finden und ihnen beitreten - Das System sendet automatisch Protokolle, wenn ein Fehler bei der Entschlüsselung auftritt. + Das System sendet automatisch Protokolle, wenn ein Fehler bei der Entschlüsselung auftritt Automatische Meldung von Entschlüsselungsfehlern. Auffindbarkeit (%s) Per E-Mail einladen, finde Kontakte und mehr… @@ -3049,4 +3049,24 @@ Deine Identitätsserver Richtlinie Deine Heimserver Richtlinie ${app_name} Richtlinie + Erstelle eine Abstimmung + Öffne die Kontakte + Sticker verschicken + Datei hochladen + Verschicke Fotos und Videos + Kamera öffnen + Sind Sie sicher, dass Sie diese Umfrage entfernen möchten\? Sie können diese Umfrage nicht wiederherstellen, sobald sie entfernt wurde. + Abstimmung entfernen + Abstimmung beendet + Stimme abgegeben + Aktiviere Abstimmungen + Abstimmung beenden + Dies verhindert, dass andere Personen abstimmen können, und zeigt die Endergebnisse der Umfrage an. + Diese Abstimmung beenden\? + Gewinneroption + Abstimmung beenden + + Endgültiges Ergebnis basierend auf %1$d Abstimmung + Endgültiges Ergebnis basierend auf %1$d Abstimmungen + \ No newline at end of file From cce8234c6f827ce67f07af7a34b453045e2dea9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sat, 15 Jan 2022 14:16:18 +0000 Subject: [PATCH 040/222] Translated using Weblate (Estonian) Currently translated at 99.9% (2727 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index 663212727d..c88275b9f6 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -4,7 +4,7 @@ %1$s saatis pildi. %1$s saatis kleepsu. Kasutaja %s kutse - %1$s kutsus kasutajat %2$s + %1$s saatis kutse kasutajale %2$s %1$s kutsus sind %1$s liitus jututoaga %1$s lahkus jututoast @@ -81,7 +81,7 @@ Saadan sõnumit… Tühjenda saatmisjärjekord Kasutaja %1$s kutse. Põhjus: %2$s - %1$s kutsus kasutajat %2$s. Põhjus: %3$s + %1$s saatis kutse kasutajale %2$s. Põhjus: %3$s %1$s kutsus sind. Põhjus: %2$s %1$s liitus jututoaga. Põhjus: %2$s %1$s lahkus jututoast. Põhjus: %2$s @@ -201,7 +201,7 @@ Sina võtsid tagasi jututoaga liitumise kutse kasutajalt %1$s %1$s võttis tagasi jututoaga liitumise kutse kasutajalt %2$s Sina kutsusid kasutajat %1$s - %1$s kutsus kasutajat %2$s + %1$s saatis kutse kasutajale %2$s Sa uuendasid seda jututuba. %s uuendas seda jututuba. Sina seadistasid, et tulevased jututoa sõnumid on nähtavad kasutajale %1$s @@ -2161,7 +2161,7 @@ Kui sa võtad kasutusele konto koduserveris, siis sisesta alljärgnevalt oma Matrix\'i kasutajatunnus (näiteks @torekasutaja:domeen.ee) ja salasõna. Matrix\'i kasutajatunnus Kui sa ei tea oma salasṍna, siis mine tagasi ja loo uus salasõna. - Nähtud kasutaja poolt + Seda nägi(d) Sa oled loginud välja See võib juhtuda eri põhjustel: \n From 67b2e8378af5c734d41d14aa7d4626cb48035816 Mon Sep 17 00:00:00 2001 From: Linerly Date: Sat, 15 Jan 2022 00:13:59 +0000 Subject: [PATCH 041/222] Translated using Weblate (Indonesian) Currently translated at 100.0% (2729 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index 4502d15c23..59b0079878 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -3018,7 +3018,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Elemen berfungsi dengan semua aplikasi berbasis Matrix dan bahkan dapat menjembatani ke perpesanan sumber tertutup. Hubung dengan siapa pun. Elemen memungkinkan Anda untuk memilih di mana pesan Anda disimpan, membuat Anda tetap mengendali data Anda. - Anda mengendalikannya. + Anda dalam kendali. Perpesanan terenkripsi secara ujung-ke-ujung untuk komunikasi aman dan independen, terhubung via Matrix. Miliki percakapan Anda. \ No newline at end of file From 039e1dd6adfecc24efcc2d72023e071d03d51811 Mon Sep 17 00:00:00 2001 From: Johan Smits Date: Sat, 15 Jan 2022 13:30:07 +0000 Subject: [PATCH 042/222] Translated using Weblate (Dutch) Currently translated at 93.5% (2553 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/nl/ --- vector/src/main/res/values-nl/strings.xml | 547 ++++++++++++++++++++++ 1 file changed, 547 insertions(+) diff --git a/vector/src/main/res/values-nl/strings.xml b/vector/src/main/res/values-nl/strings.xml index e1b0481913..6ca8adb794 100644 --- a/vector/src/main/res/values-nl/strings.xml +++ b/vector/src/main/res/values-nl/strings.xml @@ -2329,4 +2329,551 @@ Inschakelen Luisteren naar notificaties U mag niet deelnemen aan deze kamer + Gebeurtenis status verzonden! + Gebeurtenis verzonden! + Misvormde gebeurtenis + Ontbrekend berichttype + Geen content + Event inhoud + Statussleutel + Aangepaste statusgebeurtenis verzenden + Inhoud bewerken + Staat evenementen + Statusgebeurtenis verzenden + Aangepaste gebeurtenis verzenden + Kamerstatus verkennen + Ontwikkel tools + Niet beschikbaar + Offline + Online + Openbare space + Openbare kamer + Leesbevestigingen bekijken + Niet melden + Melden zonder geluid + Melden met geluid + Bericht niet verzonden wegens fout + Emoji kiezer sluiten + Emoji kiezer openen + Vertrouwd vertrouwensniveau + Waarschuwing vertrouwensniveau + Standaard vertrouwensniveau + heeft niet verzonden concept + Sommige berichten zijn niet verzonden + Avatar verwijderen + Verander avatar + Sleutel importeren uit bestand + Widgets openen + Authenticatie mislukt + ${app_name} vereist dat u uw inloggegevens invoert om deze actie uit te voeren. + Opnieuw authenticatie nodig + Schuif om het gesprek te beëindigen + Onbekend persoon + Doorverbinden naar %1$s + Overleg met %1$s + Er is een fout opgetreden tijdens het doorverbinden van een gesprek + Eerst overleggen + %1$s Tik om terug te keren + Actieve oproep (%1$s) · + + Actieve oproep · + %1$d actieve gesprekken · + + + 1 actief gesprek (%1$s) · 1 onderbroken gesprek + 1 actief gesprek (%1$s) · %2$d gepauzeerde gesprekken + + + Gepauzeerd gesprek + %1$d gepauzeerde gesprekken + + Actieve oproep (%1$s) + Er is een fout opgetreden bij het opzoeken van het telefoonnummer + Toetsenblok + Verbinding mislukt + Geen antwoord + Gemist videogesprek + Gemiste spraakoproep + Videogesprek geweigerd + Spraakoproep geweigerd + Videogesprek beëindigd • %1$s + Spraakoproep beëindigd • %1$s + Actief videogesprek + Actieve spraakoproep + Inkomend videogesprek + Inkomende spraakoproep + Terugbellen + Dit gesprek is beëindigd + %1$s heeft dit gesprek geweigerd + U heeft deze oproep geweigerd + U bent een gesprek begonnen + U bent momenteel in dit gesprek + U heeft deze oproep %s . geweigerd + %1$s heeft een gesprek gestart + Matrix Link + Veranderingen ongedaan maken + Er zijn niet opgeslagen wijzigingen. De wijzigingen negeren\? + De kamer is nog niet aangemaakt. Het aanmaken van een kamer annuleren\? + De link was verkeerd ingedeeld + QR-code niet gescand! + Ongeldige QR-code (ongeldige URI)! + U kunt uzelf niet DM\'en! + Deel via tekst + Kan deze kamer niet vinden. Zorg ervoor dat het bestaat. + U kunt geen kamer openen waar u uit bent verbannen. + Bevestig pincode om pincode uit te schakelen + Wijzig uw huidige pincode + Verander pincode + Elke keer dat u ${app_name} opent, is een pincode vereist. + Pincode is vereist na 2 minuten ${app_name} niet te hebben gebruikt. + Pincode vereist na 2 minuten + Geef alleen het aantal ongelezen berichten weer in een eenvoudige melding. + Toon details zoals kamernamen en berichtinhoud. + Inhoud in meldingen weergeven + Pincode is de enige manier om ${app_name} te ontgrendelen. + Schakel apparaatspecifieke biometrische gegevens in, zoals vingerafdrukken en gezichtsherkenning. + Biometrische gegevens inschakelen + Als u uw pincode opnieuw wilt instellen, tikt u op Pincode vergeten om uit te loggen en opnieuw in te stellen. + Pincode inschakelen + Beveiliging configureren + Beveilig de toegang met pincode en biometrie. + Toegang beveiligen + Om uw pincode opnieuw in te stellen, moet u opnieuw inloggen en een nieuwe maken. + Voer uw pincode in + Kan pincode niet valideren. Tik voor een nieuwe. + Kies een pincode voor beveiliging + Te veel fouten, u bent uitgelogd + Waarschuwing! Laatste resterende poging voor uitloggen! + + %d invoer + %d ingaven + + + Verkeerde code, %d resterende poging + Verkeerde code, %d resterende pogingen + + Controleer uw instellingen om pushmeldingen in te schakelen + Pushmeldingen zijn uitgeschakeld + Kan gebruiker verbanning niet opheffen + Verbannen door %1$s + Uitnodiging voor %1$s intrekken\? + Zoeken naar contacten op Matrix + Uw contactenboek is leeg + Uw contacten ophalen… + Zoek in mijn contacten + Uw telefoonboek is leeg + Toevoegen vanuit mijn telefoonboek + Herstelsleutel opslaan in + LEER MEER + BEGREPEN + We zijn verheugd om aan te kondigen dat we van naam zijn veranderd! Uw app is up-to-date en u bent ingelogd op uw account. + Riot is nu Element! + Wachten op versleutelingsgeschiedenis + U heeft geen toegang tot dit bericht omdat de afzender de sleutels met opzet niet heeft verzonden + U heeft geen toegang tot dit bericht omdat u bent geblokkeerd door de afzender + U heeft geen toegang tot dit bericht omdat uw sessie niet wordt vertrouwd door de afzender + Vanwege end-to-end versleuteling moet u mogelijk wachten op het bericht van iemand omdat de coderingssleutels niet correct naar u zijn verzonden. + Wachten op dit bericht, dit kan even duren + U heeft geen toegang tot dit bericht + Avatar instellen + Je hebt de kamerinstellingen met succes gewijzigd + Bewaar uw beveiligingssleutel ergens veilig, zoals een wachtwoordbeheerder of een kluis. + Bewaar uw beveiligingssleutel + Voer uw beveiligingszin nogmaals in om deze te bevestigen. + Voer een beveiligingszin in die alleen u kent en die wordt gebruikt om geheimen op uw server te beveiligen. + Stel een beveiligingszin in + Bewaar uw beveiligingssleutel ergens veilig, zoals een wachtwoordbeheerder of een kluis. + Bewaar uw beveiligingssleutel + Voer een geheime zin in die alleen u kent en genereer een sleutel voor back-up. + Gebruik een beveiligingszin + Genereer een beveiligingssleutel om ergens veilig op te slaan, zoals een wachtwoordbeheerder of een kluis. + Een beveiligingssleutel gebruiken + Bescherm uzelf tegen verlies van toegang tot versleutelde berichten en gegevens door een back-up te maken van versleutelingssleutels op uw server. + Beveiligde back-up instellen + Start de camera + Stop de camera + Dempen van de microfoon opheffen + De microfoon dempen + Voer de URL van een identiteitsserver in + U kunt ook een andere identiteitsserver URL invoeren + Uw thuisserver (%1$s) stelt voor om %2$s te gebruiken voor uw identiteitsserver + De toestemming van de gebruiker is niet gegeven. + Er is geen huidige associatie met dit id. + De associatie heeft gefaald. + Voor uw privacy ondersteunt ${app_name} alleen het verzenden van gehashte e-mailadressen en telefoonnummers van gebruikers. + Accepteer eerst de voorwaarden van de identiteitsserver in de instellingen. + Configureer eerst een identiteitsserver. + Deze operatie is niet mogelijk. De thuisserver is verouderd. + Deze identiteitsserver is verouderd. ${app_name} ondersteunt alleen API V2. + Verbinding met identiteitsserver %s verbreken\? + Open voorwaarden van %s + Beschikbare talen laden… + Andere beschikbare talen + Deel deze code met mensen zodat ze deze kunnen scannen om u toe te voegen en te beginnen met chatten. + Mijn code + Deel mijn code + Scan een QR-code + We kunnen geen gebruikers uitnodigen. Controleer de gebruikers die u wilt uitnodigen en probeer het opnieuw. + + Uitnodigingen verzonden naar %1$s en nog één + Uitnodigingen verzonden naar %1$s en %2$d meer + + Het is geen geldige matrix QR-code + Uitnodigingen verzonden naar %1$s en %2$s + Uitnodiging verzonden naar %1$s + 🔐️ Doe mee met ${app_name} + Hé, praat met me op ${app_name}: %s + Nodig vrienden uit + Mensen toevoegen + We kunnen je DM niet maken. Controleer de gebruikers die u wilt uitnodigen en probeer het opnieuw. + De link %1$s brengt u naar een andere site: %2$s. +\n +\nWeet u zeker dat u door wilt gaan\? + Dubbelcheck deze link + Kies een wachtwoord. + Kies een gebruikersnaam. + Kan kruislingsondertekenen niet instellen + Markeren als vertrouwd + Bevestig uw identiteit door deze login te verifiëren en deze toegang te verlenen tot versleutelde berichten. + Bevestig uw identiteit door deze login van een van uw andere sessies te verifiëren en toegang te verlenen tot versleutelde berichten. + Interactief verifiëren door Emoji + Handmatig verifiëren via tekst + Verifieer de nieuwe login voor toegang tot uw account: %1$s + Verifieer al je sessies om ervoor te zorgen dat je account en berichten veilig zijn + Bekijk waar je bent ingelogd + Versleuteld door een niet-geverifieerd apparaat + stuurt sneeuwval ❄️ + stuurt confetti 🎉 + Stuurt het gegeven bericht met sneeuwval + Stuurt het gegeven bericht met confetti + + Laat het apparaat zien waarmee u nu kunt verifiëren + %d apparaten weergeven waarmee u nu kunt verifiëren + + U start opnieuw op zonder geschiedenis, geen berichten, vertrouwde apparaten of vertrouwde gebruikers + Als je alles reset + Doe dit alleen als u geen ander apparaat heeft waarmee u dit apparaat kunt verifiëren. + Alle herstelopties vergeten of verloren\? Alles resetten + Kan geen toegang krijgen tot beveiligde opslag + Back-up kon niet worden gedecodeerd met deze herstelsleutel: controleer of u de juiste herstelsleutel hebt ingevoerd. + Selecteer uw herstelsleutel of voer deze handmatig in door deze te typen of te plakken vanaf uw klembord + Herstelsleutel gebruiken + Gebruik uw %1$s of gebruik uw %2$s om door te gaan. + Alleen ondersteund in versleutelde kamers + Dwingt dat de huidige uitgaande groepssessie in een versleutelde ruimte wordt weggegooid + Gebruik de nieuwste ${app_name} op uw andere apparaten: + of een andere Matrix client die kruislingsondetekenen ondersteunt + ${app_name} iOS +\n${app_name} Android + ${app_name} Web +\n${app_name} Desktop + Gebruik de nieuwste ${app_name} op uw andere apparaten, ${app_name} Web, ${app_name} Desktop, ${app_name} iOS, ${app_name} voor Android of een andere Matrix-client die geschikt is voor kruislingsondertekenen + Stel een nieuw accountwachtwoord in… + Kan mediabestand niet opslaan + Kan geen mediabestand aan de Galerij toevoegen + Mediabestand toegevoegd aan de Galerij + Als u deze instelling inschakelt, wordt de FLAG_SECURE aan alle activiteiten toegevoegd. Start de toepassing opnieuw om de wijziging door te voeren. + Voorkom screenshots van de applicatie + Sleutel Back-up herstelsleutel + Weet u uw Key Back-up wachtwoordzin niet, u kunt %s. + gebruik uw Backup-herstelsleutel + Voer uw Sleutel Back-up wachtwoordzin in om door te gaan. + Sleutelback-up geheim opslaan in SSSS + SSSS sleutel genereren uit herstelsleutel + SSSS sleutel genereren op basis van wachtwoordzin (%s) + SSSS sleutel genereren uit wachtwoordzin + Curvesleutel verkrijgen + Back-upsleutel controleren (%s) + Back-upsleutel controleren + Voer een herstelsleutel in + Het is geen geldige herstelsleutel + Voer uw %s in om door te gaan + Verifieer uzelf en anderen om uw chats veilig te houden + Kruisondertekening inschakelen + Encryptie upgrade beschikbaar + Dit account is gedeactiveerd. + Onjuiste gebruikersnaam en/of wachtwoord. Het ingevoerde wachtwoord begint of eindigt met spaties, controleer dit alstublieft. + Verzendt een bericht als platte tekst, zonder het als markdown te interpreteren + Stel het belang van meldingen in per gebeurtenis + Kan sleutels niet importeren + Wachten op %s… + Bijna daar! Op bevestiging wachten… + Bijna daar! Toont het andere apparaat een vinkje\? + Een onderwerp toevoegen + %s om mensen te laten weten waar deze kamer over gaat. + Dit is het begin van uw privéberichtgeschiedenis met %s. + Dit is het begin van dit gesprek. + Dit is het begin van %s. + U hebt de kamer gemaakt en geconfigureerd. + %s heeft de kamer gemaakt en geconfigureerd. + De versleuteling die door deze kamer wordt gebruikt, wordt niet ondersteund + Versleuteling niet ingeschakeld + Berichten in deze ruimte zijn end-to-end versleuteld. + Berichten in deze ruimte zijn end-to-end versleuteld. Lees meer en verifieer gebruikers in hun profiel. + Als u nu annuleert, kunt u versleutelde berichten en gegevens kwijtraken als u de toegang tot uw aanmeldingen verliest. +\n +\nU kunt ook Veilige back-up instellen en uw sleutels beheren in Instellingen. + Door een herstelwachtwoordzin in te stellen, kunt u versleutelde berichten beveiligen en ontgrendelen en vertrouwen. + Door een herstelwachtwoordzin in te stellen, kunt u versleutelde berichten beveiligen en ontgrendelen en vertrouwen. +\n +\nAls u geen berichtwachtwoord wilt instellen, genereert u in plaats daarvan een berichtsleutel. + Dat kan niet vanaf mobiel + Kopieer het naar uw persoonlijke cloudopslag + Bewaar het op een USB-stick of back-upstation + Print het uit en bewaar het ergens veilig + Uw %2$s en %1$s zijn nu ingesteld. +\n +\nHoud ze veilig! U heeft ze nodig om versleutelde berichten te ontgrendelen en informatie te beveiligen als u al uw actieve sessies verliest. + Sleutelback-up instellen + Zelfondertekenende sleutel synchroniseren + Gebruikerssleutel synchroniseren + Hoofdsleutel synchroniseren + SSSS standaardsleutel definiëren + Beveiligde sleutel genereren op basis van wachtwoordzin + Aangemaakte identiteitssleutels publiceren + Gebruik deze %1$s als een vangnet voor het geval u %2$s vergeet. + Hou het veilig + Uw herstelsleutel + Herstel instellen. + Dit kan enkele seconden duren, even geduld a.u.b. + Voer een beveiligingszin in die alleen u kent en die wordt gebruikt om geheimen op uw server te beveiligen. + Gebruik niet uw accountwachtwoord. + Voer uw %s opnieuw in om het te bevestigen. + Beveilig en ontgrendel versleutelde berichten en vertrouw met een %s. + Voer uw %s in om door te gaan. + Een berichtsleutel genereren + Stel een %s in + Verificatie is geannuleerd. U kunt de verificatie opnieuw starten. + Een van de volgende zaken kan worden aangetast: +\n +\n- Uw wachtwoord +\n- Uw thuisserver +\n- Dit apparaat, of het andere apparaat +\n- De internetverbinding die elk apparaat gebruikt +\n +\nWe raden u aan uw wachtwoord en herstelsleutel onmiddellijk in Instellingen te wijzigen. + U verifieert %1$s (%2$s) niet als u nu annuleert. Begin opnieuw in hun gebruikersprofiel. + Als u annuleert, kunt u geen versleutelde berichten op dit apparaat lezen en zullen andere gebruikers het niet vertrouwen + Als u annuleert, kunt u geen versleutelde berichten lezen op je nieuwe apparaat en zullen andere gebruikers het niet vertrouwen + Uw account is mogelijk gecompromitteerd + Dit was ik niet + Gebruik deze sessie om uw nieuwe te verifiëren en deze toegang te verlenen tot versleutelde berichten. + Tik om te controleren en te verifiëren + Nieuwe login. Was u dit\? + Ontgrendel de geschiedenis van versleutelde berichten + Exportcontrole + ${app_name} Android + Sleutels zijn al up-to-date! + Evenement gemodereerd door ruimtebeheerder, reden: %1$s + Evenement verwijderd door gebruiker, reden: %1$s + Reden voor redigeren + Geef een reden op + Weet u zeker dat u dit evenement wilt verwijderen (wissen)\? Houd er rekening mee dat als u een kamernaam of onderwerpwijziging verwijdert, de wijziging ongedaan kan worden gemaakt. + Media verzenden in het originele formaat + + Stuur video in het originele formaat + Stuur video\'s in het originele formaat + + + Stuur afbeelding in het originele formaat + Stuur afbeeldingen in het originele formaat + + Wilt u deze bijlage naar %1$s sturen\? + U mag alleen toegang krijgen tot geheime opslag vanaf een vertrouwd apparaat + Voer geheime wachtwoordzin voor opslag in + Kan geen geheimen vinden in opslag + Nieuwe aanmelding + Als je geen toegang hebt tot een bestaande sessie + Een herstelwachtwoordzin of -sleutel gebruiken + Maakt een eenvoudige peiling + De accountgegevens van het type %1$s verwijderen\? +\n +\nWees voorzichtig, het kan leiden tot onverwacht gedrag. + Vliegtuigmodus is ingeschakeld + Verbinding met de server is verbroken + Bijna daar! Toont %s een vinkje\? + Totdat deze gebruiker deze sessie vertrouwt, worden berichten die van en naar de sessie worden verzonden, gelabeld met waarschuwingen. U kunt het ook handmatig verifiëren. + %1$s (%2$s) aangemeld met een nieuwe sessie: + Deze sessie wordt vertrouwd voor veilig berichtenverkeer omdat %1$s (%2$s) deze heeft geverifieerd: + Kan geen sessies ophalen + Gebruik een bestaande sessie om deze te verifiëren en deze toegang te verlenen tot versleutelde berichten. + Andere gebruikers vertrouwen het misschien niet + Verifieer deze login + + %d actieve sessie + %d actieve sessies + + Verifieer deze sessie om hem als vertrouwd te markeren en verleen hem toegang tot versleutelde berichten. Als u zich niet bij deze sessie hebt aangemeld, is uw account mogelijk gehackt: + Deze sessie wordt vertrouwd voor veilige berichten omdat u deze heeft geverifieerd: + Geen cryptografische informatie beschikbaar + Standaardversie + Kamerversies 👓 + De limiet is onbekend. + Uw thuisserver accepteert bijlagen (bestanden, media, enz.) met een grootte tot %s. + Server limiet voor het uploaden van bestanden + Serverversie + Server naam + Afmelden voor deze sessie + Toon alle sessies + Uw serverbeheerder heeft standaard end-to-end codering uitgeschakeld in privéruimten en privéberichten. + Kruisondertekenen is niet ingeschakeld + Kruisondertekenen is ingeschakeld. +\nSleutels worden niet vertrouwd + Kruisondertekenen is ingeschakeld +\nSleutels zijn vertrouwd. +\nPrivésleutels zijn niet bekend + Kruisondertekening is ingeschakeld +\nPrivésleutels op het apparaat. + Uw nieuwe sessie is nu geverifieerd. Het heeft toegang tot uw gecodeerde berichten en andere gebruikers zullen het als vertrouwd zien. + Berichten met deze gebruiker zijn end-to-end versleuteld en kunnen niet door derden worden gelezen. + Vergelijk de code met die op het scherm van de andere gebruiker. + Vergelijk de unieke emoji en zorg ervoor dat ze in dezelfde volgorde verschijnen. + Doe dit voor de zekerheid persoonlijk of gebruik een andere manier om te communiceren. + Om veilig te zijn, verifieert u %s door een eenmalige code te controleren. + Eenmaal ingeschakeld, kan codering voor een kamer niet worden uitgeschakeld. Berichten die in een versleutelde ruimte worden verzonden, kunnen niet door de server worden gezien, alleen door de deelnemers van de ruimte. Het inschakelen van codering kan voorkomen dat veel bots en bruggen correct werken. + Eenmaal ingeschakeld, kan codering niet worden uitgeschakeld. + U bent niet gemachtigd om versleuteling in deze ruimte in te schakelen. + End-to-end-versleuteling inschakelen… + Verzendt de gegeven emote gekleurd als een regenboog + Stuurt het gegeven bericht gekleurd als een regenboog + Deze sessie kan deze verificatie niet delen met uw andere sessies. +\nDe verificatie wordt lokaal opgeslagen en gedeeld in een toekomstige versie van de app. + ${app_name} heeft een probleem ondervonden bij het weergeven van de inhoud van het evenement met id \'%1$s\' + ${app_name} verwerkt geen bericht van het type \'%1$s\' + ${app_name} verwerkt geen gebeurtenissen van het type \'%1$s\' + Ga naar ontvangstbewijs lezen + Direct bericht + Aangepast (%1$d) in %2$s + Standaard in %1$s + Moderator in %1$s + Beheerder in %1$s + De kamer verlaten… + Berichten hier zijn end-to-end versleuteld. +\n +\nUw berichten zijn beveiligd met sloten en alleen u en de ontvanger hebben de unieke sleutels om ze te ontgrendelen. + Berichten in deze ruimte zijn end-to-end versleuteld. +\n +\nUw berichten zijn beveiligd met sloten en alleen u en de ontvanger hebben de unieke sleutels om ze te ontgrendelen. + Berichten hier zijn niet end-to-end versleuteld. + Berichten in deze ruimte zijn niet end-to-end versleuteld. + Voor extra veiligheid, verifieer %s door een eenmalige code op beide apparaten te controleren. +\n +\nDoe dit persoonlijk voor maximale veiligheid. + Wachten op %s… + QR-code afbeelding + Als u de bovenstaande code niet kunt scannen, verifieer dan door een korte, unieke selectie emoji te vergelijken. + Verifiëren door Emoji + Verifieer door emoji\'s te vergelijken + Verifieer door emoji te vergelijken + Als u niet persoonlijk aanwezig bent, vergelijk dan emoji\'s + Scannen met dit apparaat + Scan hun code + Scan de code met uw ander apparaat of wissel en scan met dit apparaat + Scan de code met het apparaat van de andere gebruiker om elkaar veilig te verifiëren + Deze sessie verifiëren + Gereageerd met: %s + "Een van de volgende zaken kan worden aangetast: +\n +\n - Uw thuisserver +\n - De thuisserver waarmee de gebruiker die u verifieert is verbonden +\n - De internetverbinding van u of de andere gebruikers +\n - Het apparaat van u of van andere gebruikers" + Zoek naar het groene schild om ervoor te zorgen dat een gebruiker wordt vertrouwd. Vertrouw alle gebruikers in een ruimte om ervoor te zorgen dat de ruimte veilig is. + Gebruik voor ultieme veiligheid een ander vertrouwd communicatiemiddel of doe dit persoonlijk. + Verifieer deze gebruiker door te bevestigen dat de volgende unieke emoji op hun scherm verschijnen, in dezelfde volgorde. + Ze komen niet overeen + Niet-vertrouwd inloggen + Uw e-maildomein is niet geautoriseerd om op deze server te registreren + Space aanmaken… + Ruimte aanmaken… + Sommige tekens zijn niet toegestaan + Geef een kameradres op + Dit adres is al in gebruik + Space adres + Kamer adres + U kunt dit inschakelen als de ruimte alleen wordt gebruikt voor samenwerking met interne teams op uw homeserver. Dit kan later niet meer worden gewijzigd. + Blokkeer iedereen die geen deel uitmaakt van %s om ooit deel te nemen aan deze kamer + Verberg geavanceerd + Toon geavanceerd + Eenmaal ingeschakeld, kan codering niet worden uitgeschakeld. + Voegt ( ͡° ͜ʖ ͡°) toe aan een bericht in platte tekst + Voegt ¯\\_(ツ)_/¯ toe aan een bericht in platte tekst + Toon wat nuttige informatie om te helpen bij het debuggen van de applicatie + Toon debug-informatie op het scherm + ${app_name} kan vaker crashen als er een onverwachte fout optreedt + Laat alleen de eerste resultaten zien, typ meer letters… + Schud je telefoon om de detectiedrempel te testen + De ontwikkelaarsmodus activeert verborgen functies en kan de applicatie ook minder stabiel maken. Alleen voor ontwikkelaars! + Bekijk al mijn sessies + De beschrijving is te kort + Uw matrix.to link is onjuist opgemaakt + De huidige sessie is voor gebruiker %1$s en u geeft inloggegevens op voor gebruiker %2$s. Dit wordt niet ondersteund door ${app_name}. +\nWis eerst de gegevens en meld u vervolgens opnieuw aan met een ander account. + U raakt de toegang tot beveiligde berichten kwijt, tenzij u zich aanmeldt om uw coderingssleutels te herstellen. + Alle gegevens wissen die momenteel op dit apparaat zijn opgeslagen\? +\nMeld u opnieuw aan om toegang te krijgen tot uw accountgegevens en berichten. + Alle gegevens wissen + Waarschuwing: uw persoonlijke gegevens (inclusief coderingssleutels) zijn nog steeds opgeslagen op dit apparaat. +\n +\nWis het als u klaar bent met het gebruik van dit apparaat of als u zich wilt aanmelden bij een ander account. + Persoonlijke gegevens wissen + Log in om coderingssleutels te herstellen die exclusief op dit apparaat zijn opgeslagen. Je hebt ze nodig om al uw beveiligde berichten op elk apparaat te lezen. + Uw thuisserver (%1$s) beheerder heeft u uitgelogd van uw account %2$s (%3$s). + Je bent uitgelogd + Opnieuw inloggen + Het kan verschillende redenen hebben: +\n +\n• U heeft uw wachtwoord bij een andere sessie gewijzigd. +\n +\n• U heeft deze sessie verwijderd uit een andere sessie. +\n +\n• De beheerder van uw server heeft uw toegang om veiligheidsredenen ongeldig gemaakt. + Je bent uitgelogd + Kan geen geldige thuisserver vinden. Controleer uw ID a.u.b. + Dit is geen geldige gebruikers-ID. Verwacht formaat: \'@gebruiker:thuisserver.org\' + Als u uw wachtwoord niet weet, gaat u terug om het opnieuw in te stellen. + Als je een account aanmaakt op een thuisserver, gebruik dan je Matrix ID (bijv. @gebruiker:domein.nl) en wachtwoord hieronder. + Aanmelden met Matrix ID + Aanmelden met Matrix ID + Als alternatief, als u al een account heeft en u uw Matrix-ID en uw wachtwoord kent, kunt u deze methode gebruiken: + + Er zijn te veel verzoeken verzonden. Je kunt het over %1$d seconde opnieuw proberen… + Er zijn te veel verzoeken verzonden. Je kunt het over %1$d seconden opnieuw proberen… + + Deze thuisserver draait op een oude versie. Vraag uw thuisserver beheerder om te upgraden. U kunt doorgaan, maar sommige functies werken mogelijk niet correct. + Deze thuisserver heeft een te oude versie om verbinding mee te maken. Vraag uw thuisserver beheerder om te upgraden. + De ingevoerde code is niet correct. Gelieve dit te controleren. + We hebben zojuist een e-mail gestuurd naar %1$s. +\nKlik op de link die deze bevat om door te gaan met het aanmaken van een account. + Controleer uw e-mail + Accepteer de voorwaarden om door te gaan + Voer de captcha uitdaging uit + Selecteer een aangepaste thuisserver + Selecteer Element Matrix Services + Uw account is nog niet aangemaakt. +\n +\nHet registratieproces stoppen\? + Die gebruikersnaam is in gebruik + Gebruikersnaam of e-mail + Meld u aan bij %1$s + Telefoonnummer lijkt ongeldig. Controleer het alstublieft + Internationale telefoonnummers moeten beginnen met \'+\' + Gebruik het internationale formaat (telefoonnummer moet beginnen met \'+\') + We hebben zojuist een code naar %1$s gestuurd. Voer het hieronder in om te verifiëren dat u het bent. + Telefoonnummer bevestigen + Telefoon nummer (optioneel) + Gebruik het internationale formaat. + Stel een telefoonnummer in om optioneel toe te staan dat mensen die u kent u kunnen ontdekken. + Telefoonnummer instellen + Lijkt niet op een geldig e-mailadres + Stel een e-mail in om uw account te herstellen. Later kunt u optioneel toelaten dat mensen die u kent u via uw e-mail ontdekken. + E-mailadres instellen + Uw wachtwoord is nog niet gewijzigd. +\n +\nHet proces voor het wijzigen van het wachtwoord stoppen\? + Terug naar Inloggen + U bent bij alle sessies uitgelogd en ontvangt geen pushmeldingen meer. Log opnieuw in op elk apparaat om meldingen weer in te schakelen. + Je wachtwoord is gereset. + Ik heb mijn e-mailadres geverifieerd + Tik op de link om uw nieuwe wachtwoord te bevestigen. Klik hieronder als u de link hebt gevolgd die erin staat. \ No newline at end of file From 19a3eef137805323802873ac36a2a5f9829d87bb Mon Sep 17 00:00:00 2001 From: Bui Minh Duc Date: Sat, 15 Jan 2022 14:01:19 +0000 Subject: [PATCH 043/222] Translated using Weblate (Vietnamese) Currently translated at 99.1% (2707 of 2729 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- vector/src/main/res/values-vi/strings.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vector/src/main/res/values-vi/strings.xml b/vector/src/main/res/values-vi/strings.xml index 51b19ba001..1d180192ee 100644 --- a/vector/src/main/res/values-vi/strings.xml +++ b/vector/src/main/res/values-vi/strings.xml @@ -1242,8 +1242,8 @@ Hiện thông báo tin đã đọc Hiện dấu thời gian theo chuẩn 12-giờ Hiện Dấu thời gian cho tất cả tin nhắn - Định dạng tin nhắn theo chuẩn markdown trước khi gửi. - Định dạng markdown + Định dạng tin nhắn theo chuẩn Markdown trước khi gửi. + Sử dụng định dạng Markdown Cho người dùng khác biết bạn đã gõ phím. Gửi thông báo đang gõ tin nhắn Xem trước trang web trong phòng chat nếu máy chủ bật hỗ trợ chức năng này. @@ -2075,7 +2075,7 @@ Tin nhắn… Tài khoản này đã bị vô hiệu hóa. Tên người dùng và/hoặc mật khẩu không chính xác. Mật khẩu đã nhập bắt đầu hoặc kết thúc bằng không gian, vui lòng kiểm tra. - Gửi tin nhắn dưới dạng văn bản thuần túy, mà không giải thích nó dưới dạng đánh dấu + Gửi tin nhắn dưới dạng văn bản thuần túy, không sử dụng định dạng Markdown Đặt tầm quan trọng thông báo theo sự kiện Khắc phục Cấu hình thông báo @@ -2275,7 +2275,7 @@ Sau khi được bật, mã hóa không thể bị vô hiệu hóa. Bật mã hóa Thêm ( ͡° ͜ʖ ͡°) vào một tin nhắn văn bản thuần túy - "Thêm ̄\\_(ツ)_/ ̄ vào một tin nhắn văn bản thuần túy" + Thêm ¯\\_(ツ)_/¯ vào một tin nhắn văn bản thuần túy Hiển thị một số thông tin hữu ích để giúp gỡ lỗi ứng dụng Hiện thông tin debug trên màn hình ${app_name} có thể gặp sự cố thường xuyên hơn khi một lỗi bất ngờ xảy ra @@ -2352,7 +2352,7 @@ Mở ngăn khung điều hướng Có vẻ như máy chủ mất quá nhiều thời gian để phản hồi, điều này có thể được gây ra bởi kết nối kém hoặc lỗi với máy chủ. Hãy thử lại trong một thời gian. 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 gửi RageShake. 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. + 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. @@ -2415,7 +2415,7 @@ Quy tắc Push Chuyên gia Bảo mật & Quyền riêng tư - Sự ưa thích + Tuỳ biến Tổng quát Phản ứng nhanh Bạn đang xem phòng này rồi! @@ -2776,7 +2776,7 @@ Không có người dùng Phòng Danh bạ - Nhà + Trang chủ Ví dụ ID Community Ví dụ @@ -2787,11 +2787,11 @@ Ồn ào Im lặng Tắt - Đánh dấu đã bị vô hiệu hóa. - Đánh dấu đã được kích hoạt. + Tính năng định dạng tin nhắn chuẩn Markdown đã bị vô hiệu hoá. + Tính năng định dạng tin nhắn chuẩn Markdown đã được kích hoạt. Hiển thị thông tin về người dùng Để sửa trình quản lý ứng dụng Matrix - Đánh dấu Bật/Tắt + Bật/tắt tính năng định dạng Markdown Chỉ thay đổi avatar của bạn trong căn phòng hiện tại này Thay đổi avatar của căn phòng hiện tại Chỉ thay đổi biệt danh hiển thị của bạn trong phòng hiện tại From cc89a8fc776fefe91e812cbd7302b8bdef04ad9f Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 17 Jan 2022 19:16:32 +0100 Subject: [PATCH 044/222] Timeline : fix 4959 --- changelog.d/4959.bugfix | 1 + .../detail/timeline/TimelineEventController.kt | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 changelog.d/4959.bugfix diff --git a/changelog.d/4959.bugfix b/changelog.d/4959.bugfix new file mode 100644 index 0000000000..6ffa3937f9 --- /dev/null +++ b/changelog.d/4959.bugfix @@ -0,0 +1 @@ +Prevent crash in Timeline and add more logs. \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index 241ccb7428..bf0c5ee062 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -72,6 +72,7 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import timber.log.Timber import javax.inject.Inject +import kotlin.math.min import kotlin.system.measureTimeMillis class TimelineEventController @Inject constructor(private val dateFormatter: VectorDateFormatter, @@ -185,6 +186,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec override fun onChanged(position: Int, count: Int, payload: Any?) { synchronized(modelCache) { assertUpdateCallbacksAllowed() + Timber.v("listUpdateCallback.onChanged(position: $position, count: $count). " + + "\ncurrentSnapshot has size of ${currentSnapshot.size} items") (position until position + count).forEach { // Invalidate cache modelCache[it] = null @@ -192,10 +195,12 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec // Also invalidate the first previous displayable event if // it's sent by the same user so we are sure we have up to date information. val invalidatedSenderId: String? = currentSnapshot.getOrNull(position)?.senderInfo?.userId - val prevDisplayableEventIndex = currentSnapshot.subList(0, position).indexOfLast { + // In some cases onChanged will be called before onRemoved and onInserted so position will be smaller than currentSnapshot.size. + val prevList = currentSnapshot.subList(0, min(position, currentSnapshot.size)) + val prevDisplayableEventIndex = prevList.indexOfLast { timelineEventVisibilityHelper.shouldShowEvent(it, partialState.highlightedEventId) } - if (prevDisplayableEventIndex != -1 && currentSnapshot[prevDisplayableEventIndex].senderInfo.userId == invalidatedSenderId) { + if (prevDisplayableEventIndex != -1 && currentSnapshot.getOrNull(prevDisplayableEventIndex)?.senderInfo?.userId == invalidatedSenderId) { modelCache[prevDisplayableEventIndex] = null } requestModelBuild() @@ -205,6 +210,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec override fun onMoved(fromPosition: Int, toPosition: Int) { synchronized(modelCache) { assertUpdateCallbacksAllowed() + Timber.v("listUpdateCallback.onMoved(fromPosition: $fromPosition, toPosition: $toPosition). " + + "\ncurrentSnapshot has size of ${currentSnapshot.size} items") val model = modelCache.removeAt(fromPosition) modelCache.add(toPosition, model) requestModelBuild() @@ -214,6 +221,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec override fun onInserted(position: Int, count: Int) { synchronized(modelCache) { assertUpdateCallbacksAllowed() + Timber.v("listUpdateCallback.onInserted(position: $position, count: $count). " + + "\ncurrentSnapshot has size of ${currentSnapshot.size} items") repeat(count) { modelCache.add(position, null) } @@ -224,6 +233,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec override fun onRemoved(position: Int, count: Int) { synchronized(modelCache) { assertUpdateCallbacksAllowed() + Timber.v("listUpdateCallback.onRemoved(position: $position, count: $count). " + + "\ncurrentSnapshot has size of ${currentSnapshot.size} items") repeat(count) { modelCache.removeAt(position) } @@ -306,6 +317,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec inSubmitList = true val diffCallback = TimelineEventDiffUtilCallback(currentSnapshot, newSnapshot) currentSnapshot = newSnapshot + Timber.v("Submit a new snapshot of ${currentSnapshot.size} items.") val diffResult = DiffUtil.calculateDiff(diffCallback) diffResult.dispatchUpdatesTo(listUpdateCallback) requestDelayedModelBuild(0) From a08304788897d8b1641975765557da1c955e24e9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 09:12:39 +0100 Subject: [PATCH 045/222] Fix typo --- .../home/room/detail/timeline/TimelineEventController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index bf0c5ee062..4a9a03789f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -195,7 +195,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec // Also invalidate the first previous displayable event if // it's sent by the same user so we are sure we have up to date information. val invalidatedSenderId: String? = currentSnapshot.getOrNull(position)?.senderInfo?.userId - // In some cases onChanged will be called before onRemoved and onInserted so position will be smaller than currentSnapshot.size. + // In some cases onChanged will be called before onRemoved and onInserted so position will be bigger than currentSnapshot.size. val prevList = currentSnapshot.subList(0, min(position, currentSnapshot.size)) val prevDisplayableEventIndex = prevList.indexOfLast { timelineEventVisibilityHelper.shouldShowEvent(it, partialState.highlightedEventId) From 13881a589a1b30686c5ec5f12fbb276e88876411 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Jan 2022 11:48:58 +0100 Subject: [PATCH 046/222] Remove temporary change on the "NewApi" lint error. --- vector/lint.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vector/lint.xml b/vector/lint.xml index 818349da24..f02090489c 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -40,6 +40,7 @@ + @@ -82,10 +83,6 @@ - - - - From 961f821ab9e270442bc948b1322b1a258d75d5f0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 09:19:52 +0100 Subject: [PATCH 047/222] Create and use `removeIfCompat` (#4961) --- .../utils/compat/MutableCollectionCompat.kt | 27 +++++++++++++++++++ .../analytics/DecryptionFailureTracker.kt | 5 ++-- .../reactions/EmojiRecyclerAdapter.kt | 10 ++----- 3 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt diff --git a/vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt b/vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt new file mode 100644 index 0000000000..e131b5f328 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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.core.utils.compat + +import android.os.Build + +fun MutableCollection.removeIfCompat(predicate: (E) -> Boolean) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + removeIf(predicate) + } else { + removeAll(filter(predicate).toSet()) + } +} diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index cd98356445..ec11702054 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -19,6 +19,7 @@ package im.vector.app.features.analytics import im.vector.app.core.flow.tickerFlow import im.vector.app.core.time.Clock import im.vector.app.features.analytics.plan.Error +import im.vector.app.core.utils.compat.removeIfCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -89,7 +90,7 @@ class DecryptionFailureTracker @Inject constructor( fun onTimeLineDisposed(roomId: String) { scope.launch(Dispatchers.Default) { synchronized(failures) { - failures.removeIf { it.roomId == roomId } + failures.removeIfCompat { it.roomId == roomId } } } } @@ -105,7 +106,7 @@ class DecryptionFailureTracker @Inject constructor( private fun removeFailureForEventId(eventId: String) { synchronized(failures) { - failures.removeIf { it.failedEventId == eventId } + failures.removeIfCompat { it.failedEventId == eventId } } } diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt index d64ee0f705..6abbbe29af 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt @@ -32,6 +32,7 @@ import androidx.transition.AutoTransition import androidx.transition.TransitionManager import im.vector.app.R import im.vector.app.features.reactions.data.EmojiData +import im.vector.app.core.utils.compat.removeIfCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -215,14 +216,7 @@ class EmojiRecyclerAdapter @Inject constructor() : override fun onViewRecycled(holder: ViewHolder) { if (holder is EmojiViewHolder) { holder.data = null - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - toUpdateWhenNotBusy.removeIf { it.second == holder } - } else { - val index = toUpdateWhenNotBusy.indexOfFirst { it.second == holder } - if (index != -1) { - toUpdateWhenNotBusy.removeAt(index) - } - } + toUpdateWhenNotBusy.removeIfCompat { it.second == holder } } super.onViewRecycled(holder) } From f5b16b834cb50c0715032c84ade27b0613a5f3a9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Jan 2022 12:50:44 +0100 Subject: [PATCH 048/222] Changelog --- changelog.d/4962.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4962.bugfix diff --git a/changelog.d/4962.bugfix b/changelog.d/4962.bugfix new file mode 100644 index 0000000000..489f91cfc3 --- /dev/null +++ b/changelog.d/4962.bugfix @@ -0,0 +1 @@ +Fix crash on API <24 and make sure this error will not occur again. \ No newline at end of file From 42dcf52eb05d57d26c1b6d2e5e65658c8038b4a2 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 18 Jan 2022 12:34:02 +0300 Subject: [PATCH 049/222] Use official maptiler key. --- vector/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index 65e3e0e9f0..a6085e0ae0 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -150,7 +150,7 @@ android { // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" - buildConfigField "String", "mapTilerKey", "\"KF6tcY7YuKFgJSZ1EFQ2\"" + buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\"" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" From ede1fe39fcbe94d22c10e21f92db18454b592026 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 18 Jan 2022 13:41:40 +0300 Subject: [PATCH 050/222] Disable location sharing from build settings. --- vector/build.gradle | 1 + .../java/im/vector/app/features/settings/VectorPreferences.kt | 4 ++-- .../features/settings/VectorSettingsPreferencesFragment.kt | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index a6085e0ae0..c5c45f5ef3 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -150,6 +150,7 @@ android { // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" + buildConfigField "Boolean", "enableLocationSharing", "false" buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\"" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 67d26231b2..859c5ce678 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -188,7 +188,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val DID_PROMOTE_NEW_RESTRICTED_JOIN_RULE = "DID_PROMOTE_NEW_RESTRICTED_JOIN_RULE" // Location Sharing - private const val SETTINGS_PREF_ENABLE_LOCATION_SHARING = "SETTINGS_PREF_ENABLE_LOCATION_SHARING" + const val SETTINGS_PREF_ENABLE_LOCATION_SHARING = "SETTINGS_PREF_ENABLE_LOCATION_SHARING" private const val MEDIA_SAVING_3_DAYS = 0 private const val MEDIA_SAVING_1_WEEK = 1 @@ -1000,6 +1000,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { } fun isLocationSharingEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_PREF_ENABLE_LOCATION_SHARING, false) + return defaultPrefs.getBoolean(SETTINGS_PREF_ENABLE_LOCATION_SHARING, false) && BuildConfig.enableLocationSharing } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt index 2e2fab06a3..50e32ae453 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt @@ -22,6 +22,7 @@ import android.widget.CheckedTextView import androidx.core.view.children import androidx.preference.Preference import com.google.android.material.dialog.MaterialAlertDialogBuilder +import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.dialogs.PhotoOrVideoDialog import im.vector.app.core.extensions.restart @@ -149,6 +150,8 @@ class VectorSettingsPreferencesFragment @Inject constructor( }) true } + + findPreference(VectorPreferences.SETTINGS_PREF_ENABLE_LOCATION_SHARING)?.isVisible = BuildConfig.enableLocationSharing } private fun updateTakePhotoOrVideoPreferenceSummary() { From 114c60cfedc1d32c9042ed95d2f50c8c70ff2052 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 10:29:26 +0000 Subject: [PATCH 051/222] fixing onboarding crash when signing in/up with sso - handles the sso flows by not forwarding to the signin/signup pages and instead using the previous onLoginFlowRetrieved when the selected server type is other --- .../features/onboarding/OnboardingViewModel.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 5d1e0fdade..4b3ce14002 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -826,13 +826,17 @@ class OnboardingViewModel @AssistedInject constructor( } withState { - when (it.onboardingFlow) { - OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn)) - OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp)) - OnboardingFlow.SignInSignUp, - null -> { - _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) + if (it.serverType == ServerType.MatrixOrg) { + when (it.onboardingFlow) { + OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn)) + OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp)) + OnboardingFlow.SignInSignUp, + null -> { + _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) + } } + } else { + _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) } } } From 54a5c3e52a71b0a4add78fa9ac8a04524f04002c Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 10:43:39 +0000 Subject: [PATCH 052/222] adding changelog entry --- changelog.d/4969.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4969.bugfix diff --git a/changelog.d/4969.bugfix b/changelog.d/4969.bugfix new file mode 100644 index 0000000000..6edfd498bf --- /dev/null +++ b/changelog.d/4969.bugfix @@ -0,0 +1 @@ +Fixes sign in/up crash when selecting ems and other server types which use SSO \ No newline at end of file From bdd30e3b8fbcea43ec35a08d28f7380a7b14b1f6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 12:04:06 +0100 Subject: [PATCH 053/222] Fix crash when viewing source which contains an emoji. Import source of jsonviewer as a module of this project. --- changelog.d/4796.bugfix | 1 + dependencies.gradle | 1 + dependencies_groups.gradle | 2 +- library/jsonviewer/.gitignore | 1 + library/jsonviewer/build.gradle | 64 +++++ .../jsonviewer/src/main/AndroidManifest.xml | 1 + .../jsonviewer/JSonViewerDialog.kt | 77 ++++++ .../jsonviewer/JSonViewerEpoxyController.kt | 261 ++++++++++++++++++ .../jsonviewer/JSonViewerFragment.kt | 103 +++++++ .../jsonviewer/JSonViewerModel.kt | 124 +++++++++ .../jsonviewer/JSonViewerStyleProvider.kt | 46 +++ .../jsonviewer/JSonViewerViewModel.kt | 67 +++++ .../jsonviewer/SafeCharSequence.kt | 30 ++ .../java/org/billcarsonfr/jsonviewer/Utils.kt | 33 +++ .../org/billcarsonfr/jsonviewer/ValueItem.kt | 93 +++++++ .../main/res/layout/fragment_dialog_jv.xml | 5 + .../res/layout/fragment_jv_recycler_view.xml | 18 ++ .../layout/fragment_jv_recycler_view_wrap.xml | 10 + .../main/res/layout/item_jv_base_value.xml | 16 ++ .../src/main/res/menu/jv_menu_item.xml | 8 + .../jsonviewer/src/main/res/values/colors.xml | 11 + .../src/main/res/values/strings.xml | 3 + .../billcarsonfr/jsonviewer/ModelParseTest.kt | 96 +++++++ settings.gradle | 1 + vector/build.gradle | 2 +- 25 files changed, 1072 insertions(+), 2 deletions(-) create mode 100644 changelog.d/4796.bugfix create mode 100644 library/jsonviewer/.gitignore create mode 100644 library/jsonviewer/build.gradle create mode 100644 library/jsonviewer/src/main/AndroidManifest.xml create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt create mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt create mode 100644 library/jsonviewer/src/main/res/layout/fragment_dialog_jv.xml create mode 100644 library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view.xml create mode 100644 library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view_wrap.xml create mode 100644 library/jsonviewer/src/main/res/layout/item_jv_base_value.xml create mode 100644 library/jsonviewer/src/main/res/menu/jv_menu_item.xml create mode 100644 library/jsonviewer/src/main/res/values/colors.xml create mode 100644 library/jsonviewer/src/main/res/values/strings.xml create mode 100644 library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt diff --git a/changelog.d/4796.bugfix b/changelog.d/4796.bugfix new file mode 100644 index 0000000000..df5b5a4eba --- /dev/null +++ b/changelog.d/4796.bugfix @@ -0,0 +1 @@ +Fix crash when viewing source which contains an emoji \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle index 6cb5fac64c..3fb47ba711 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -71,6 +71,7 @@ ext.libs = [ 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso" ], google : [ + // TODO There is 1.6.0? 'material' : "com.google.android.material:material:1.4.0" ], dagger : [ diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 3853919bcb..fd36f5110c 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -4,7 +4,6 @@ ext.groups = [ ], group: [ 'com.github.Armen101', - 'com.github.BillCarsonFr', 'com.github.chrisbanes', 'com.github.hyuwah', 'com.github.jetradarmobile', @@ -154,6 +153,7 @@ ext.groups = [ 'org.jetbrains.intellij.deps', 'org.jetbrains.kotlin', 'org.jetbrains.kotlinx', + 'org.json', 'org.jsoup', 'org.junit', 'org.junit.jupiter', diff --git a/library/jsonviewer/.gitignore b/library/jsonviewer/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/library/jsonviewer/.gitignore @@ -0,0 +1 @@ +/build diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle new file mode 100644 index 0000000000..ee2be6fd25 --- /dev/null +++ b/library/jsonviewer/build.gradle @@ -0,0 +1,64 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-parcelize' +apply plugin: 'kotlin-kapt' +apply plugin: 'com.jakewharton.butterknife' + +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3' + } +} + +android { + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } + + kotlinOptions { + jvmTarget = "11" + } +} + +dependencies { + implementation libs.androidx.appCompat + implementation libs.androidx.core + + implementation libs.airbnb.epoxy + kapt libs.airbnb.epoxyProcessor + + implementation libs.airbnb.mavericks + // Span utils + implementation 'me.gujun.android:span:1.7' + + implementation libs.google.material + + implementation libs.jetbrains.coroutinesCore + implementation libs.jetbrains.coroutinesAndroid + + testImplementation 'org.json:json:20190722' + testImplementation libs.tests.junit + androidTestImplementation libs.androidx.junit + androidTestImplementation libs.androidx.espressoCore +} diff --git a/library/jsonviewer/src/main/AndroidManifest.xml b/library/jsonviewer/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..73322c2fdb --- /dev/null +++ b/library/jsonviewer/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt new file mode 100644 index 0000000000..a8d9cac849 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import com.airbnb.mvrx.Mavericks + +class JSonViewerDialog : DialogFragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_dialog_jv, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val args: JSonViewerFragmentArgs = arguments?.getParcelable(Mavericks.KEY_ARG) ?: return + if (savedInstanceState == null) { + childFragmentManager.beginTransaction() + .replace( + R.id.fragmentContainer, JSonViewerFragment.newInstance( + args.jsonString, + args.defaultOpenDepth, + true, + args.styleProvider + ) + ) + .commitNow() + } + } + + override fun onResume() { + super.onResume() + // Get existing layout params for the window + val params = dialog?.window?.attributes + // Assign window properties to fill the parent + params?.width = WindowManager.LayoutParams.MATCH_PARENT + params?.height = WindowManager.LayoutParams.MATCH_PARENT + dialog?.window?.attributes = params + } + + companion object { + fun newInstance( + jsonString: String, + initialOpenDepth: Int = -1, + styleProvider: JSonViewerStyleProvider? = null + ): JSonViewerDialog { + val args = Bundle() + val parcelableArgs = + JSonViewerFragmentArgs(jsonString, initialOpenDepth, false, styleProvider) + args.putParcelable(Mavericks.KEY_ARG, parcelableArgs) + return JSonViewerDialog().apply { arguments = args } + } + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt new file mode 100644 index 0000000000..1ff35f5005 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.content.Context +import android.view.View +import com.airbnb.epoxy.TypedEpoxyController +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Success +import me.gujun.android.span.Span +import me.gujun.android.span.span + +internal class JSonViewerEpoxyController(private val context: Context) : + TypedEpoxyController() { + + private var styleProvider: JSonViewerStyleProvider = JSonViewerStyleProvider.default(context) + + fun setStyle(styleProvider: JSonViewerStyleProvider?) { + this.styleProvider = styleProvider ?: JSonViewerStyleProvider.default(context) + } + + override fun buildModels(data: JSonViewerState?) { + val async = data?.root ?: return + + when (async) { + is Fail -> { + valueItem { + id("fail") + text(async.error.localizedMessage?.toSafeCharSequence()) + } + } + is Success -> { + val model = data.root.invoke() + + model?.let { + buildRec(it, 0, "") + } + } + } + } + + private fun buildRec( + model: JSonViewerModel, + depth: Int, + idBase: String + ) { + val host = this + val id = "$idBase/${model.key ?: model.index}_${model.isExpanded}}" + when (model) { + is JSonViewerObject -> { + if (model.isExpanded) { + open(id, model.key, model.index, depth, true, model) + model.keys.forEach { + buildRec(it.value, depth + 1, id) + } + close(id, depth, true) + } else { + valueItem { + id(id + "_sum") + depth(depth) + text( + span { + if (model.key != null) { + span("\"${model.key}\"") { + textColor = host.styleProvider.keyColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + if (model.index != null) { + span("${model.index}") { + textColor = host.styleProvider.secondaryColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + span { + +"{+${model.keys.size}}" + textColor = host.styleProvider.baseColor + } + }.toSafeCharSequence() + ) + itemClickListener(View.OnClickListener { host.itemClicked(model) }) + } + } + } + is JSonViewerArray -> { + if (model.isExpanded) { + open(id, model.key, model.index, depth, false, model) + model.items.forEach { + buildRec(it, depth + 1, id) + } + close(id, depth, false) + } else { + valueItem { + id(id + "_sum") + depth(depth) + text( + span { + if (model.key != null) { + span("\"${model.key}\"") { + textColor = host.styleProvider.keyColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + if (model.index != null) { + span("${model.index}") { + textColor = host.styleProvider.secondaryColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + span { + +"[+${model.items.size}]" + textColor = host.styleProvider.baseColor + } + }.toSafeCharSequence() + ) + itemClickListener(View.OnClickListener { host.itemClicked(model) }) + } + } + } + is JSonViewerLeaf -> { + valueItem { + id(id) + depth(depth) + text( + span { + if (model.key != null) { + span("\"${model.key}\"") { + textColor = host.styleProvider.keyColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + + if (model.index != null) { + span("${model.index}") { + textColor = host.styleProvider.secondaryColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + append(host.valueToSpan(model)) + }.toSafeCharSequence() + ) + copyValue(model.stringRes) + } + } + } + } + + private fun valueToSpan(leaf: JSonViewerLeaf): Span { + val host = this + return when (leaf.type) { + JSONType.STRING -> { + span("\"${leaf.stringRes}\"") { + textColor = host.styleProvider.stringColor + } + } + JSONType.NUMBER -> { + span(leaf.stringRes) { + textColor = host.styleProvider.numberColor + } + } + JSONType.BOOLEAN -> { + span(leaf.stringRes) { + textColor = host.styleProvider.booleanColor + } + } + JSONType.NULL -> { + span("null") { + textColor = host.styleProvider.booleanColor + } + } + } + } + + private fun open( + id: String, + key: String?, + index: Int?, + depth: Int, + isObject: Boolean = true, + composed: JSonViewerModel + ) { + val host = this + valueItem { + id("${id}_Open") + depth(depth) + text( + span { + if (key != null) { + span("\"$key\"") { + textColor = host.styleProvider.keyColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + if (index != null) { + span("$index") { + textColor = host.styleProvider.secondaryColor + } + span(" : ") { + textColor = host.styleProvider.baseColor + } + } + span("- ") { + textColor = host.styleProvider.secondaryColor + } + span("{".takeIf { isObject } ?: "[") { + textColor = host.styleProvider.baseColor + } + }.toSafeCharSequence() + ) + itemClickListener(View.OnClickListener { host.itemClicked(composed) }) + } + + } + + private fun itemClicked(model: JSonViewerModel) { + model.isExpanded = !model.isExpanded + setData(currentData) + } + + private fun close(id: String, depth: Int, isObject: Boolean = true) { + val host = this + valueItem { + id("${id}_Close") + depth(depth) + text( + span { + text = "}".takeIf { isObject } ?: "]" + textColor = host.styleProvider.baseColor + }.toSafeCharSequence() + ) + } + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt new file mode 100644 index 0000000000..a8aa2493d2 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.os.Bundle +import android.os.Parcelable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.airbnb.epoxy.EpoxyRecyclerView +import com.airbnb.mvrx.Mavericks +import com.airbnb.mvrx.MavericksView +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import kotlinx.parcelize.Parcelize + +@Parcelize +internal data class JSonViewerFragmentArgs( + val jsonString: String, + val defaultOpenDepth: Int, + val wrap: Boolean, + val styleProvider: JSonViewerStyleProvider? +) : Parcelable + + +class JSonViewerFragment : Fragment(), MavericksView { + + private val viewModel: JSonViewerViewModel by fragmentViewModel() + + private val epoxyController by lazy { + JSonViewerEpoxyController(requireContext()) + } + + private lateinit var recyclerView: EpoxyRecyclerView + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val args: JSonViewerFragmentArgs? = arguments?.getParcelable(Mavericks.KEY_ARG) + val inflate = + if (args?.wrap == true) { + inflater.inflate(R.layout.fragment_jv_recycler_view_wrap, container, false) + } else { + inflater.inflate(R.layout.fragment_jv_recycler_view, container, false) + } + recyclerView = inflate.findViewById(R.id.jvRecyclerView) + recyclerView.layoutManager = + LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + recyclerView.setController(epoxyController) + epoxyController.setStyle(args?.styleProvider) + registerForContextMenu(recyclerView) + return inflate + } + + fun showJson(jsonString: String, initialOpenDepth: Int) { + viewModel.setJsonSource(jsonString, initialOpenDepth) + } + + override fun invalidate() = withState(viewModel) { state -> + epoxyController.setData(state) + } + + companion object { + fun newInstance( + jsonString: String, + initialOpenDepth: Int = -1, + wrap: Boolean = false, + styleProvider: JSonViewerStyleProvider? = null + ): JSonViewerFragment { + return JSonViewerFragment().apply { + arguments = Bundle().apply { + putParcelable( + Mavericks.KEY_ARG, + JSonViewerFragmentArgs( + jsonString, + initialOpenDepth, + wrap, + styleProvider + ) + ) + } + } + } + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt new file mode 100644 index 0000000000..3850044880 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject + +internal open class JSonViewerModel(var key: String?, var index: Int?, val jObject: Any) { + var depth = 0 + var isExpanded = false +} + +internal interface Composed { + fun addChild(model: JSonViewerModel) +} + +internal class JSonViewerObject(key: String?, index: Int?, jObject: JSONObject) : + JSonViewerModel(key, index, jObject), + Composed { + + var keys = LinkedHashMap() + + override fun addChild(model: JSonViewerModel) { + keys[model.key!!] = model + } + +} + +internal class JSonViewerArray(key: String?, index: Int?, jObject: JSONArray) : + JSonViewerModel(key, index, jObject), Composed { + var items = ArrayList() + + override fun addChild(model: JSonViewerModel) { + items.add(model) + } +} + +internal class JSonViewerLeaf(key: String?, index: Int?, val stringRes: String, val type: JSONType) : + JSonViewerModel(key, index, stringRes) + + +internal enum class JSONType { + STRING, + NUMBER, + BOOLEAN, + NULL +} + +internal object ModelParser { + + @Throws(JSONException::class) + fun fromJsonString(jsonString: String, initialOpenDepth: Int = -1): JSonViewerObject { + val jobj = JSONObject(jsonString.trim()) + val root = JSonViewerObject(null, null, jobj).apply { isExpanded = true } + jobj.keys().forEach { + eval(root, it, null, jobj.get(it), 1, initialOpenDepth) + } + return root + } + + private fun eval(parent: Composed, key: String?, index: Int?, obj: Any, depth: Int, initialOpenDepth: Int) { + when (obj) { + is JSONObject -> { + val objectComposed = JSonViewerObject(key, index, obj) + .apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth } + objectComposed.depth = depth + obj.keys().forEach { + eval(objectComposed, it, null, obj.get(it), depth + 1, initialOpenDepth) + } + parent.addChild(objectComposed) + } + is JSONArray -> { + val objectComposed = JSonViewerArray(key, index, obj) + .apply { isExpanded = initialOpenDepth == -1 || depth <= initialOpenDepth } + objectComposed.depth = depth + for (i in 0 until obj.length()) { + eval(objectComposed, null, i, obj[i], depth + 1, initialOpenDepth) + } + parent.addChild(objectComposed) + } + is String -> { + JSonViewerLeaf(key, index, obj, JSONType.STRING).let { + it.depth = depth + parent.addChild(it) + } + } + is Number -> { + JSonViewerLeaf(key, index, obj.toString(), JSONType.NUMBER).let { + it.depth = depth + parent.addChild(it) + } + } + is Boolean -> { + JSonViewerLeaf(key, index, obj.toString(), JSONType.BOOLEAN).let { + it.depth = depth + parent.addChild(it) + } + } + else -> { + if (obj == JSONObject.NULL) { + JSonViewerLeaf(key, index, "null", JSONType.NULL).let { + it.depth = depth + parent.addChild(it) + } + } + } + } + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt new file mode 100644 index 0000000000..956e585f80 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.content.Context +import android.os.Parcelable +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import kotlinx.parcelize.Parcelize + +@Parcelize +data class JSonViewerStyleProvider( + @ColorInt val keyColor: Int, + @ColorInt val stringColor: Int, + @ColorInt val booleanColor: Int, + @ColorInt val numberColor: Int, + @ColorInt val baseColor: Int, + @ColorInt val secondaryColor: Int +) : Parcelable { + + companion object { + fun default(context: Context) = JSonViewerStyleProvider( + keyColor = ContextCompat.getColor(context, R.color.key_color), + stringColor = ContextCompat.getColor(context, R.color.string_color), + booleanColor = ContextCompat.getColor(context, R.color.bool_color), + numberColor = ContextCompat.getColor(context, R.color.number_color), + baseColor = ContextCompat.getColor(context, R.color.base_color), + secondaryColor = ContextCompat.getColor(context, R.color.secondary_color) + ) + } +} + diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt new file mode 100644 index 0000000000..d978573a64 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import com.airbnb.mvrx.* +import kotlinx.coroutines.launch + +internal data class JSonViewerState( + val root: Async = Uninitialized +) : MavericksState + +internal class JSonViewerViewModel(initialState: JSonViewerState) : + MavericksViewModel(initialState) { + + fun setJsonSource(json: String, initialOpenDepth: Int) { + setState { + copy(root = Loading()) + } + viewModelScope.launch { + try { + ModelParser.fromJsonString(json, initialOpenDepth).let { + setState { + copy( + root = Success(it) + ) + } + } + } catch (error: Throwable) { + setState { + copy( + root = Fail(error) + ) + } + } + } + } + + companion object : MavericksViewModelFactory { + + @JvmStatic + override fun initialState(viewModelContext: ViewModelContext): JSonViewerState? { + val arg: JSonViewerFragmentArgs = viewModelContext.args() + return try { + JSonViewerState( + Success(ModelParser.fromJsonString(arg.jsonString, arg.defaultOpenDepth)) + ) + } catch (failure: Throwable) { + JSonViewerState(Fail(failure)) + } + + } + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt new file mode 100644 index 0000000000..79556f81d7 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +/** + * Wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering + * TODO Mutualize + */ +internal class SafeCharSequence(val charSequence: CharSequence) { + private val hash = charSequence.toString().hashCode() + + override fun hashCode() = hash + override fun equals(other: Any?) = other is SafeCharSequence && other.hash == hash +} + +internal fun CharSequence.toSafeCharSequence() = SafeCharSequence(this) diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt new file mode 100644 index 0000000000..6536a3401e --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.content.Context +import android.util.TypedValue + +/** + * TODO Mutualize + */ +internal object Utils { + fun dpToPx(dp: Int, context: Context): Int { + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp.toFloat(), + context.resources.displayMetrics + ).toInt() + } +} diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt new file mode 100644 index 0000000000..5c003c97e9 --- /dev/null +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.view.ContextMenu +import android.view.Menu +import android.view.View +import android.widget.LinearLayout +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyHolder +import com.airbnb.epoxy.EpoxyModelClass +import com.airbnb.epoxy.EpoxyModelWithHolder + +@EpoxyModelClass(layout = R2.layout.item_jv_base_value) +internal abstract class ValueItem : EpoxyModelWithHolder() { + + @EpoxyAttribute + var text: SafeCharSequence? = null + + @EpoxyAttribute + var depth: Int = 0 + + @EpoxyAttribute + var copyValue: String? = null + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemClickListener: View.OnClickListener? = null + + override fun bind(holder: Holder) { + super.bind(holder) + holder.textView.text = text?.charSequence + holder.baseView.setPadding(Utils.dpToPx(16 * depth, holder.baseView.context), 0, 0, 0) + itemClickListener?.let { holder.baseView.setOnClickListener(it) } + holder.copyValue = copyValue + } + + override fun unbind(holder: Holder) { + super.unbind(holder) + holder.baseView.setOnClickListener(null) + holder.copyValue = null + } + + class Holder : EpoxyHolder(), View.OnCreateContextMenuListener { + + lateinit var textView: TextView + lateinit var baseView: LinearLayout + var copyValue: String? = null + + override fun bindView(itemView: View) { + baseView = itemView.findViewById(R.id.jvBaseLayout) + textView = itemView.findViewById(R.id.jvValueText) + itemView.setOnCreateContextMenuListener(this) + } + + override fun onCreateContextMenu( + menu: ContextMenu?, + v: View?, + menuInfo: ContextMenu.ContextMenuInfo? + ) { + + if (copyValue != null) { + val menuItem = menu?.add( + Menu.NONE, R.id.copy_value, + Menu.NONE, R.string.copy_value + ) + val clipService = + v?.context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager + menuItem?.setOnMenuItemClickListener { + clipService?.setPrimaryClip(ClipData.newPlainText("", copyValue)) + true + } + } + } + } +} diff --git a/library/jsonviewer/src/main/res/layout/fragment_dialog_jv.xml b/library/jsonviewer/src/main/res/layout/fragment_dialog_jv.xml new file mode 100644 index 0000000000..fb9e6d38c5 --- /dev/null +++ b/library/jsonviewer/src/main/res/layout/fragment_dialog_jv.xml @@ -0,0 +1,5 @@ + + diff --git a/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view.xml b/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view.xml new file mode 100644 index 0000000000..20822191e6 --- /dev/null +++ b/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view_wrap.xml b/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view_wrap.xml new file mode 100644 index 0000000000..8b61b13111 --- /dev/null +++ b/library/jsonviewer/src/main/res/layout/fragment_jv_recycler_view_wrap.xml @@ -0,0 +1,10 @@ + + diff --git a/library/jsonviewer/src/main/res/layout/item_jv_base_value.xml b/library/jsonviewer/src/main/res/layout/item_jv_base_value.xml new file mode 100644 index 0000000000..b7dee1221b --- /dev/null +++ b/library/jsonviewer/src/main/res/layout/item_jv_base_value.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/library/jsonviewer/src/main/res/menu/jv_menu_item.xml b/library/jsonviewer/src/main/res/menu/jv_menu_item.xml new file mode 100644 index 0000000000..4da69b5117 --- /dev/null +++ b/library/jsonviewer/src/main/res/menu/jv_menu_item.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/library/jsonviewer/src/main/res/values/colors.xml b/library/jsonviewer/src/main/res/values/colors.xml new file mode 100644 index 0000000000..7b92899918 --- /dev/null +++ b/library/jsonviewer/src/main/res/values/colors.xml @@ -0,0 +1,11 @@ + + + + #FF006700 + #FF040091 + #FF980000 + #FF1700FF + #FF000000 + #FFAAAAAA + + diff --git a/library/jsonviewer/src/main/res/values/strings.xml b/library/jsonviewer/src/main/res/values/strings.xml new file mode 100644 index 0000000000..cc4b8726b4 --- /dev/null +++ b/library/jsonviewer/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Copy Value + diff --git a/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt new file mode 100644 index 0000000000..4caf9ce958 --- /dev/null +++ b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer + +import org.junit.Assert +import org.junit.Test + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ModelParseTest { + @Test + fun parsing_isCorrect() { + val string = """ + { + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } + } + """.trim() + + val model = ModelParser.fromJsonString(string) + + Assert.assertEquals(0, model.depth) + Assert.assertEquals(1, model.keys.size) + Assert.assertTrue(model.keys.containsKey("glossary")) + Assert.assertTrue(model.keys["glossary"] is JSonViewerObject) + + val glossary = model.keys["glossary"] as JSonViewerObject + Assert.assertEquals(2, glossary.keys.size) + Assert.assertTrue(glossary.keys.containsKey("title")) + Assert.assertTrue(glossary.keys.containsKey("GlossDiv")) + + Assert.assertTrue(glossary.keys["title"] is JSonViewerLeaf) + (glossary.keys["title"] as JSonViewerLeaf).let { + Assert.assertEquals(JSONType.STRING, it.type) + } + + + Assert.assertTrue(glossary.keys["GlossDiv"] is JSonViewerObject) + val glossDiv = glossary.keys["GlossDiv"] as JSonViewerObject + + + Assert.assertTrue(glossDiv.keys["GlossList"] is JSonViewerObject) + val glossList = glossDiv.keys["GlossList"] as JSonViewerObject + + + Assert.assertTrue(glossList.keys["GlossEntry"] is JSonViewerObject) + val glossEntry = glossList.keys["GlossEntry"] as JSonViewerObject + + Assert.assertTrue(glossEntry.keys["GlossDef"] is JSonViewerObject) + val glossDef = glossEntry.keys["GlossDef"] as JSonViewerObject + + + Assert.assertTrue(glossDef.keys["GlossSeeAlso"] is JSonViewerArray) + val glossSeeAlso = glossDef.keys["GlossSeeAlso"] as JSonViewerArray + + Assert.assertEquals(2, glossSeeAlso.items.size) + Assert.assertEquals("0", glossSeeAlso.items.first().key) + Assert.assertEquals("GML", (glossSeeAlso.items.first() as JSonViewerLeaf).stringRes) + + } +} diff --git a/settings.gradle b/settings.gradle index e3b84b4733..7ba66c7cb1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,4 +5,5 @@ include ':diff-match-patch' include ':attachment-viewer' include ':multipicker' include ':library:ui-styles' +include ':library:jsonviewer' include ':matrix-sdk-android-flow' diff --git a/vector/build.gradle b/vector/build.gradle index f136543a2e..fad04ffabe 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -326,6 +326,7 @@ dependencies { implementation project(":diff-match-patch") implementation project(":multipicker") implementation project(":attachment-viewer") + implementation project(":library:jsonviewer") implementation project(":library:ui-styles") implementation 'androidx.multidex:multidex:2.0.1' @@ -458,7 +459,6 @@ dependencies { gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' implementation "androidx.emoji2:emoji2:1.0.1" - implementation('com.github.BillCarsonFr:JsonViewer:0.7') // WebRTC // org.webrtc:google-webrtc is for development purposes only From 2a7719cdf60f2828e02d216e01e3de711d9d3173 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 12:12:04 +0100 Subject: [PATCH 054/222] ktlint --- .../jsonviewer/JSonViewerEpoxyController.kt | 1 - .../org/billcarsonfr/jsonviewer/JSonViewerFragment.kt | 1 - .../org/billcarsonfr/jsonviewer/JSonViewerModel.kt | 2 -- .../jsonviewer/JSonViewerStyleProvider.kt | 1 - .../billcarsonfr/jsonviewer/JSonViewerViewModel.kt | 11 +++++++++-- .../java/org/billcarsonfr/jsonviewer/ValueItem.kt | 1 - .../org/billcarsonfr/jsonviewer/ModelParseTest.kt | 5 ----- .../features/analytics/DecryptionFailureTracker.kt | 2 +- .../app/features/reactions/EmojiRecyclerAdapter.kt | 2 +- 9 files changed, 11 insertions(+), 15 deletions(-) diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt index 1ff35f5005..9c48a137da 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt @@ -237,7 +237,6 @@ internal class JSonViewerEpoxyController(private val context: Context) : ) itemClickListener(View.OnClickListener { host.itemClicked(composed) }) } - } private fun itemClicked(model: JSonViewerModel) { diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt index a8aa2493d2..51e2797958 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt @@ -38,7 +38,6 @@ internal data class JSonViewerFragmentArgs( val styleProvider: JSonViewerStyleProvider? ) : Parcelable - class JSonViewerFragment : Fragment(), MavericksView { private val viewModel: JSonViewerViewModel by fragmentViewModel() diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt index 3850044880..3d1f8dd3e2 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerModel.kt @@ -38,7 +38,6 @@ internal class JSonViewerObject(key: String?, index: Int?, jObject: JSONObject) override fun addChild(model: JSonViewerModel) { keys[model.key!!] = model } - } internal class JSonViewerArray(key: String?, index: Int?, jObject: JSONArray) : @@ -53,7 +52,6 @@ internal class JSonViewerArray(key: String?, index: Int?, jObject: JSONArray) : internal class JSonViewerLeaf(key: String?, index: Int?, val stringRes: String, val type: JSONType) : JSonViewerModel(key, index, stringRes) - internal enum class JSONType { STRING, NUMBER, diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt index 956e585f80..4fc04c91e4 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerStyleProvider.kt @@ -43,4 +43,3 @@ data class JSonViewerStyleProvider( ) } } - diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt index d978573a64..bc3f022cfa 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerViewModel.kt @@ -16,7 +16,15 @@ package org.billcarsonfr.jsonviewer -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MavericksState +import com.airbnb.mvrx.MavericksViewModel +import com.airbnb.mvrx.MavericksViewModelFactory +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext import kotlinx.coroutines.launch internal data class JSonViewerState( @@ -61,7 +69,6 @@ internal class JSonViewerViewModel(initialState: JSonViewerState) : } catch (failure: Throwable) { JSonViewerState(Fail(failure)) } - } } } diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt index 5c003c97e9..9193a20ab2 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt @@ -75,7 +75,6 @@ internal abstract class ValueItem : EpoxyModelWithHolder() { v: View?, menuInfo: ContextMenu.ContextMenuInfo? ) { - if (copyValue != null) { val menuItem = menu?.add( Menu.NONE, R.id.copy_value, diff --git a/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt index 4caf9ce958..b2d80911f1 100644 --- a/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt +++ b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt @@ -69,28 +69,23 @@ class ModelParseTest { Assert.assertEquals(JSONType.STRING, it.type) } - Assert.assertTrue(glossary.keys["GlossDiv"] is JSonViewerObject) val glossDiv = glossary.keys["GlossDiv"] as JSonViewerObject - Assert.assertTrue(glossDiv.keys["GlossList"] is JSonViewerObject) val glossList = glossDiv.keys["GlossList"] as JSonViewerObject - Assert.assertTrue(glossList.keys["GlossEntry"] is JSonViewerObject) val glossEntry = glossList.keys["GlossEntry"] as JSonViewerObject Assert.assertTrue(glossEntry.keys["GlossDef"] is JSonViewerObject) val glossDef = glossEntry.keys["GlossDef"] as JSonViewerObject - Assert.assertTrue(glossDef.keys["GlossSeeAlso"] is JSonViewerArray) val glossSeeAlso = glossDef.keys["GlossSeeAlso"] as JSonViewerArray Assert.assertEquals(2, glossSeeAlso.items.size) Assert.assertEquals("0", glossSeeAlso.items.first().key) Assert.assertEquals("GML", (glossSeeAlso.items.first() as JSonViewerLeaf).stringRes) - } } diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index ec11702054..18fec37c62 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -18,8 +18,8 @@ package im.vector.app.features.analytics import im.vector.app.core.flow.tickerFlow import im.vector.app.core.time.Clock -import im.vector.app.features.analytics.plan.Error import im.vector.app.core.utils.compat.removeIfCompat +import im.vector.app.features.analytics.plan.Error import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt index 6abbbe29af..06d8a0bf88 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt @@ -31,8 +31,8 @@ import androidx.recyclerview.widget.RecyclerView import androidx.transition.AutoTransition import androidx.transition.TransitionManager import im.vector.app.R -import im.vector.app.features.reactions.data.EmojiData import im.vector.app.core.utils.compat.removeIfCompat +import im.vector.app.features.reactions.data.EmojiData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch From f0d5260be8418d2d5c1bba2875cbdca1a47ae430 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 12:34:14 +0100 Subject: [PATCH 055/222] Fix unit test --- .../test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt index b2d80911f1..350bcdf289 100644 --- a/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt +++ b/library/jsonviewer/src/test/java/org/billcarsonfr/jsonviewer/ModelParseTest.kt @@ -85,7 +85,8 @@ class ModelParseTest { val glossSeeAlso = glossDef.keys["GlossSeeAlso"] as JSonViewerArray Assert.assertEquals(2, glossSeeAlso.items.size) - Assert.assertEquals("0", glossSeeAlso.items.first().key) + Assert.assertEquals(0, glossSeeAlso.items.first().index) + Assert.assertNull(glossSeeAlso.items.first().key) Assert.assertEquals("GML", (glossSeeAlso.items.first() as JSonViewerLeaf).stringRes) } } From 7993ff39a5430e9bb8880b19929db36b97456f76 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 18 Jan 2022 15:33:48 +0300 Subject: [PATCH 056/222] Add missing fields to location event content. --- .../room/model/message/LocationAsset.kt | 25 ++++++++++++++++++ .../room/model/message/LocationAssetType.kt | 26 +++++++++++++++++++ .../model/message/MessageLocationContent.kt | 16 +++++++++++- .../room/send/LocalEchoEventFactory.kt | 10 ++++++- 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAsset.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAssetType.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAsset.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAsset.kt new file mode 100644 index 0000000000..e8b3cf2488 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAsset.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2020 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.api.session.room.model.message + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class LocationAsset( + @Json(name = "type") val type: LocationAssetType? = null +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAssetType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAssetType.kt new file mode 100644 index 0000000000..ef40e21c47 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/LocationAssetType.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2020 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.api.session.room.model.message + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = false) +enum class LocationAssetType { + @Json(name = "m.self") + SELF +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt index 9571cc4280..00720b9ae5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLocationContent.kt @@ -45,5 +45,19 @@ data class MessageLocationContent( @Json(name = "org.matrix.msc3488.location") val locationInfo: LocationInfo? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, - @Json(name = "m.new_content") override val newContent: Content? = null + @Json(name = "m.new_content") override val newContent: Content? = null, + + /** + * m.asset defines a generic asset that can be used for location tracking but also in other places like inventories, geofencing, checkins/checkouts etc. + * It should contain a mandatory namespaced type key defining what particular asset is being referred to. + * For the purposes of user location tracking m.self should be used in order to avoid duplicating the mxid. + */ + @Json(name = "m.asset") val locationAsset: LocationAsset? = null, + + /** + * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) + */ + @Json(name = "org.matrix.msc3488.ts") val ts: Long? = null, + + @Json(name = "org.matrix.msc1767.text") val text: String? = null ) : MessageContent 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 dc5e2a70f1..0cd33cd2d9 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 @@ -32,6 +32,8 @@ import org.matrix.android.sdk.api.session.room.model.message.AudioInfo import org.matrix.android.sdk.api.session.room.model.message.AudioWaveformInfo import org.matrix.android.sdk.api.session.room.model.message.FileInfo import org.matrix.android.sdk.api.session.room.model.message.ImageInfo +import org.matrix.android.sdk.api.session.room.model.message.LocationAsset +import org.matrix.android.sdk.api.session.room.model.message.LocationAssetType import org.matrix.android.sdk.api.session.room.model.message.LocationInfo import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent @@ -63,6 +65,7 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils +import java.util.concurrent.TimeUnit import javax.inject.Inject /** @@ -207,7 +210,12 @@ internal class LocalEchoEventFactory @Inject constructor( locationInfo = LocationInfo( geoUri = geoUri, description = geoUri - ) + ), + locationAsset = LocationAsset( + type = LocationAssetType.SELF + ), + ts = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), + text = geoUri ) return createMessageEvent(roomId, content) } From ea8465f5f3f96fab3ed75f6be541d3ab3e07f050 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:06:02 +0100 Subject: [PATCH 057/222] Version 1.3.15 for hotfix release --- matrix-sdk-android/build.gradle | 2 +- vector/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 a1fb006e88..8b32b7dbc5 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -31,7 +31,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.3.14\"" + buildConfigField "String", "SDK_VERSION", "\"1.3.15\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" resValue "string", "git_sdk_revision", "\"${gitRevision()}\"" diff --git a/vector/build.gradle b/vector/build.gradle index fad04ffabe..695c205002 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -18,7 +18,7 @@ ext.versionMinor = 3 // 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 = 14 +ext.versionPatch = 15 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 68cd303a59332a19f25ff96adbc312e944de6a0d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:11:01 +0100 Subject: [PATCH 058/222] towncrier --- CHANGES.md | 11 +++++++++++ changelog.d/4796.bugfix | 1 - changelog.d/4959.bugfix | 1 - changelog.d/4962.bugfix | 1 - changelog.d/4969.bugfix | 1 - 5 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 changelog.d/4796.bugfix delete mode 100644 changelog.d/4959.bugfix delete mode 100644 changelog.d/4962.bugfix delete mode 100644 changelog.d/4969.bugfix diff --git a/CHANGES.md b/CHANGES.md index e93d1bb089..cf885d5cd5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,14 @@ +Changes in Element v1.3.15 (2022-01-18) +======================================= + +Bugfixes 🐛 +---------- + - Fix crash when viewing source which contains an emoji ([#4796](https://github.com/vector-im/element-android/issues/4796)) + - Prevent crash in Timeline and add more logs. ([#4959](https://github.com/vector-im/element-android/issues/4959)) + - Fix crash on API <24 and make sure this error will not occur again. ([#4962](https://github.com/vector-im/element-android/issues/4962)) + - Fixes sign in/up crash when selecting ems and other server types which use SSO ([#4969](https://github.com/vector-im/element-android/issues/4969)) + + Changes in Element v1.3.14 (2022-01-12) ======================================= diff --git a/changelog.d/4796.bugfix b/changelog.d/4796.bugfix deleted file mode 100644 index df5b5a4eba..0000000000 --- a/changelog.d/4796.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash when viewing source which contains an emoji \ No newline at end of file diff --git a/changelog.d/4959.bugfix b/changelog.d/4959.bugfix deleted file mode 100644 index 6ffa3937f9..0000000000 --- a/changelog.d/4959.bugfix +++ /dev/null @@ -1 +0,0 @@ -Prevent crash in Timeline and add more logs. \ No newline at end of file diff --git a/changelog.d/4962.bugfix b/changelog.d/4962.bugfix deleted file mode 100644 index 489f91cfc3..0000000000 --- a/changelog.d/4962.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash on API <24 and make sure this error will not occur again. \ No newline at end of file diff --git a/changelog.d/4969.bugfix b/changelog.d/4969.bugfix deleted file mode 100644 index 6edfd498bf..0000000000 --- a/changelog.d/4969.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes sign in/up crash when selecting ems and other server types which use SSO \ No newline at end of file From 5e96e87bdc2bd12f8dd4844f8dbd0d2454c5f175 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:13:31 +0100 Subject: [PATCH 059/222] fastlane --- fastlane/metadata/android/en-US/changelogs/40103150.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40103150.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40103150.txt b/fastlane/metadata/android/en-US/changelogs/40103150.txt new file mode 100644 index 0000000000..2b5fbe76ca --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40103150.txt @@ -0,0 +1,2 @@ +Main changes in this version: First change in onboarding screens, including Analytics opt-in. Support for Events with Math added in the labs. +Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.15 \ No newline at end of file From 8af92a40917aacae92122070ca26e7a05315e25c Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Sat, 15 Jan 2022 23:26:18 +0000 Subject: [PATCH 060/222] Sync issue automation with element-web Add automation for * labelling Labs issues * adding design and product issues to boards * adding design and product PRs to boards * adding UISI issues to Crypto team board Fixes issue #4949 --- ...-move-labelled.yml => triage-labelled.yml} | 101 +++++++++---- .../workflows/triage-move-review-requests.yml | 139 ++++++++++++++++++ .github/workflows/triage-priority-bugs.yml | 5 +- ...e-unlabelled.yml => triage-unlabelled.yml} | 26 ++++ changelog.d/4949.misc | 1 + 5 files changed, 244 insertions(+), 28 deletions(-) rename .github/workflows/{triage-move-labelled.yml => triage-labelled.yml} (60%) create mode 100644 .github/workflows/triage-move-review-requests.yml rename .github/workflows/{triage-move-unlabelled.yml => triage-unlabelled.yml} (58%) create mode 100644 changelog.d/4949.misc diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-labelled.yml similarity index 60% rename from .github/workflows/triage-move-labelled.yml rename to .github/workflows/triage-labelled.yml index e2f5cc32e9..faa6c74a99 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -5,6 +5,31 @@ on: types: [labeled] jobs: + apply_Z-Labs_label: + name: Add Z-Labs label for features behind labs flags + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'A-Maths') || + contains(github.event.issue.labels.*.name, 'A-Message-Pinning') || + contains(github.event.issue.labels.*.name, 'A-Threads') || + contains(github.event.issue.labels.*.name, 'A-Polls') || + contains(github.event.issue.labels.*.name, 'A-Location-Sharing') || + contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') || + contains(github.event.issue.labels.*.name, 'Z-IA') || + contains(github.event.issue.labels.*.name, 'A-Themes-Custom') || + contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') || + contains(github.event.issue.labels.*.name, 'A-Tags') + steps: + - uses: actions/github-script@v5 + with: + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['Z-Labs'] + }) + move_needs_info_issues: name: X-Needs-Info issues to Need info column on triage board runs-on: ubuntu-latest @@ -51,32 +76,56 @@ jobs: PROJECT_ID: "PN_kwDOAM0swc0sUA" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - # delight_issues_to_board: - # name: Spaces issues to new Delight project board - # runs-on: ubuntu-latest - # # Skip in forks - # if: > - # github.repository == 'vector-im/element-android' && - # contains(github.event.issue.labels.*.name, 'A-Spaces') || - # contains(github.event.issue.labels.*.name, 'A-Space-Settings') || - # contains(github.event.issue.labels.*.name, 'A-Subspaces') - # steps: - # - uses: octokit/graphql-action@v2.x - # with: - # headers: '{"GraphQL-Features": "projects_next_graphql"}' - # query: | - # mutation add_to_project($projectid:ID!,$contentid:ID!) { - # addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - # projectNextItem { - # id - # } - # } - # } - # projectid: ${{ env.PROJECT_ID }} - # contentid: ${{ github.event.issue.node_id }} - # env: - # PROJECT_ID: "PN_kwDOAM0swc1HvQ" - # GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + add_product_issues: + name: X-Needs-Product to Design project board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'X-Needs-Product') + steps: + - uses: octokit/graphql-action@v2.x + id: add_to_project + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:ID!,$contentid:ID!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc4AAg6N" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + +# delight_issues_to_board: +# name: Spaces issues to new Delight project board +# runs-on: ubuntu-latest +# # Skip in forks +# if: > +# github.repository == 'vector-im/element-android' && +# contains(github.event.issue.labels.*.name, 'A-Spaces') || +# contains(github.event.issue.labels.*.name, 'A-Space-Settings') || +# contains(github.event.issue.labels.*.name, 'A-Subspaces') +# steps: +# - uses: octokit/graphql-action@v2.x +# with: +# headers: '{"GraphQL-Features": "projects_next_graphql"}' +# query: | +# mutation add_to_project($projectid:ID!,$contentid:ID!) { +# addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { +# projectNextItem { +# id +# } +# } +# } +# projectid: ${{ env.PROJECT_ID }} +# contentid: ${{ github.event.issue.node_id }} +# env: +# PROJECT_ID: "PN_kwDOAM0swc1HvQ" +# GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_voice-message_issues: name: A-Voice Messages to voice message board diff --git a/.github/workflows/triage-move-review-requests.yml b/.github/workflows/triage-move-review-requests.yml new file mode 100644 index 0000000000..75738a53a9 --- /dev/null +++ b/.github/workflows/triage-move-review-requests.yml @@ -0,0 +1,139 @@ +name: Move pull requests asking for review to the relevant project +on: + pull_request_target: + types: [review_requested] + +jobs: + add_design_pr_to_project: + name: Move PRs asking for design review to the design board + runs-on: ubuntu-latest + steps: + - uses: octokit/graphql-action@v2.x + id: find_team_members + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + query find_team_members($team: String!) { + organization(login: "vector-im") { + team(slug: $team) { + members { + nodes { + login + } + } + } + } + } + team: ${{ env.TEAM }} + env: + TEAM: "design" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + - id: any_matching_reviewers + run: | + # Fetch requested reviewers, and people who are on the team + echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json + echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json + jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt + jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt + + # Fetch requested team reviewers, and the name of the team + echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json + jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt + echo '${{ env.TEAM }}' | tee /tmp/team.txt + + # If either a reviewer matches a team member, or a team matches our team, say "true" + if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then + echo "::set-output name=match::true" + elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then + echo "::set-output name=match::true" + else + echo "::set-output name=match::false" + fi + env: + TEAM: "design" + - uses: octokit/graphql-action@v2.x + id: add_to_project + if: steps.any_matching_reviewers.outputs.match == 'true' + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:ID!, $contentid:ID!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.pull_request.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc0sUA" + TEAM: "design" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + add_product_pr_to_project: + name: Move PRs asking for product review to the product board + runs-on: ubuntu-latest + steps: + - uses: octokit/graphql-action@v2.x + id: find_team_members + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + query find_team_members($team: String!) { + organization(login: "vector-im") { + team(slug: $team) { + members { + nodes { + login + } + } + } + } + } + team: ${{ env.TEAM }} + env: + TEAM: "product" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + - id: any_matching_reviewers + run: | + # Fetch requested reviewers, and people who are on the team + echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json + echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json + jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt + jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt + + # Fetch requested team reviewers, and the name of the team + echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json + jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt + echo '${{ env.TEAM }}' | tee /tmp/team.txt + + # If either a reviewer matches a team member, or a team matches our team, say "true" + if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then + echo "::set-output name=match::true" + elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then + echo "::set-output name=match::true" + else + echo "::set-output name=match::false" + fi + env: + TEAM: "product" + - uses: octokit/graphql-action@v2.x + id: add_to_project + if: steps.any_matching_reviewers.outputs.match == 'true' + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:ID!, $contentid:ID!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.pull_request.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc4AAg6N" + TEAM: "product" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/.github/workflows/triage-priority-bugs.yml b/.github/workflows/triage-priority-bugs.yml index daea78de19..70c337e748 100644 --- a/.github/workflows/triage-priority-bugs.yml +++ b/.github/workflows/triage-priority-bugs.yml @@ -38,7 +38,8 @@ jobs: # Skip in forks if: > github.repository == 'vector-im/element-android' && - (contains(github.event.issue.labels.*.name, 'A-E2EE') || + (contains(github.event.issue.labels.*.name, 'Z-UISI') || + (contains(github.event.issue.labels.*.name, 'A-E2EE') || contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') || contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') || contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') || @@ -50,7 +51,7 @@ jobs: contains(github.event.issue.labels.*.name, 'S-Major') && contains(github.event.issue.labels.*.name, 'O-Frequent') || contains(github.event.issue.labels.*.name, 'A11y') && - contains(github.event.issue.labels.*.name, 'O-Frequent')) + contains(github.event.issue.labels.*.name, 'O-Frequent'))) steps: - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 with: diff --git a/.github/workflows/triage-move-unlabelled.yml b/.github/workflows/triage-unlabelled.yml similarity index 58% rename from .github/workflows/triage-move-unlabelled.yml rename to .github/workflows/triage-unlabelled.yml index eb90cdb503..06df286d09 100644 --- a/.github/workflows/triage-move-unlabelled.yml +++ b/.github/workflows/triage-unlabelled.yml @@ -34,3 +34,29 @@ jobs: project: Issue triage column: Triaged repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} + + remove_Z-Labs_label: + name: Remove Z-Labs label when features behind labs flags are removed + runs-on: ubuntu-latest + if: > + !(contains(github.event.issue.labels.*.name, 'A-Maths') || + contains(github.event.issue.labels.*.name, 'A-Message-Pinning') || + contains(github.event.issue.labels.*.name, 'A-Threads') || + contains(github.event.issue.labels.*.name, 'A-Polls') || + contains(github.event.issue.labels.*.name, 'A-Location-Sharing') || + contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') || + contains(github.event.issue.labels.*.name, 'Z-IA') || + contains(github.event.issue.labels.*.name, 'A-Themes-Custom') || + contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') || + contains(github.event.issue.labels.*.name, 'A-Tags')) && + contains(github.event.issue.labels.*.name, 'Z-Labs') + steps: + - uses: actions/github-script@v5 + with: + script: | + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: ['Z-Labs'] + }) diff --git a/changelog.d/4949.misc b/changelog.d/4949.misc new file mode 100644 index 0000000000..8f23c7a05e --- /dev/null +++ b/changelog.d/4949.misc @@ -0,0 +1 @@ +Sync issue automation with element-web From ffad479dadb9c6336809db030f08bf4f013d0051 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:30:59 +0100 Subject: [PATCH 061/222] Move the file to the new module. --- .../im/vector/lib}/core/utils/compat/MutableCollectionCompat.kt | 2 +- .../vector/app/features/analytics/DecryptionFailureTracker.kt | 2 +- .../im/vector/app/features/reactions/EmojiRecyclerAdapter.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename {vector/src/main/java/im/vector/app => library/core-utils/src/main/java/im/vector/lib}/core/utils/compat/MutableCollectionCompat.kt (95%) diff --git a/vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt b/library/core-utils/src/main/java/im/vector/lib/core/utils/compat/MutableCollectionCompat.kt similarity index 95% rename from vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt rename to library/core-utils/src/main/java/im/vector/lib/core/utils/compat/MutableCollectionCompat.kt index e131b5f328..332ed27ca3 100644 --- a/vector/src/main/java/im/vector/app/core/utils/compat/MutableCollectionCompat.kt +++ b/library/core-utils/src/main/java/im/vector/lib/core/utils/compat/MutableCollectionCompat.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.core.utils.compat +package im.vector.lib.core.utils.compat import android.os.Build diff --git a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt index d3c1767c83..8b9dcc348b 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/DecryptionFailureTracker.kt @@ -17,8 +17,8 @@ package im.vector.app.features.analytics import im.vector.app.core.time.Clock -import im.vector.app.core.utils.compat.removeIfCompat import im.vector.app.features.analytics.plan.Error +import im.vector.lib.core.utils.compat.removeIfCompat import im.vector.lib.core.utils.flow.tickerFlow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt index 06d8a0bf88..5c0d2f36f5 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiRecyclerAdapter.kt @@ -31,8 +31,8 @@ import androidx.recyclerview.widget.RecyclerView import androidx.transition.AutoTransition import androidx.transition.TransitionManager import im.vector.app.R -import im.vector.app.core.utils.compat.removeIfCompat import im.vector.app.features.reactions.data.EmojiData +import im.vector.lib.core.utils.compat.removeIfCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch From 1c42df775292c20340defa741b9d31526d7ae3eb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:39:02 +0100 Subject: [PATCH 062/222] Move the file to the new module. --- .../lib/core/utils}/epoxy/charsequence/EpoxyCharSequence.kt | 2 +- .../vector/lib/core/utils}/epoxy/charsequence/Extensions.kt | 2 +- .../core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt | 2 +- .../main/java/im/vector/app/core/ui/list/GenericFooterItem.kt | 2 +- .../src/main/java/im/vector/app/core/ui/list/GenericItem.kt | 2 +- .../main/java/im/vector/app/core/ui/list/GenericPillItem.kt | 2 +- .../java/im/vector/app/core/ui/list/GenericWithValueItem.kt | 2 +- .../settings/KeysBackupSettingsRecyclerViewController.kt | 2 +- .../verification/cancel/VerificationCancelController.kt | 4 ++-- .../crypto/verification/cancel/VerificationNotMeController.kt | 2 +- .../verification/choose/VerificationChooseMethodController.kt | 2 +- .../conclusion/VerificationConclusionController.kt | 2 +- .../verification/emoji/VerificationEmojiCodeController.kt | 2 +- .../verification/epoxy/BottomSheetVerificationNoticeItem.kt | 2 +- .../qrconfirmation/VerificationQRWaitingController.kt | 2 +- .../qrconfirmation/VerificationQrScannedByOtherController.kt | 2 +- .../verification/request/VerificationRequestController.kt | 2 +- .../app/features/devtools/RoomDevToolSendFormController.kt | 2 +- .../vector/app/features/devtools/RoomStateListController.kt | 4 ++-- .../home/room/detail/search/SearchResultController.kt | 2 +- .../app/features/home/room/detail/search/SearchResultItem.kt | 2 +- .../detail/timeline/action/MessageActionsEpoxyController.kt | 2 +- .../timeline/edithistory/ViewEditHistoryEpoxyController.kt | 2 +- .../home/room/detail/timeline/factory/EncryptedItemFactory.kt | 2 +- .../home/room/detail/timeline/factory/MessageItemFactory.kt | 2 +- .../home/room/detail/timeline/factory/NoticeItemFactory.kt | 2 +- .../room/detail/timeline/factory/RoomCreateItemFactory.kt | 2 +- .../home/room/detail/timeline/item/MessageBlockCodeItem.kt | 2 +- .../home/room/detail/timeline/item/MessageTextItem.kt | 2 +- .../app/features/home/room/detail/timeline/item/NoticeItem.kt | 2 +- .../features/home/room/detail/timeline/item/RoomCreateItem.kt | 2 +- .../room/detail/timeline/reactions/ReactionInfoSimpleItem.kt | 2 +- .../detail/timeline/reactions/ViewReactionsEpoxyController.kt | 2 +- .../features/home/room/detail/widget/RoomWidgetsController.kt | 2 +- .../im/vector/app/features/home/room/list/RoomSummaryItem.kt | 2 +- .../app/features/home/room/list/RoomSummaryItemFactory.kt | 2 +- .../app/features/onboarding/ftueauth/SplashCarouselState.kt | 2 +- .../onboarding/ftueauth/SplashCarouselStateFactory.kt | 4 ++-- .../vector/app/features/poll/create/CreatePollController.kt | 2 +- .../app/features/reactions/EmojiSearchResultController.kt | 2 +- .../roomdirectory/createroom/CreateSubSpaceController.kt | 2 +- .../features/roommemberprofile/RoomMemberProfileController.kt | 2 +- .../roommemberprofile/devices/DeviceListEpoxyController.kt | 2 +- .../devices/DeviceTrustInfoEpoxyController.kt | 2 +- .../vector/app/features/roomprofile/RoomProfileController.kt | 2 +- .../roomprofile/banned/RoomBannedMemberListController.kt | 2 +- .../settings/joinrule/RoomJoinRuleAdvancedController.kt | 2 +- .../settings/joinrule/advanced/ChooseRestrictedController.kt | 2 +- .../settings/crosssigning/CrossSigningSettingsController.kt | 2 +- .../devices/DeviceVerificationInfoBottomSheetController.kt | 2 +- .../features/settings/devtools/AccountDataEpoxyController.kt | 2 +- .../settings/devtools/GossipingTrailPagedEpoxyController.kt | 2 +- .../settings/devtools/IncomingKeyRequestPagedController.kt | 2 +- .../settings/devtools/OutgoingKeyRequestPagedController.kt | 2 +- .../settings/homeserver/HomeserverSettingsController.kt | 2 +- .../app/features/settings/push/PushGateWayController.kt | 2 +- .../vector/app/features/settings/push/PushRulesController.kt | 2 +- .../settings/threepids/ThreePidsSettingsController.kt | 2 +- .../im/vector/app/features/spaces/SpaceSummaryController.kt | 2 +- .../app/features/spaces/create/SpaceAdd3pidEpoxyController.kt | 2 +- .../features/spaces/create/SpaceDefaultRoomEpoxyController.kt | 2 +- .../app/features/spaces/create/SpaceDetailEpoxyController.kt | 2 +- .../app/features/spaces/explore/SpaceDirectoryController.kt | 2 +- .../app/features/spaces/manage/AddRoomListController.kt | 2 +- .../app/features/spaces/manage/SpaceManageRoomsController.kt | 2 +- .../app/features/spaces/people/SpacePeopleListController.kt | 2 +- .../vector/app/features/userdirectory/UserListController.kt | 2 +- 67 files changed, 70 insertions(+), 70 deletions(-) rename {vector/src/main/java/im/vector/app/core => library/core-utils/src/main/java/im/vector/lib/core/utils}/epoxy/charsequence/EpoxyCharSequence.kt (94%) rename {vector/src/main/java/im/vector/app/core => library/core-utils/src/main/java/im/vector/lib/core/utils}/epoxy/charsequence/Extensions.kt (93%) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt b/library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/EpoxyCharSequence.kt similarity index 94% rename from vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt rename to library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/EpoxyCharSequence.kt index dcd19b598d..77e2d58001 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt +++ b/library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/EpoxyCharSequence.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.core.epoxy.charsequence +package im.vector.lib.core.utils.epoxy.charsequence /** * Wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering diff --git a/vector/src/main/java/im/vector/app/core/epoxy/charsequence/Extensions.kt b/library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/Extensions.kt similarity index 93% rename from vector/src/main/java/im/vector/app/core/epoxy/charsequence/Extensions.kt rename to library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/Extensions.kt index b6d918c575..ba0f0b9ad6 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/charsequence/Extensions.kt +++ b/library/core-utils/src/main/java/im/vector/lib/core/utils/epoxy/charsequence/Extensions.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.core.epoxy.charsequence +package im.vector.lib.core.utils.epoxy.charsequence /** * Extensions to wrap CharSequence to EpoxyCharSequence diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index 35db585b79..8e61a1c1cb 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -26,7 +26,6 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.displayname.getBestName @@ -34,6 +33,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess import im.vector.app.features.media.ImageContentRenderer +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.util.MatrixItem /** diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt index 5e3ea285a5..6d7763cd48 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt @@ -24,10 +24,10 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * A generic list item. diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt index 3a691ddfd5..7b00001e4c 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt @@ -28,9 +28,9 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * A generic list item. diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt index e116561ecb..09fdcded6e 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt @@ -28,10 +28,10 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * A generic list item with a rounded corner background and an optional icon diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt index f95281eb75..e633b633a7 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt @@ -27,10 +27,10 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * A generic list item. diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt index 010255256e..577572ef14 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt @@ -22,13 +22,13 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle import im.vector.app.core.ui.list.genericItem import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt index f0909dbc26..1adafe2760 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt @@ -20,14 +20,14 @@ import androidx.core.text.toSpannable import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class VerificationCancelController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt index 34f97d3cb2..a7c987f97e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt @@ -19,13 +19,13 @@ package im.vector.app.features.crypto.verification.cancel import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.html.EventHtmlRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class VerificationNotMeController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt index 352c21a156..acc8cf61b9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt @@ -19,12 +19,12 @@ package im.vector.app.features.crypto.verification.choose import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationQrCodeItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class VerificationChooseMethodController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt index 1314fd6fec..1d6dfbd947 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt @@ -19,13 +19,13 @@ package im.vector.app.features.crypto.verification.conclusion import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.html.EventHtmlRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt index 838f25ddfa..9f3e8ff690 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt @@ -21,7 +21,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Success import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.ColorProvider @@ -32,6 +31,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationE import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem import im.vector.app.features.displayname.getBestName +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class VerificationEmojiCodeController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt index f63459991b..ecd9989cdc 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt @@ -22,7 +22,7 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * A action for bottom sheet. diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt index cef5994c38..8de5f94ec9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt @@ -18,12 +18,12 @@ package im.vector.app.features.crypto.verification.qrconfirmation import com.airbnb.epoxy.EpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index bb21a6ccef..38f29622d0 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.crypto.verification.qrconfirmation import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState @@ -27,6 +26,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationA import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.displayname.getBestName +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt index d40ee1f5c9..90997830a0 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt @@ -23,7 +23,6 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.colorizeMatchingText @@ -33,6 +32,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationA import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem import im.vector.app.features.displayname.getBestName +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class VerificationRequestController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt index f0a6f40208..573ec0c085 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolSendFormController.kt @@ -18,11 +18,11 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formMultiLineEditTextItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class RoomDevToolSendFormController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt index ee5ae600ff..3f05db8ed5 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt @@ -18,11 +18,11 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.json.JSONObject import javax.inject.Inject @@ -37,7 +37,7 @@ class RoomStateListController @Inject constructor( override fun buildModels(data: RoomDevToolViewState?) { val host = this when (data?.displayMode) { - RoomDevToolViewState.Mode.StateEventList -> { + RoomDevToolViewState.Mode.StateEventList -> { val stateEventsGroups = data.stateEvents.invoke().orEmpty().groupBy { it.getClearType() } if (stateEventsGroups.isEmpty()) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt index 4c5a52864d..ccf83011a8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt @@ -26,12 +26,12 @@ import com.airbnb.epoxy.VisibilityState import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.GenericHeaderItem_ import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt index 9d146792d9..95dea2b8d2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt @@ -24,11 +24,11 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass(layout = R.layout.item_search_result) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 15f33db6ff..27819ca863 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -27,7 +27,6 @@ import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetMessagePreviewItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetQuickReactionsItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetSendStateItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.DimensionConverter @@ -40,6 +39,7 @@ import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovement import im.vector.app.features.home.room.detail.timeline.tools.linkify import im.vector.app.features.html.SpanUtils import im.vector.app.features.media.ImageContentRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.room.send.SendState diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt index 19b6b8c71a..1dad6cc4a7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt @@ -23,7 +23,6 @@ import com.airbnb.mvrx.Success import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem @@ -31,6 +30,7 @@ import im.vector.app.core.ui.list.genericHeaderItem import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.list.genericLoaderItem import im.vector.app.features.html.EventHtmlRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import name.fraser.neil.plaintext.diff_match_patch import org.matrix.android.sdk.api.session.events.model.Event diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt index 89c9c51f0c..4f8a36e234 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt @@ -18,7 +18,6 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider @@ -28,6 +27,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttrib import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem_ import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.session.crypto.MXCryptoError 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 21af8b82cb..ec0c247a03 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 @@ -28,7 +28,6 @@ import dagger.Lazy import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider @@ -70,6 +69,7 @@ import im.vector.app.features.html.SpanUtils import im.vector.app.features.html.VectorHtmlCompressor import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.commonmark.node.Document import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt index 70c8fa7574..6951c3c316 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt @@ -16,13 +16,13 @@ package im.vector.app.features.home.room.detail.timeline.factory -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.format.NoticeEventFormatter import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory import im.vector.app.features.home.room.detail.timeline.item.NoticeItem import im.vector.app.features.home.room.detail.timeline.item.NoticeItem_ +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt index 3a3d269058..fff709f346 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt @@ -18,10 +18,10 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.room.detail.timeline.item.RoomCreateItem_ +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.toModel diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt index be9b727017..915ad6a17d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt @@ -20,9 +20,9 @@ import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import me.saket.bettermovementmethod.BetterLinkMovementMethod @EpoxyModelClass(layout = R.layout.item_timeline_event_base) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt index e499f090fb..1794f04c2a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt @@ -25,7 +25,6 @@ import androidx.core.widget.TextViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.onLongClickIgnoringLinks import im.vector.app.features.home.room.detail.timeline.TimelineEventController @@ -34,6 +33,7 @@ import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlUiState import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlView import im.vector.app.features.media.ImageContentRenderer +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import io.noties.markwon.MarkwonPlugin import org.matrix.android.sdk.api.extensions.orFalse diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt index 2851668df5..689d7e6768 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt @@ -23,11 +23,11 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.ClickListener -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.TimelineEventController +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt index 34edcfe9f4..a6d2bcc66d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt @@ -22,7 +22,7 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import me.saket.bettermovementmethod.BetterLinkMovementMethod @EpoxyModelClass(layout = R.layout.item_timeline_event_create) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt index f6976d96bf..f150e13016 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt @@ -24,8 +24,8 @@ import com.airbnb.epoxy.EpoxyModelWithHolder import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence /** * Item displaying an emoji reaction (single line with emoji, author, time) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt index 17a3ac4a5f..10af3792d5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt @@ -22,10 +22,10 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success import im.vector.app.EmojiSpanify import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericLoaderItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject /** diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt index 5c2ad3799b..b2da3bfc78 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt @@ -18,11 +18,11 @@ package im.vector.app.features.home.room.detail.widget import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericButtonItem import im.vector.app.core.ui.list.genericFooterItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.widgets.model.Widget import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index 4261acd7ee..b037191ad1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -30,7 +30,6 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.ui.views.PresenceStateImageView @@ -38,6 +37,7 @@ import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.presence.model.UserPresence import org.matrix.android.sdk.api.util.MatrixItem diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index ff57544a36..6326d9c97a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -23,12 +23,12 @@ import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter import im.vector.app.features.home.room.typing.TypingHelper +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt index 5328722a99..7f68cef307 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt @@ -18,7 +18,7 @@ package im.vector.app.features.onboarding.ftueauth import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence data class SplashCarouselState( val items: List diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt index 4ea462f737..da5f8b6379 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselStateFactory.kt @@ -20,13 +20,13 @@ import android.content.Context import androidx.annotation.AttrRes import androidx.annotation.DrawableRes import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.LocaleProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.isEnglishSpeaking import im.vector.app.features.themes.ThemeProvider import im.vector.app.features.themes.ThemeUtils +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt index 90128d9263..3b170ef799 100644 --- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt +++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt @@ -20,7 +20,6 @@ import android.view.Gravity import android.view.inputmethod.EditorInfo import com.airbnb.epoxy.EpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -28,6 +27,7 @@ import im.vector.app.core.ui.list.genericButtonItem import im.vector.app.core.ui.list.genericItem import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formEditTextWithDeleteItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class CreatePollController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt index f1165e44d4..f699a86d33 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiSearchResultController.kt @@ -20,9 +20,9 @@ import androidx.recyclerview.widget.RecyclerView import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.EmojiCompatFontProvider import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class EmojiSearchResultController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt index c8d907b0b2..e67b272c32 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt @@ -20,7 +20,6 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericPillItem @@ -29,6 +28,7 @@ import im.vector.app.features.form.formEditTextItem import im.vector.app.features.form.formEditableSquareAvatarItem import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.app.features.form.formSubmitButtonItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.model.RoomJoinRules diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt index ca022edcab..22a1779a2b 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt @@ -19,11 +19,11 @@ package im.vector.app.features.roommemberprofile import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt index 8b49c694c4..3bfb210f8d 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.ColorProvider @@ -33,6 +32,7 @@ import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt index 8ee6967afa..c7f6e64f5c 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.roommemberprofile.devices import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -28,6 +27,7 @@ import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index a1eeaf9286..e4630dae3f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.roomprofile import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.expandableTextItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection @@ -32,6 +31,7 @@ import im.vector.app.features.home.ShortcutCreator import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.image import me.gujun.android.span.span import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt index 1e0572297b..cc332c0ba2 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.roomprofile.banned import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.epoxy.profiles.profileMatrixItemWithProgress @@ -27,6 +26,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.members.RoomMemberSummaryFilter +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt index 5e963b4cbc..caf4b1843a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.roomprofile.settings.joinrule import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -26,6 +25,7 @@ import im.vector.app.core.ui.list.genericButtonItem import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt index b301b8c947..bbec3ca4a5 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChooseRestrictedController.kt @@ -22,13 +22,13 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.spaces.manage.roomSelectionItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.util.MatrixItem import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt index d00cb783c9..548b6fa59a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt @@ -17,7 +17,6 @@ package im.vector.app.features.settings.crosssigning import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericButtonItem @@ -25,6 +24,7 @@ import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.list.genericPositiveButtonItem import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt index 040ee9ab84..2b8fa4b49a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.settings.devices import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider @@ -27,6 +26,7 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.views.toDrawableRes import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import timber.log.Timber diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt index 93cac3a0f6..f3ae18a72f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt @@ -22,11 +22,11 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericWithValueItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt index 08d0d60909..c1b05cca42 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt @@ -21,10 +21,10 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt index 1e13fa37bb..4c8bd65c0e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt @@ -20,9 +20,9 @@ import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt index 5d89bf9b1c..0a52c1a7dd 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt @@ -18,9 +18,9 @@ package im.vector.app.features.settings.devtools import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt index d2ec53523c..f690a25ab8 100644 --- a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -32,6 +31,7 @@ import im.vector.app.features.discovery.settingsCenteredImageItem import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsSectionTitleItem import im.vector.app.features.settings.VectorPreferences +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.federation.FederationVersion import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt index 3daeace09f..68c3e960c7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGateWayController.kt @@ -18,9 +18,9 @@ package im.vector.app.features.settings.push import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class PushGateWayController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt index ed6a31d070..68f288ffd3 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushRulesController.kt @@ -18,9 +18,9 @@ package im.vector.app.features.settings.push import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class PushRulesController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt index f3c0469d79..d374357396 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.error.ErrorFormatter @@ -38,6 +37,7 @@ import im.vector.app.features.discovery.settingsEditTextItem import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsInformationItem import im.vector.app.features.discovery.settingsSectionTitleItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.identity.ThreePid diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt index e8c2c4bde6..95e4405da5 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt @@ -19,7 +19,6 @@ package im.vector.app.features.spaces import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.RoomGroupingMethod -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem @@ -30,6 +29,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.UnreadCounterBadgeView import im.vector.app.group import im.vector.app.space +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.room.model.Membership diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt index 816931a7c1..1193ecb496 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt @@ -20,7 +20,6 @@ import android.text.InputType import com.airbnb.epoxy.TypedEpoxyController import com.google.android.material.textfield.TextInputLayout import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -28,6 +27,7 @@ import im.vector.app.core.ui.list.genericButtonItem import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.form.formEditTextItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class SpaceAdd3pidEpoxyController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt index 3353e66b3c..4ef469500b 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDefaultRoomEpoxyController.kt @@ -19,12 +19,12 @@ package im.vector.app.features.spaces.create import com.airbnb.epoxy.TypedEpoxyController import com.google.android.material.textfield.TextInputLayout import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.form.formEditTextItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import javax.inject.Inject class SpaceDefaultRoomEpoxyController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt index a22256c3e1..b25ae4f2c7 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceDetailEpoxyController.kt @@ -20,7 +20,6 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import im.vector.app.R import im.vector.app.core.epoxy.TextListener -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.form.formEditTextItem @@ -28,6 +27,7 @@ import im.vector.app.features.form.formEditableSquareAvatarItem import im.vector.app.features.form.formMultiLineEditTextItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.MatrixConstants import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import org.matrix.android.sdk.api.util.MatrixItem diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt index 6dadce30e0..a2c1380098 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt @@ -24,7 +24,6 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Uninitialized import im.vector.app.R import im.vector.app.core.epoxy.ClickListener -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -35,6 +34,7 @@ import im.vector.app.core.ui.list.genericEmptyWithActionItem import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.spaceChildInfoItem +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError.Companion.M_UNRECOGNIZED diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt index ec88e9f8a6..3164daf634 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt @@ -20,11 +20,11 @@ import androidx.recyclerview.widget.DiffUtil import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericPillItem_ import im.vector.app.core.utils.createUIHandler import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.list.RoomCategoryItem_ +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.room.ResultBoundaries import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.util.toMatrixItem diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt index 67c9f83498..54f19ce297 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageRoomsController.kt @@ -21,13 +21,13 @@ import com.airbnb.epoxy.VisibilityState import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Incomplete import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import org.matrix.android.sdk.api.util.toMatrixItem import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt index 62bd866cb1..1fbe9bbbf9 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.spaces.people import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.profiles.profileMatrixItemWithPowerLevel @@ -31,6 +30,7 @@ import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.members.RoomMemberListCategories import im.vector.app.features.roomprofile.members.RoomMemberListViewState import im.vector.app.features.roomprofile.members.RoomMemberSummaryFilter +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.util.toMatrixItem diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt index cb0ec7c36b..55858b2baf 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt @@ -22,7 +22,6 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R -import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem @@ -32,6 +31,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericPillItem import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.identity.IdentityServiceError From a38a03c98064f95306f157c60d5b1478e2d650b2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:41:35 +0100 Subject: [PATCH 063/222] Use class from common module --- library/jsonviewer/build.gradle | 2 ++ .../jsonviewer/JSonViewerEpoxyController.kt | 13 ++++---- .../jsonviewer/SafeCharSequence.kt | 30 ------------------- .../org/billcarsonfr/jsonviewer/ValueItem.kt | 3 +- 4 files changed, 11 insertions(+), 37 deletions(-) delete mode 100644 library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle index ee2be6fd25..223cb18acc 100644 --- a/library/jsonviewer/build.gradle +++ b/library/jsonviewer/build.gradle @@ -42,6 +42,8 @@ android { } dependencies { + implementation project(":library:core-utils") + implementation libs.androidx.appCompat implementation libs.androidx.core diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt index 9c48a137da..96b5a9c997 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerEpoxyController.kt @@ -21,6 +21,7 @@ import android.view.View import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Success +import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.Span import me.gujun.android.span.span @@ -40,7 +41,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : is Fail -> { valueItem { id("fail") - text(async.error.localizedMessage?.toSafeCharSequence()) + text(async.error.localizedMessage?.toEpoxyCharSequence()) } } is Success -> { @@ -94,7 +95,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : +"{+${model.keys.size}}" textColor = host.styleProvider.baseColor } - }.toSafeCharSequence() + }.toEpoxyCharSequence() ) itemClickListener(View.OnClickListener { host.itemClicked(model) }) } @@ -133,7 +134,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : +"[+${model.items.size}]" textColor = host.styleProvider.baseColor } - }.toSafeCharSequence() + }.toEpoxyCharSequence() ) itemClickListener(View.OnClickListener { host.itemClicked(model) }) } @@ -163,7 +164,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : } } append(host.valueToSpan(model)) - }.toSafeCharSequence() + }.toEpoxyCharSequence() ) copyValue(model.stringRes) } @@ -233,7 +234,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : span("{".takeIf { isObject } ?: "[") { textColor = host.styleProvider.baseColor } - }.toSafeCharSequence() + }.toEpoxyCharSequence() ) itemClickListener(View.OnClickListener { host.itemClicked(composed) }) } @@ -253,7 +254,7 @@ internal class JSonViewerEpoxyController(private val context: Context) : span { text = "}".takeIf { isObject } ?: "]" textColor = host.styleProvider.baseColor - }.toSafeCharSequence() + }.toEpoxyCharSequence() ) } } diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt deleted file mode 100644 index 79556f81d7..0000000000 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/SafeCharSequence.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2022 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 org.billcarsonfr.jsonviewer - -/** - * Wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering - * TODO Mutualize - */ -internal class SafeCharSequence(val charSequence: CharSequence) { - private val hash = charSequence.toString().hashCode() - - override fun hashCode() = hash - override fun equals(other: Any?) = other is SafeCharSequence && other.hash == hash -} - -internal fun CharSequence.toSafeCharSequence() = SafeCharSequence(this) diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt index 9193a20ab2..227ac2a71d 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/ValueItem.kt @@ -28,12 +28,13 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyHolder import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelWithHolder +import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence @EpoxyModelClass(layout = R2.layout.item_jv_base_value) internal abstract class ValueItem : EpoxyModelWithHolder() { @EpoxyAttribute - var text: SafeCharSequence? = null + var text: EpoxyCharSequence? = null @EpoxyAttribute var depth: Int = 0 From 2dfded73261ab178abfe900e6ae37e2041ebe433 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 18 Jan 2022 14:42:32 +0100 Subject: [PATCH 064/222] Remove comment --- .../src/main/java/org/billcarsonfr/jsonviewer/Utils.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt index 6536a3401e..efb2bfd855 100644 --- a/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt +++ b/library/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/Utils.kt @@ -19,9 +19,6 @@ package org.billcarsonfr.jsonviewer import android.content.Context import android.util.TypedValue -/** - * TODO Mutualize - */ internal object Utils { fun dpToPx(dp: Int, context: Context): Int { return TypedValue.applyDimension( From 69c05e63d4bbf87d33dc189d20482890ed4c2b49 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 11:46:49 +0000 Subject: [PATCH 065/222] only reverting to the combined sign in/sign up screen when the currently login mode isn't supported - eg for a SSO only flow or unknown/unsupported --- .../app/features/onboarding/OnboardingViewModel.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 366ad044b3..43f37f4601 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -852,7 +852,7 @@ class OnboardingViewModel @AssistedInject constructor( } withState { - if (it.serverType == ServerType.MatrixOrg) { + if (loginMode.supportsSignModeScreen()) { when (it.onboardingFlow) { OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn)) OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp)) @@ -880,3 +880,13 @@ class OnboardingViewModel @AssistedInject constructor( return authenticationService.getFallbackUrl(forSignIn, deviceId) } } + +private fun LoginMode.supportsSignModeScreen(): Boolean { + return when (this) { + LoginMode.Password, + is LoginMode.SsoAndPassword -> true + is LoginMode.Sso, + LoginMode.Unknown, + LoginMode.Unsupported -> false + } +} From a3dd3a830cf2d80e092369593f6341cf6d3e07be Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 12:37:42 +0000 Subject: [PATCH 066/222] fixing wrong wait function being used --- .../androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt index 53d6c16bb7..a5cd0badb3 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt @@ -127,7 +127,7 @@ class RoomDetailRobot { fun openSettings(block: RoomSettingsRobot.() -> Unit) { clickMenu(R.id.timeline_setting) - waitForView(withId(R.id.roomProfileAvatarView)) + waitUntilViewVisible(withId(R.id.roomProfileAvatarView)) sleep(1000) block(RoomSettingsRobot()) pressBack() From eb763bb5bb09d8d60f3157d929ba4334153d1c3b Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 12:38:03 +0000 Subject: [PATCH 067/222] adding onboarding option crawling to the sanity tests --- .../vector/app/ui/UiAllScreensSanityTest.kt | 4 + .../im/vector/app/ui/robot/ElementRobot.kt | 4 + .../im/vector/app/ui/robot/OnboardingRobot.kt | 92 +++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt index 33e1e6f6b4..042e9ef3ee 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt @@ -55,6 +55,10 @@ class UiAllScreensSanityTest { fun allScreensTest() { IdlingPolicies.setMasterPolicyTimeout(120, TimeUnit.SECONDS) + elementRobot.onboarding { + crawl() + } + // Create an account val userId = "UiTest_" + UUID.randomUUID().toString() elementRobot.signUp(userId) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt index 22a5a0790b..638cf9840e 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt @@ -40,6 +40,10 @@ import timber.log.Timber class ElementRobot { + fun onboarding(block: OnboardingRobot.() -> Unit) { + block(OnboardingRobot()) + } + fun signUp(userId: String) { val onboardingRobot = OnboardingRobot() onboardingRobot.createAccount(userId = userId) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt index 633d3cceab..57693709c6 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt @@ -18,6 +18,7 @@ package im.vector.app.ui.robot import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withId import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertDisabled @@ -31,6 +32,24 @@ import im.vector.app.waitForView class OnboardingRobot { + fun crawl() { + waitUntilViewVisible(withId(R.id.loginSplashSubmit)) + crawlGetStarted() + crawlAlreadyHaveAccount() + } + + private fun crawlGetStarted() { + clickOn(R.id.loginSplashSubmit) + AuthOptionsRobot().crawlGetStarted() + pressBack() + } + + private fun crawlAlreadyHaveAccount() { + clickOn(R.id.loginSplashAlreadyHaveAccount) + AuthOptionsRobot().crawlAlreadyHaveAccount() + pressBack() + } + fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") { initSession(true, userId, password, homeServerUrl) } @@ -73,3 +92,76 @@ class OnboardingRobot { clickOn(R.id.loginSubmit) } } + +class AuthOptionsRobot { + + fun crawlGetStarted() { + assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + crawlMatrixServer(isSignUp = true) + crawlEmsServer() + crawlOtherServer(isSignUp = true) + crawlSignInWithMatrixId() + } + + fun crawlAlreadyHaveAccount() { + assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + crawlMatrixServer(isSignUp = false) + crawlEmsServer() + crawlOtherServer(isSignUp = false) + crawlSignInWithMatrixId() + } + + private fun crawlOtherServer(isSignUp: Boolean) { + clickOn(R.id.loginServerChoiceOther) + waitUntilViewVisible(withId(R.id.loginServerUrlFormTitle)) + writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://chat.mozilla.org") + clickOn(R.id.loginServerUrlFormSubmit) + waitUntilViewVisible(withId(R.id.loginSignupSigninTitle)) + assertDisplayed(R.id.loginSignupSigninText, "Connect to chat.mozilla.org") + assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + pressBack() + + writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://matrix.org") + clickOn(R.id.loginServerUrlFormSubmit) + assetMatrixSignInOptions(isSignUp) + pressBack() + pressBack() + } + + private fun crawlEmsServer() { + clickOn(R.id.loginServerChoiceEms) + waitUntilViewVisible(withId(R.id.loginServerUrlFormTitle)) + assertDisplayed(R.id.loginServerUrlFormTitle, R.string.login_connect_to_modular) + + writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://one.ems.host") + clickOn(R.id.loginServerUrlFormSubmit) + + waitUntilViewVisible(withId(R.id.loginSignupSigninTitle)) + assertDisplayed(R.id.loginSignupSigninText, "one.ems.host") + assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + pressBack() + pressBack() + } + + private fun crawlMatrixServer(isSignUp: Boolean) { + clickOn(R.id.loginServerChoiceMatrixOrg) + assetMatrixSignInOptions(isSignUp) + pressBack() + } + + private fun assetMatrixSignInOptions(isSignUp: Boolean) { + waitUntilViewVisible(withId(R.id.loginTitle)) + when (isSignUp) { + true -> assertDisplayed(R.id.loginTitle, "Sign up to matrix.org") + false -> assertDisplayed(R.id.loginTitle, "Connect to matrix.org") + } + } + + private fun crawlSignInWithMatrixId() { + clickOn(R.id.loginServerIKnowMyIdSubmit) + waitUntilViewVisible(withId(R.id.loginTitle)) + assertDisplayed(R.id.loginTitle, R.string.login_signin_matrix_id_title) + pressBack() + } +} + From 37c4d941090932a74d84229dafe2b36f0bcb1442 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 12:48:17 +0000 Subject: [PATCH 068/222] adding changelog entry --- changelog.d/4975.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4975.misc diff --git a/changelog.d/4975.misc b/changelog.d/4975.misc new file mode 100644 index 0000000000..12d1fc163f --- /dev/null +++ b/changelog.d/4975.misc @@ -0,0 +1 @@ +Including onboarding server options in the all screen sanity test suite \ No newline at end of file From 030d9ef351092e644672680dd6f1280073469853 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 12:50:00 +0000 Subject: [PATCH 069/222] extracting inner class to its own file and updating function names relative to their usage --- .../im/vector/app/ui/robot/OnboardingRobot.kt | 77 +-------------- .../app/ui/robot/OnboardingServersRobot.kt | 97 +++++++++++++++++++ 2 files changed, 99 insertions(+), 75 deletions(-) create mode 100644 vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt index 57693709c6..62d446fe84 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt @@ -40,13 +40,13 @@ class OnboardingRobot { private fun crawlGetStarted() { clickOn(R.id.loginSplashSubmit) - AuthOptionsRobot().crawlGetStarted() + OnboardingServersRobot().crawlSignUp() pressBack() } private fun crawlAlreadyHaveAccount() { clickOn(R.id.loginSplashAlreadyHaveAccount) - AuthOptionsRobot().crawlAlreadyHaveAccount() + OnboardingServersRobot().crawlSignIn() pressBack() } @@ -92,76 +92,3 @@ class OnboardingRobot { clickOn(R.id.loginSubmit) } } - -class AuthOptionsRobot { - - fun crawlGetStarted() { - assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) - crawlMatrixServer(isSignUp = true) - crawlEmsServer() - crawlOtherServer(isSignUp = true) - crawlSignInWithMatrixId() - } - - fun crawlAlreadyHaveAccount() { - assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) - crawlMatrixServer(isSignUp = false) - crawlEmsServer() - crawlOtherServer(isSignUp = false) - crawlSignInWithMatrixId() - } - - private fun crawlOtherServer(isSignUp: Boolean) { - clickOn(R.id.loginServerChoiceOther) - waitUntilViewVisible(withId(R.id.loginServerUrlFormTitle)) - writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://chat.mozilla.org") - clickOn(R.id.loginServerUrlFormSubmit) - waitUntilViewVisible(withId(R.id.loginSignupSigninTitle)) - assertDisplayed(R.id.loginSignupSigninText, "Connect to chat.mozilla.org") - assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) - pressBack() - - writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://matrix.org") - clickOn(R.id.loginServerUrlFormSubmit) - assetMatrixSignInOptions(isSignUp) - pressBack() - pressBack() - } - - private fun crawlEmsServer() { - clickOn(R.id.loginServerChoiceEms) - waitUntilViewVisible(withId(R.id.loginServerUrlFormTitle)) - assertDisplayed(R.id.loginServerUrlFormTitle, R.string.login_connect_to_modular) - - writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://one.ems.host") - clickOn(R.id.loginServerUrlFormSubmit) - - waitUntilViewVisible(withId(R.id.loginSignupSigninTitle)) - assertDisplayed(R.id.loginSignupSigninText, "one.ems.host") - assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) - pressBack() - pressBack() - } - - private fun crawlMatrixServer(isSignUp: Boolean) { - clickOn(R.id.loginServerChoiceMatrixOrg) - assetMatrixSignInOptions(isSignUp) - pressBack() - } - - private fun assetMatrixSignInOptions(isSignUp: Boolean) { - waitUntilViewVisible(withId(R.id.loginTitle)) - when (isSignUp) { - true -> assertDisplayed(R.id.loginTitle, "Sign up to matrix.org") - false -> assertDisplayed(R.id.loginTitle, "Connect to matrix.org") - } - } - - private fun crawlSignInWithMatrixId() { - clickOn(R.id.loginServerIKnowMyIdSubmit) - waitUntilViewVisible(withId(R.id.loginTitle)) - assertDisplayed(R.id.loginTitle, R.string.login_signin_matrix_id_title) - pressBack() - } -} - diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt new file mode 100644 index 0000000000..1625b4580d --- /dev/null +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingServersRobot.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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.ui.robot + +import androidx.test.espresso.Espresso +import androidx.test.espresso.matcher.ViewMatchers +import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions +import com.adevinta.android.barista.interaction.BaristaClickInteractions +import com.adevinta.android.barista.interaction.BaristaEditTextInteractions +import im.vector.app.R +import im.vector.app.espresso.tools.waitUntilViewVisible + +class OnboardingServersRobot { + + fun crawlSignUp() { + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + crawlMatrixServer(isSignUp = true) + crawlEmsServer() + crawlOtherServer(isSignUp = true) + crawlSignInWithMatrixId() + } + + fun crawlSignIn() { + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerTitle, R.string.login_server_title) + crawlMatrixServer(isSignUp = false) + crawlEmsServer() + crawlOtherServer(isSignUp = false) + crawlSignInWithMatrixId() + } + + private fun crawlOtherServer(isSignUp: Boolean) { + BaristaClickInteractions.clickOn(R.id.loginServerChoiceOther) + waitUntilViewVisible(ViewMatchers.withId(R.id.loginServerUrlFormTitle)) + BaristaEditTextInteractions.writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://chat.mozilla.org") + BaristaClickInteractions.clickOn(R.id.loginServerUrlFormSubmit) + waitUntilViewVisible(ViewMatchers.withId(R.id.loginSignupSigninTitle)) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninText, "Connect to chat.mozilla.org") + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + Espresso.pressBack() + + BaristaEditTextInteractions.writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://matrix.org") + BaristaClickInteractions.clickOn(R.id.loginServerUrlFormSubmit) + assetMatrixSignInOptions(isSignUp) + Espresso.pressBack() + Espresso.pressBack() + } + + private fun crawlEmsServer() { + BaristaClickInteractions.clickOn(R.id.loginServerChoiceEms) + waitUntilViewVisible(ViewMatchers.withId(R.id.loginServerUrlFormTitle)) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginServerUrlFormTitle, R.string.login_connect_to_modular) + + BaristaEditTextInteractions.writeTo(R.id.loginServerUrlFormHomeServerUrl, "https://one.ems.host") + BaristaClickInteractions.clickOn(R.id.loginServerUrlFormSubmit) + + waitUntilViewVisible(ViewMatchers.withId(R.id.loginSignupSigninTitle)) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninText, "one.ems.host") + BaristaVisibilityAssertions.assertDisplayed(R.id.loginSignupSigninSubmit, R.string.login_signin_sso) + Espresso.pressBack() + Espresso.pressBack() + } + + private fun crawlMatrixServer(isSignUp: Boolean) { + BaristaClickInteractions.clickOn(R.id.loginServerChoiceMatrixOrg) + assetMatrixSignInOptions(isSignUp) + Espresso.pressBack() + } + + private fun assetMatrixSignInOptions(isSignUp: Boolean) { + waitUntilViewVisible(ViewMatchers.withId(R.id.loginTitle)) + when (isSignUp) { + true -> BaristaVisibilityAssertions.assertDisplayed(R.id.loginTitle, "Sign up to matrix.org") + false -> BaristaVisibilityAssertions.assertDisplayed(R.id.loginTitle, "Connect to matrix.org") + } + } + + private fun crawlSignInWithMatrixId() { + BaristaClickInteractions.clickOn(R.id.loginServerIKnowMyIdSubmit) + waitUntilViewVisible(ViewMatchers.withId(R.id.loginTitle)) + BaristaVisibilityAssertions.assertDisplayed(R.id.loginTitle, R.string.login_signin_matrix_id_title) + Espresso.pressBack() + } +} From 70a95fc373f21ca4d0229b63262aadc4c01fb730 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 16:21:37 +0000 Subject: [PATCH 070/222] removing unused import --- .../androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt index a5cd0badb3..ebf5fdf23d 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt @@ -37,7 +37,6 @@ import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBot import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet import im.vector.app.features.reactions.data.EmojiDataSource import im.vector.app.interactWithSheet -import im.vector.app.waitForView import im.vector.app.withRetry import java.lang.Thread.sleep From 8d37dc5118a887e293cc760a61dda25b7d85a090 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 23:08:02 +0000 Subject: [PATCH 071/222] Bump json from 20190722 to 20211205 Bumps [json](https://github.com/douglascrockford/JSON-java) from 20190722 to 20211205. - [Release notes](https://github.com/douglascrockford/JSON-java/releases) - [Changelog](https://github.com/stleary/JSON-java/blob/master/docs/RELEASES.md) - [Commits](https://github.com/douglascrockford/JSON-java/commits) --- updated-dependencies: - dependency-name: org.json:json dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- library/jsonviewer/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/jsonviewer/build.gradle b/library/jsonviewer/build.gradle index 223cb18acc..15f46754b3 100644 --- a/library/jsonviewer/build.gradle +++ b/library/jsonviewer/build.gradle @@ -59,7 +59,7 @@ dependencies { implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid - testImplementation 'org.json:json:20190722' + testImplementation 'org.json:json:20211205' testImplementation libs.tests.junit androidTestImplementation libs.androidx.junit androidTestImplementation libs.androidx.espressoCore From 1e99e12857eb26f019ae195bdb906c84e10962f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 23:08:13 +0000 Subject: [PATCH 072/222] Bump realm-gradle-plugin from 10.9.0 to 10.10.0 Bumps [realm-gradle-plugin](https://github.com/realm/realm-java) from 10.9.0 to 10.10.0. - [Release notes](https://github.com/realm/realm-java/releases) - [Changelog](https://github.com/realm/realm-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/realm/realm-java/compare/v10.9.0...v10.10.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] --- 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 7b9a611c72..19b602eb39 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -9,7 +9,7 @@ buildscript { mavenCentral() } dependencies { - classpath "io.realm:realm-gradle-plugin:10.9.0" + classpath "io.realm:realm-gradle-plugin:10.10.0" } } From 381dd5343ac124cde3bd0a24c69f088ece5a01e0 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 19 Jan 2022 13:00:21 +0300 Subject: [PATCH 073/222] Show edit action for poll messages if it is not voted and closed. --- .../timeline/action/MessageActionsViewModel.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index ff7d555ee3..3cecb59675 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -466,14 +466,15 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted } private fun canEdit(event: TimelineEvent, myUserId: String, actionPermissions: ActionPermissions): Boolean { - // Only event of type EventType.MESSAGE are supported for the moment - if (event.root.getClearType() != EventType.MESSAGE) return false + // Only event of type EventType.MESSAGE and EventType.POLL_START are supported for the moment + if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.POLL_START)) return false if (!actionPermissions.canSendMessage) return false // TODO if user is admin or moderator val messageContent = event.root.getClearContent().toModel() return event.root.senderId == myUserId && ( messageContent?.msgType == MessageType.MSGTYPE_TEXT || - messageContent?.msgType == MessageType.MSGTYPE_EMOTE + messageContent?.msgType == MessageType.MSGTYPE_EMOTE || + canEditPoll(event) ) } @@ -516,4 +517,10 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted canRedact(event, actionPermissions) && event.annotations?.pollResponseSummary?.closedTime == null } + + private fun canEditPoll(event: TimelineEvent): Boolean { + return event.root.getClearType() == EventType.POLL_START && + event.annotations?.pollResponseSummary?.closedTime == null && + event.annotations?.pollResponseSummary?.aggregatedContent?.totalVotes ?: 0 == 0 + } } From 00f2947636cec91629e4cbf500731a3ef6c38e35 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 17 Jan 2022 17:20:41 +0000 Subject: [PATCH 074/222] enabling the splash carousel feature by default --- changelog.d/4584.feature | 1 + vector/src/main/java/im/vector/app/features/VectorFeatures.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/4584.feature diff --git a/changelog.d/4584.feature b/changelog.d/4584.feature new file mode 100644 index 0000000000..6c0de3b34f --- /dev/null +++ b/changelog.d/4584.feature @@ -0,0 +1 @@ +Enables the FTUE splash carousel \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index 25c204f2ef..03e9954b2c 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -35,6 +35,6 @@ interface VectorFeatures { class DefaultVectorFeatures : VectorFeatures { override fun onboardingVariant(): VectorFeatures.OnboardingVariant = BuildConfig.ONBOARDING_VARIANT override fun isOnboardingAlreadyHaveAccountSplashEnabled() = true - override fun isOnboardingSplashCarouselEnabled() = false + override fun isOnboardingSplashCarouselEnabled() = true override fun isOnboardingUseCaseEnabled() = false } From 36a26fcfd0625d6fceaf110d336fe48b2e95d84a Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 17 Jan 2022 17:32:15 +0000 Subject: [PATCH 075/222] replacing the dark carousel background with a solid colour as par design changes --- .../src/main/res/drawable/bg_carousel_page_dark.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/ui-styles/src/main/res/drawable/bg_carousel_page_dark.xml b/library/ui-styles/src/main/res/drawable/bg_carousel_page_dark.xml index f229c51d1b..2542ff2b1d 100644 --- a/library/ui-styles/src/main/res/drawable/bg_carousel_page_dark.xml +++ b/library/ui-styles/src/main/res/drawable/bg_carousel_page_dark.xml @@ -1,7 +1,4 @@ - + \ No newline at end of file From 8f98f3e6d08a1011f76f788faf36c5cd8eed8b21 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 18 Jan 2022 16:36:01 +0000 Subject: [PATCH 076/222] promoting wip carousel strings --- vector/src/main/res/values/donottranslate.xml | 7 ------- vector/src/main/res/values/strings.xml | 9 ++++++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vector/src/main/res/values/donottranslate.xml b/vector/src/main/res/values/donottranslate.xml index ab50d7e7c3..af2319883c 100755 --- a/vector/src/main/res/values/donottranslate.xml +++ b/vector/src/main/res/values/donottranslate.xml @@ -18,13 +18,6 @@ Cut the slack from teams. - Secure and independent communication that gives you the same level of privacy as a face-to-face conversation in your own home. - Choose where your conversations are kept, giving you control and independence. Connected via Matrix. - End-to-end encrypted and no phone number required. No ads or datamining. - Messaging for your team. - - ${app_name} is also great for the workplace. It’s trusted by the world’s most secure organisations. - Who will you chat to the most? We\'ll help you get connected. Friends and family diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 27bab7d66f..5480f7f433 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2526,13 +2526,20 @@ You\'re in control. Element lets you choose where your messages are stored, keeping you in control of your data. - Secure Messaging. + Secure messaging. No phone number required, so you don\'t have to share those details with the outside world. No ads, no datamining. Cut the slack from teams. As universal as email, Element is a completely new type of collaboration. + Secure and independent communication that gives you the same level of privacy as a face-to-face conversation in your own home. + Choose where your conversations are kept, giving you control and independence. Connected via Matrix. + End-to-end encrypted and no phone number required. No ads or datamining. + Messaging for your team. + + ${app_name} is also great for the workplace. It’s trusted by the world’s most secure organisations. + It\'s your conversation. Own it. Chat with people directly or in groups Keep conversations private with encryption From 211f1840669ffd92997d3fbec1662a4da02220be Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 19 Jan 2022 09:49:17 +0000 Subject: [PATCH 077/222] updating splash submit copy to use Create account when the I already have an account feature is enabled --- .../java/im/vector/app/ui/robot/OnboardingRobot.kt | 2 +- .../ftueauth/FtueAuthSplashCarouselFragment.kt | 12 ++++++++---- .../onboarding/ftueauth/FtueAuthSplashFragment.kt | 10 +++++++--- .../main/res/layout/fragment_ftue_auth_splash.xml | 1 - .../res/layout/fragment_ftue_splash_carousel.xml | 1 - vector/src/main/res/values/strings.xml | 1 + 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt index 62d446fe84..47bf31355c 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt @@ -63,7 +63,7 @@ class OnboardingRobot { password: String, homeServerUrl: String) { waitUntilViewVisible(withId(R.id.loginSplashSubmit)) - assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_submit) + assertDisplayed(R.id.loginSplashSubmit, R.string.login_splash_create_account) if (createAccount) { clickOn(R.id.loginSplashSubmit) } else { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt index 038e020cf6..49e8875cb5 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt @@ -68,9 +68,13 @@ class FtueAuthSplashCarouselFragment @Inject constructor( TabLayoutMediator(views.carouselIndicator, views.splashCarousel) { _, _ -> }.attach() carouselController.setData(carouselStateFactory.create()) - views.loginSplashSubmit.debouncedClicks { getStarted() } + val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() + views.loginSplashSubmit.apply { + setText(if (isAlreadyHaveAccountEnabled) R.string.login_splash_create_account else R.string.login_splash_submit) + debouncedClicks { splashSubmit(isAlreadyHaveAccountEnabled) } + } views.loginSplashAlreadyHaveAccount.apply { - isVisible = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() + isVisible = isAlreadyHaveAccountEnabled debouncedClicks { alreadyHaveAnAccount() } } @@ -111,8 +115,8 @@ class FtueAuthSplashCarouselFragment @Inject constructor( } } - private fun getStarted() { - val getStartedFlow = if (vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled()) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp + private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { + val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = false, onboardingFlow = getStartedFlow)) } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt index fd63889fd6..031579db5f 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt @@ -53,7 +53,11 @@ class FtueAuthSplashFragment @Inject constructor( } private fun setupViews() { - views.loginSplashSubmit.debouncedClicks { getStarted() } + val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() + views.loginSplashSubmit.apply { + setText(if (isAlreadyHaveAccountEnabled) R.string.login_splash_create_account else R.string.login_splash_submit) + debouncedClicks { splashSubmit(isAlreadyHaveAccountEnabled) } + } views.loginSplashAlreadyHaveAccount.apply { isVisible = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() debouncedClicks { alreadyHaveAnAccount() } @@ -69,8 +73,8 @@ class FtueAuthSplashFragment @Inject constructor( } } - private fun getStarted() { - val getStartedFlow = if (vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled()) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp + private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { + val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = false, onboardingFlow = getStartedFlow)) } diff --git a/vector/src/main/res/layout/fragment_ftue_auth_splash.xml b/vector/src/main/res/layout/fragment_ftue_auth_splash.xml index 803ad700db..afe086f484 100644 --- a/vector/src/main/res/layout/fragment_ftue_auth_splash.xml +++ b/vector/src/main/res/layout/fragment_ftue_auth_splash.xml @@ -182,7 +182,6 @@ style="@style/Widget.Vector.Button.Login" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="@string/login_splash_submit" android:textAllCaps="true" android:transitionName="loginSubmitTransition" app:layout_constraintBottom_toTopOf="@id/loginSplashSpace5" diff --git a/vector/src/main/res/layout/fragment_ftue_splash_carousel.xml b/vector/src/main/res/layout/fragment_ftue_splash_carousel.xml index facef377d4..c049ec81d9 100644 --- a/vector/src/main/res/layout/fragment_ftue_splash_carousel.xml +++ b/vector/src/main/res/layout/fragment_ftue_splash_carousel.xml @@ -61,7 +61,6 @@ style="@style/Widget.Vector.Button.Login" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="@string/login_splash_submit" android:textAllCaps="true" android:transitionName="loginSubmitTransition" app:layout_constraintBottom_toTopOf="@id/loginSplashAlreadyHaveAccount" diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 5480f7f433..110d1e651b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2545,6 +2545,7 @@ Keep conversations private with encryption Extend & customise your experience Get started + Create account I already have an account Select a server From 8d0299e411e38d65cc56de180762116fb5176633 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Wed, 19 Jan 2022 12:46:22 +0200 Subject: [PATCH 078/222] Ignore dependabot upgrade for @github-script@v3 --- .github/dependabot.yml | 3 +++ changelog.d/4988.misc | 1 + 2 files changed, 4 insertions(+) create mode 100644 changelog.d/4988.misc diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8c2f1041e0..53cfc4e389 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,9 @@ updates: directory: "/" schedule: interval: "weekly" + ignore: + - dependency-name: "github-script" + versions: ["3.x"] # Updates for Gradle dependencies used in the app - package-ecosystem: gradle directory: "/" diff --git a/changelog.d/4988.misc b/changelog.d/4988.misc new file mode 100644 index 0000000000..9fbeb781d5 --- /dev/null +++ b/changelog.d/4988.misc @@ -0,0 +1 @@ +Exclude dependabot upgrade for @github-script@v3 From 3c7f2c5bdfa8b2cf69531f6946ab8b33de7bd9d3 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 19 Jan 2022 11:18:54 +0000 Subject: [PATCH 079/222] adding tools:text for dynamically set text --- vector/src/main/res/layout/fragment_ftue_auth_splash.xml | 3 ++- vector/src/main/res/layout/fragment_ftue_splash_carousel.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/layout/fragment_ftue_auth_splash.xml b/vector/src/main/res/layout/fragment_ftue_auth_splash.xml index afe086f484..ef3d015bdb 100644 --- a/vector/src/main/res/layout/fragment_ftue_auth_splash.xml +++ b/vector/src/main/res/layout/fragment_ftue_auth_splash.xml @@ -187,7 +187,8 @@ app:layout_constraintBottom_toTopOf="@id/loginSplashSpace5" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/loginSplashSpace4" /> + app:layout_constraintTop_toBottomOf="@id/loginSplashSpace4" + tools:text="@string/login_splash_create_account" />