From 4f8fd7b994d5811ecf00ea52ed87248335e958a6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 14 Aug 2020 15:40:02 +0200 Subject: [PATCH] Benoit's review - Cleanup - Force refresh of HomeServerCapabilities - add some doc - remove dead code - remove commented code - remove duplicated comment - use getBestName() - improve code formatting - Fix isAudioOnly parameter in jitsi url - Fix layout issue between "Active conference" banner and "Jump to first unread message banner" - Improve "Active conference" banner - Remove Calendar permission from Manifest --- CHANGES.md | 2 +- matrix-sdk-android/build.gradle | 2 +- .../android/sdk/api/auth/data/WellKnown.kt | 10 ++- .../homeserver/HomeServerCapabilities.kt | 4 +- .../database/RealmSessionStoreMigration.kt | 10 ++- vector/src/main/AndroidManifest.xml | 8 +++ .../app/core/ui/list/GenericButtonItem.kt | 4 +- .../app/core/ui/views/ActiveConferenceView.kt | 2 +- .../call/conference/JitsiCallViewActions.kt | 21 ++++++ .../call/conference/JitsiCallViewEvents.kt | 21 ++++++ .../call/conference/JitsiCallViewModel.kt | 20 ++---- .../call/conference/VectorJitsiActivity.kt | 2 +- .../home/room/detail/RoomDetailAction.kt | 5 +- .../home/room/detail/RoomDetailFragment.kt | 72 +++++++++---------- .../home/room/detail/RoomDetailViewEvents.kt | 4 +- .../home/room/detail/RoomDetailViewModel.kt | 21 +++--- .../detail/widget/RoomWidgetsBottomSheet.kt | 4 +- ...Controller.kt => RoomWidgetsController.kt} | 17 +++-- .../settings/devices/DevicesController.kt | 2 +- .../RoomWidgetPermissionBottomSheet.kt | 6 +- .../main/res/layout/fragment_room_detail.xml | 22 +++--- .../src/main/res/layout/item_room_widget.xml | 36 +++++----- .../main/res/layout/view_active_call_view.xml | 4 +- .../layout/view_active_conference_view.xml | 6 +- vector/src/main/res/values/strings.xml | 2 +- 25 files changed, 174 insertions(+), 133 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewActions.kt create mode 100644 vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewEvents.kt rename vector/src/main/java/im/vector/app/features/home/room/detail/widget/{RoomWidgetController.kt => RoomWidgetsController.kt} (79%) diff --git a/CHANGES.md b/CHANGES.md index 752f6489f2..77d5077ee5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,7 @@ Changes in Element 1.0.5 (2020-XX-XX) Features ✨: - Protect access to the app by a pin code (#1700) - - Conference with Jitsi support (#43) + - Conference with Jitsi support (#43) Improvements 🙌: - Give user the possibility to prevent accidental call (#1869) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 57a9dfaa87..7991ecbc7b 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -137,7 +137,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.8.1")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:logging-interceptor' - implementation("com.squareup.okhttp3:okhttp-urlconnection") + implementation 'com.squareup.okhttp3:okhttp-urlconnection' implementation "com.squareup.moshi:moshi-adapters:$moshi_version" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt index b59fbacdf4..b10cae6171 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/WellKnown.kt @@ -74,9 +74,7 @@ data class E2EWellKnownConfig( ) @JsonClass(generateAdapter = true) -class WellKnownPreferredConfig { - - @JvmField - @Json(name = "preferredDomain") - var preferredDomain: String? = null -} +data class WellKnownPreferredConfig( + @Json(name = "preferredDomain") + val preferredDomain: String? = null +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 99e02361c1..de7ac45bf3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -39,7 +39,9 @@ data class HomeServerCapabilities( * (as it was before) for various environments where this is desired. */ val adminE2EByDefault: Boolean = true, - + /** + * Preferred Jitsi domain, provided in Wellknown + */ val preferredJitsiDomain: String? = null ) { companion object { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index 88be8dda50..7d2a4ea581 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -17,10 +17,10 @@ package org.matrix.android.sdk.internal.database -import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields -import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import io.realm.DynamicRealm import io.realm.RealmMigration +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import timber.log.Timber import javax.inject.Inject @@ -55,8 +55,12 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration { } private fun migrateTo3(realm: DynamicRealm) { - Timber.d("Step 1 -> 2") + Timber.d("Step 2 -> 3") realm.schema.get("HomeServerCapabilitiesEntity") ?.addField(HomeServerCapabilitiesEntityFields.PREFERRED_JITSI_DOMAIN, String::class.java) + ?.transform { obj -> + // Schedule a refresh of the capabilities + obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0) + } } } diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 95baf304d0..c962098143 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -28,6 +28,14 @@ + + + + () var text: String? = null @EpoxyAttribute - var itemClickAction: View.OnClickListener? = null + var buttonClickAction: View.OnClickListener? = null @EpoxyAttribute @ColorInt @@ -57,7 +57,7 @@ abstract class GenericButtonItem : VectorEpoxyModel() holder.button.icon = null } - itemClickAction?.let { holder.button.setOnClickListener(it) } + buttonClickAction?.let { holder.button.setOnClickListener(it) } } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt index 08b182d4d8..240ad61c40 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt @@ -92,7 +92,7 @@ class ActiveConferenceView @JvmOverloads constructor( val summary = state.asyncRoomSummary() if (summary?.membership == Membership.JOIN) { // We only display banner for 'live' widgets - val activeConf = // for now only jitsi? + val activeConf = state.activeRoomWidgets()?.firstOrNull { // for now only jitsi? it.type == WidgetType.Jitsi diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewActions.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewActions.kt new file mode 100644 index 0000000000..6554e50d63 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewActions.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 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.call.conference + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class JitsiCallViewActions : VectorViewModelAction diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewEvents.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewEvents.kt new file mode 100644 index 0000000000..319322daba --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewEvents.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 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.call.conference + +import im.vector.app.core.platform.VectorViewEvents + +sealed class JitsiCallViewEvents : VectorViewEvents diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt index 49e888d68e..cf4d1417e3 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt @@ -23,11 +23,8 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject -import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewModel -import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.resources.StringProvider -import im.vector.app.features.call.WebRtcPeerConnectionManager import org.jitsi.meet.sdk.JitsiMeetUserInfo import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session @@ -36,16 +33,11 @@ import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.rx.asObservable import java.net.URL -sealed class JitsiCallViewActions : VectorViewModelAction - -sealed class JitsiCallViewEvents : VectorViewEvents - class JitsiCallViewModel @AssistedInject constructor( @Assisted initialState: JitsiCallViewState, @Assisted val args: VectorJitsiActivity.Args, - val session: Session, - val webRtcPeerConnectionManager: WebRtcPeerConnectionManager, - val stringProvider: StringProvider + private val session: Session, + private val stringProvider: StringProvider ) : VectorViewModel(initialState) { @AssistedInject.Factory @@ -56,7 +48,7 @@ class JitsiCallViewModel @AssistedInject constructor( init { val me = session.getUser(session.myUserId)?.toMatrixItem() val userInfo = JitsiMeetUserInfo().apply { - displayName = me?.displayName + displayName = me?.getBestName() avatar = me?.avatarUrl?.let { session.contentUrlResolver().resolveFullSize(it) }?.let { URL(it) } } val roomName = session.getRoomSummary(args.roomId)?.displayName @@ -73,7 +65,7 @@ class JitsiCallViewModel @AssistedInject constructor( if (jitsiWidget != null) { val uri = Uri.parse(jitsiWidget.computedUrl) val confId = uri.getQueryParameter("confId") - val ppt = jitsiWidget.computedUrl?.let { JitsiWidgetProperties(it, stringProvider) } + val ppt = jitsiWidget.computedUrl?.let { url -> JitsiWidgetProperties(url, stringProvider) } setState { copy( widget = Success(jitsiWidget), @@ -89,7 +81,8 @@ class JitsiCallViewModel @AssistedInject constructor( ) } } - }.disposeOnClear() + } + .disposeOnClear() } override fun handle(action: JitsiCallViewActions) { @@ -108,7 +101,6 @@ class JitsiCallViewModel @AssistedInject constructor( override fun initialState(viewModelContext: ViewModelContext): JitsiCallViewState? { val args: VectorJitsiActivity.Args = viewModelContext.args() -// val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() return JitsiCallViewState( roomId = args.roomId, diff --git a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt index 8695a746d0..e26cb23ac7 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt @@ -55,7 +55,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMeetActivityInterface, Ji @Inject lateinit var viewModelFactory: JitsiCallViewModel.Factory - var jitsiMeetView: JitsiMeetView? = null + private var jitsiMeetView: JitsiMeetView? = null private val jitsiViewModel: JitsiCallViewModel by viewModel() 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 5f3488437f..5930be4f1b 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 @@ -82,7 +82,8 @@ sealed class RoomDetailAction : VectorViewModelAction { object SelectStickerAttachment : RoomDetailAction() object OpenIntegrationManager: RoomDetailAction() object ManageIntegrations: RoomDetailAction() - data class AddJitsiWidget(val video: Boolean): RoomDetailAction() + data class AddJitsiWidget(val withVideo: Boolean): RoomDetailAction() data class RemoveWidget(val widgetId: String): RoomDetailAction() - data class EnsureNativeWidgetAllowed(val widget: Widget, val grantedEvents: RoomDetailViewEvents) : RoomDetailAction() + data class EnsureNativeWidgetAllowed(val widget: Widget, + val grantedEvents: RoomDetailViewEvents) : 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 eea22d0a97..a6ce63dfab 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 @@ -154,6 +154,14 @@ import im.vector.app.features.widgets.WidgetActivity import im.vector.app.features.widgets.WidgetArgs import im.vector.app.features.widgets.WidgetKind import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import kotlinx.android.parcel.Parcelize +import kotlinx.android.synthetic.main.fragment_room_detail.* +import kotlinx.android.synthetic.main.merge_composer_layout.view.* +import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* +import org.billcarsonfr.jsonviewer.JSonViewerDialog +import org.commonmark.parser.Parser import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.permalinks.PermalinkFactory import org.matrix.android.sdk.api.session.Session @@ -176,21 +184,13 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent +import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.session.widgets.model.WidgetType import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers -import kotlinx.android.parcel.Parcelize -import kotlinx.android.synthetic.main.fragment_room_detail.* -import kotlinx.android.synthetic.main.merge_composer_layout.view.* -import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* -import org.billcarsonfr.jsonviewer.JSonViewerDialog -import org.commonmark.parser.Parser -import org.matrix.android.sdk.api.session.widgets.model.Widget import timber.log.Timber import java.io.File import java.net.URL @@ -370,24 +370,24 @@ class RoomDetailFragment @Inject constructor( private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) { val tag = RoomWidgetPermissionBottomSheet::class.java.name - val dFrag = childFragmentManager - .findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet + val dFrag = childFragmentManager.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet if (dFrag != null && dFrag.dialog?.isShowing == true && !dFrag.isRemoving) { return } else { - RoomWidgetPermissionBottomSheet - .newInstance(WidgetArgs( + RoomWidgetPermissionBottomSheet.newInstance( + WidgetArgs( baseUrl = it.domain, kind = WidgetKind.ROOM, roomId = roomDetailArgs.roomId, widgetId = it.widget.widgetId - )).apply { - directListener = { granted -> - if (granted) { - roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(it.widget, it.grantedEvents)) - } - } + ) + ).apply { + directListener = { granted -> + if (granted) { + roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(it.widget, it.grantedEvents)) } + } + } .show(childFragmentManager, tag) } } @@ -592,7 +592,8 @@ class RoomDetailFragment @Inject constructor( override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) - menu.findItem(R.id.open_matrix_apps).let { menuItem -> + // We use a custom layout for this menu item, so we need to set a ClickListener + menu.findItem(R.id.open_matrix_apps)?.let { menuItem -> menuItem.actionView.setOnClickListener { onOptionsItemSelected(menuItem) } @@ -604,24 +605,23 @@ class RoomDetailFragment @Inject constructor( it.isVisible = roomDetailViewModel.isMenuItemVisible(it.itemId) } withState(roomDetailViewModel) { state -> - val findItem = menu.findItem(R.id.open_matrix_apps) - val widgetsCount = state.activeRoomWidgets.invoke()?.size - if (widgetsCount ?: 0 > 0) { - val actionView = findItem.actionView + val matrixAppsMenuItem = menu.findItem(R.id.open_matrix_apps) + val widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0 + if (widgetsCount > 0) { + val actionView = matrixAppsMenuItem.actionView actionView .findViewById(R.id.action_view_icon_image) .setColorFilter(ContextCompat.getColor(requireContext(), R.color.riotx_accent)) - actionView.findViewById(R.id.cart_badge).isVisible = true - actionView.findViewById(R.id.cart_badge).text = "$widgetsCount" - findItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) + actionView.findViewById(R.id.cart_badge).setTextOrHide("$widgetsCount") + matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) } else { // icon should be default color no badge - val actionView = findItem.actionView + val actionView = matrixAppsMenuItem.actionView actionView .findViewById(R.id.action_view_icon_image) .setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.riotx_text_secondary)) actionView.findViewById(R.id.cart_badge).isVisible = false - findItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) + matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER) } } } @@ -646,6 +646,7 @@ class RoomDetailFragment @Inject constructor( R.id.voice_call, R.id.video_call -> { handleCallRequest(item) + true } R.id.hangup_call -> { roomDetailViewModel.handle(RoomDetailAction.EndCall) @@ -655,10 +656,10 @@ class RoomDetailFragment @Inject constructor( } } - private fun handleCallRequest(item: MenuItem): Boolean = withState(roomDetailViewModel) { state -> - val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState true + private fun handleCallRequest(item: MenuItem) = withState(roomDetailViewModel) { state -> + val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState val isVideoCall = item.itemId == R.id.video_call - return@withState when (roomSummary.joinedMembersCount) { + when (roomSummary.joinedMembersCount) { 1 -> { val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0 if (pendingInvite) { @@ -668,7 +669,6 @@ class RoomDetailFragment @Inject constructor( // You cannot place a call with yourself. showDialogWithMessage(getString(R.string.cannot_call_yourself)) } - true } 2 -> { val activeCall = sharedCallActionViewModel.activeCall.value @@ -685,7 +685,6 @@ class RoomDetailFragment @Inject constructor( } else { safeStartCall(isVideoCall) } - true } else -> { // it's jitsi call @@ -709,7 +708,6 @@ class RoomDetailFragment @Inject constructor( .show() } } - true } } } @@ -1725,10 +1723,6 @@ class RoomDetailFragment @Inject constructor( .show() } -// private fun joinCurrentJitsiCall(withVideo: Boolean) { -// -// } - // VectorInviteView.Callback override fun onAcceptInvite() { 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 45f036a066..29ed43f17d 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 @@ -72,7 +72,9 @@ sealed class RoomDetailViewEvents : VectorViewEvents { object OpenIntegrationManager: RoomDetailViewEvents() object OpenActiveWidgetBottomSheet: RoomDetailViewEvents() - data class RequestNativeWidgetPermission(val widget: Widget, val domain: String, val grantedEvents: RoomDetailViewEvents) : RoomDetailViewEvents() + data class RequestNativeWidgetPermission(val widget: Widget, + val domain: String, + val grantedEvents: RoomDetailViewEvents) : RoomDetailViewEvents() object MessageSent : SendMessageResult() data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult() 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 e85de5c918..7585bfca26 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 @@ -332,15 +332,9 @@ class RoomDetailViewModel @AssistedInject constructor( private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) { _viewEvents.post(RoomDetailViewEvents.ShowWaitingView) viewModelScope.launch(Dispatchers.IO) { - // Build data for a jitsi widget - // Build data for a jitsi widget val widgetId: String = WidgetType.Jitsi.preferred + "_" + session.myUserId + "_" + System.currentTimeMillis() - // Create a random enough jitsi conference id - // Note: the jitsi server automatically creates conference when the conference - // id does not exist yet - // Create a random enough jitsi conference id // Note: the jitsi server automatically creates conference when the conference // id does not exist yet @@ -356,9 +350,14 @@ class RoomDetailViewModel @AssistedInject constructor( // We use the default element wrapper for this widget // https://github.com/vector-im/element-web/blob/develop/docs/jitsi-dev.md - val url = "https://app.element.io/jitsi.html?" + - "confId=$confId#conferenceDomain=\$domain&conferenceId=\$conferenceId&isAudioOnly=${action.video}" + - "&displayName=\$matrix_display_name&avatarUrl=\$matrix_avatar_url&userId=\$matrix_user_id" + val url = "https://app.element.io/jitsi.html" + + "?confId=$confId" + + "#conferenceDomain=\$domain" + + "&conferenceId=\$conferenceId" + + "&isAudioOnly=${!action.withVideo}" + + "&displayName=\$matrix_display_name" + + "&avatarUrl=\$matrix_avatar_url" + + "&userId=\$matrix_user_id" val widgetEventContent = mapOf( "url" to url, @@ -366,7 +365,7 @@ class RoomDetailViewModel @AssistedInject constructor( "data" to mapOf( "conferenceId" to confId, "domain" to jitsiDomain, - "isAudioOnly" to !action.video + "isAudioOnly" to !action.withVideo ), "creatorUserId" to session.myUserId, "id" to widgetId, @@ -377,7 +376,7 @@ class RoomDetailViewModel @AssistedInject constructor( val widget = awaitCallback { session.widgetService().createRoomWidget(roomId, widgetId, widgetEventContent, it) } - _viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.video)) + _viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.withVideo)) } catch (failure: Throwable) { _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_add_widget))) } finally { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt index 32446bfcde..e87f5cdaa9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt @@ -38,9 +38,9 @@ import javax.inject.Inject /** * Bottom sheet displaying active widgets in a room */ -class RoomWidgetsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomWidgetController.Listener { +class RoomWidgetsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomWidgetsController.Listener { - @Inject lateinit var epoxyController: RoomWidgetController + @Inject lateinit var epoxyController: RoomWidgetsController @Inject lateinit var colorProvider: ColorProvider @Inject lateinit var navigator: Navigator diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt similarity index 79% rename from vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetController.kt rename to vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt index 77a179e2db..b6536fbd93 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/widget/RoomWidgetsController.kt @@ -29,7 +29,10 @@ import javax.inject.Inject /** * Epoxy controller for room widgets list */ -class RoomWidgetController @Inject constructor(val stringProvider: StringProvider, val colorProvider: ColorProvider) : TypedEpoxyController>() { +class RoomWidgetsController @Inject constructor( + val stringProvider: StringProvider, + val colorProvider: ColorProvider) + : TypedEpoxyController>() { var listener: Listener? = null @@ -41,18 +44,18 @@ class RoomWidgetController @Inject constructor(val stringProvider: StringProvide } } else { widgets.forEach { - RoomWidgetItem_() - .id(it.widgetId) - .widget(it) - .widgetClicked { listener?.didSelectWidget(it) } - .addTo(this) + roomWidgetItem { + id(it.widgetId) + widget(it) + widgetClicked { listener?.didSelectWidget(it) } + } } } genericButtonItem { id("addIntegration") text(stringProvider.getString(R.string.room_manage_integrations)) textColor(colorProvider.getColor(R.color.riotx_accent)) - itemClickAction(View.OnClickListener { listener?.didSelectManageWidgets() }) + buttonClickAction(View.OnClickListener { listener?.didSelectManageWidgets() }) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt index 9a863b9142..5d0c9fb1b0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt @@ -111,7 +111,7 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor // id("complete_security") // iconRes(R.drawable.ic_shield_warning) // text(stringProvider.getString(R.string.complete_security)) -// itemClickAction(DebouncedClickListener(View.OnClickListener { _ -> +// buttonClickAction(DebouncedClickListener(View.OnClickListener { _ -> // callback?.completeSecurity() // })) // } diff --git a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt index 13470daaf7..63e54ab074 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionBottomSheet.kt @@ -48,7 +48,7 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() { injector.inject(this) } - // Use this if you don't need to full activity view model + // Use this if you don't need the full activity view model var directListener: ((Boolean) -> Unit)? = null override fun invalidate() = withState(viewModel) { state -> @@ -91,16 +91,16 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() { @OnClick(R.id.widgetPermissionDecline) fun doDecline() { viewModel.handle(RoomWidgetPermissionActions.BlockWidget) - // optimistic dismiss directListener?.invoke(false) + // optimistic dismiss dismiss() } @OnClick(R.id.widgetPermissionContinue) fun doAccept() { viewModel.handle(RoomWidgetPermissionActions.AllowWidget) - // optimistic dismiss directListener?.invoke(true) + // optimistic dismiss dismiss() } diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml index d42020ad69..cc3efbf4f4 100644 --- a/vector/src/main/res/layout/fragment_room_detail.xml +++ b/vector/src/main/res/layout/fragment_room_detail.xml @@ -129,17 +129,17 @@ android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/activeCallView"> + app:layout_constraintTop_toBottomOf="@id/activeConferenceView"> - - - - - - - - - + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/activeConferenceView"> - + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + app:layout_constraintBottom_toTopOf="@id/roomWidgetUrl" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/roomWidgetAvatar" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_chainStyle="packed" + tools:text="Widget name" /> - \ No newline at end of file diff --git a/vector/src/main/res/layout/view_active_call_view.xml b/vector/src/main/res/layout/view_active_call_view.xml index 62ab2ae60e..5634dcee8f 100644 --- a/vector/src/main/res/layout/view_active_call_view.xml +++ b/vector/src/main/res/layout/view_active_call_view.xml @@ -25,8 +25,9 @@ android:textColor="@color/white" app:drawableTint="@color/white" /> - diff --git a/vector/src/main/res/layout/view_active_conference_view.xml b/vector/src/main/res/layout/view_active_conference_view.xml index abe7c87080..66a47b728d 100644 --- a/vector/src/main/res/layout/view_active_conference_view.xml +++ b/vector/src/main/res/layout/view_active_conference_view.xml @@ -5,7 +5,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?colorPrimary" - android:foreground="?attr/selectableItemBackground" tools:parentTag="android.widget.RelativeLayout"> - diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 853e60fc48..94cafc73e1 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -93,7 +93,7 @@ A conference is already in progress! Start video meeting Start audio meeting - Meetings use Jitsi security and permission policies. All people currently in the room will see an invite to join while your meeting is happening. + Meetings use Jitsi security and permission policies. All people currently in the room will see an invite to join while your meeting is happening. Cannot start call You cannot place a call with yourself You cannot place a call with yourself, wait for participants to accept invitation