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
This commit is contained in:
parent
157f22ac2d
commit
4f8fd7b994
|
@ -137,7 +137,7 @@ dependencies {
|
||||||
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.8.1"))
|
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.8.1"))
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
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"
|
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
||||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
||||||
|
|
|
@ -74,9 +74,7 @@ data class E2EWellKnownConfig(
|
||||||
)
|
)
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
class WellKnownPreferredConfig {
|
data class WellKnownPreferredConfig(
|
||||||
|
|
||||||
@JvmField
|
|
||||||
@Json(name = "preferredDomain")
|
@Json(name = "preferredDomain")
|
||||||
var preferredDomain: String? = null
|
val preferredDomain: String? = null
|
||||||
}
|
)
|
||||||
|
|
|
@ -39,7 +39,9 @@ data class HomeServerCapabilities(
|
||||||
* (as it was before) for various environments where this is desired.
|
* (as it was before) for various environments where this is desired.
|
||||||
*/
|
*/
|
||||||
val adminE2EByDefault: Boolean = true,
|
val adminE2EByDefault: Boolean = true,
|
||||||
|
/**
|
||||||
|
* Preferred Jitsi domain, provided in Wellknown
|
||||||
|
*/
|
||||||
val preferredJitsiDomain: String? = null
|
val preferredJitsiDomain: String? = null
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.database
|
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.DynamicRealm
|
||||||
import io.realm.RealmMigration
|
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 timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -55,8 +55,12 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun migrateTo3(realm: DynamicRealm) {
|
private fun migrateTo3(realm: DynamicRealm) {
|
||||||
Timber.d("Step 1 -> 2")
|
Timber.d("Step 2 -> 3")
|
||||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||||
?.addField(HomeServerCapabilitiesEntityFields.PREFERRED_JITSI_DOMAIN, String::class.java)
|
?.addField(HomeServerCapabilitiesEntityFields.PREFERRED_JITSI_DOMAIN, String::class.java)
|
||||||
|
?.transform { obj ->
|
||||||
|
// Schedule a refresh of the capabilities
|
||||||
|
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,14 @@
|
||||||
<!-- Needed for incoming calls -->
|
<!-- Needed for incoming calls -->
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
|
||||||
|
<!-- Jitsi libs adds CALENDAR permissions, but we can remove them safely according to https://github.com/jitsi/jitsi-meet/issues/4068#issuecomment-480482481 -->
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_CALENDAR"
|
||||||
|
tools:node="remove" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_CALENDAR"
|
||||||
|
tools:node="remove" />
|
||||||
|
|
||||||
<!-- Adding CAMERA permission prevents Chromebooks to see the application on the PlayStore -->
|
<!-- Adding CAMERA permission prevents Chromebooks to see the application on the PlayStore -->
|
||||||
<!-- Tell that the Camera is not mandatory to install the application -->
|
<!-- Tell that the Camera is not mandatory to install the application -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
|
|
|
@ -36,7 +36,7 @@ abstract class GenericButtonItem : VectorEpoxyModel<GenericButtonItem.Holder>()
|
||||||
var text: String? = null
|
var text: String? = null
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var itemClickAction: View.OnClickListener? = null
|
var buttonClickAction: View.OnClickListener? = null
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
@ColorInt
|
@ColorInt
|
||||||
|
@ -57,7 +57,7 @@ abstract class GenericButtonItem : VectorEpoxyModel<GenericButtonItem.Holder>()
|
||||||
holder.button.icon = null
|
holder.button.icon = null
|
||||||
}
|
}
|
||||||
|
|
||||||
itemClickAction?.let { holder.button.setOnClickListener(it) }
|
buttonClickAction?.let { holder.button.setOnClickListener(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
|
|
@ -92,7 +92,7 @@ class ActiveConferenceView @JvmOverloads constructor(
|
||||||
val summary = state.asyncRoomSummary()
|
val summary = state.asyncRoomSummary()
|
||||||
if (summary?.membership == Membership.JOIN) {
|
if (summary?.membership == Membership.JOIN) {
|
||||||
// We only display banner for 'live' widgets
|
// We only display banner for 'live' widgets
|
||||||
val activeConf = // for now only jitsi?
|
val activeConf =
|
||||||
state.activeRoomWidgets()?.firstOrNull {
|
state.activeRoomWidgets()?.firstOrNull {
|
||||||
// for now only jitsi?
|
// for now only jitsi?
|
||||||
it.type == WidgetType.Jitsi
|
it.type == WidgetType.Jitsi
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -23,11 +23,8 @@ import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
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.VectorViewModel
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.call.WebRtcPeerConnectionManager
|
|
||||||
import org.jitsi.meet.sdk.JitsiMeetUserInfo
|
import org.jitsi.meet.sdk.JitsiMeetUserInfo
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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 org.matrix.android.sdk.rx.asObservable
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
sealed class JitsiCallViewActions : VectorViewModelAction
|
|
||||||
|
|
||||||
sealed class JitsiCallViewEvents : VectorViewEvents
|
|
||||||
|
|
||||||
class JitsiCallViewModel @AssistedInject constructor(
|
class JitsiCallViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: JitsiCallViewState,
|
@Assisted initialState: JitsiCallViewState,
|
||||||
@Assisted val args: VectorJitsiActivity.Args,
|
@Assisted val args: VectorJitsiActivity.Args,
|
||||||
val session: Session,
|
private val session: Session,
|
||||||
val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
|
private val stringProvider: StringProvider
|
||||||
val stringProvider: StringProvider
|
|
||||||
) : VectorViewModel<JitsiCallViewState, JitsiCallViewActions, JitsiCallViewEvents>(initialState) {
|
) : VectorViewModel<JitsiCallViewState, JitsiCallViewActions, JitsiCallViewEvents>(initialState) {
|
||||||
|
|
||||||
@AssistedInject.Factory
|
@AssistedInject.Factory
|
||||||
|
@ -56,7 +48,7 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||||
init {
|
init {
|
||||||
val me = session.getUser(session.myUserId)?.toMatrixItem()
|
val me = session.getUser(session.myUserId)?.toMatrixItem()
|
||||||
val userInfo = JitsiMeetUserInfo().apply {
|
val userInfo = JitsiMeetUserInfo().apply {
|
||||||
displayName = me?.displayName
|
displayName = me?.getBestName()
|
||||||
avatar = me?.avatarUrl?.let { session.contentUrlResolver().resolveFullSize(it) }?.let { URL(it) }
|
avatar = me?.avatarUrl?.let { session.contentUrlResolver().resolveFullSize(it) }?.let { URL(it) }
|
||||||
}
|
}
|
||||||
val roomName = session.getRoomSummary(args.roomId)?.displayName
|
val roomName = session.getRoomSummary(args.roomId)?.displayName
|
||||||
|
@ -73,7 +65,7 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||||
if (jitsiWidget != null) {
|
if (jitsiWidget != null) {
|
||||||
val uri = Uri.parse(jitsiWidget.computedUrl)
|
val uri = Uri.parse(jitsiWidget.computedUrl)
|
||||||
val confId = uri.getQueryParameter("confId")
|
val confId = uri.getQueryParameter("confId")
|
||||||
val ppt = jitsiWidget.computedUrl?.let { JitsiWidgetProperties(it, stringProvider) }
|
val ppt = jitsiWidget.computedUrl?.let { url -> JitsiWidgetProperties(url, stringProvider) }
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
widget = Success(jitsiWidget),
|
widget = Success(jitsiWidget),
|
||||||
|
@ -89,7 +81,8 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.disposeOnClear()
|
}
|
||||||
|
.disposeOnClear()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handle(action: JitsiCallViewActions) {
|
override fun handle(action: JitsiCallViewActions) {
|
||||||
|
@ -108,7 +101,6 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
override fun initialState(viewModelContext: ViewModelContext): JitsiCallViewState? {
|
override fun initialState(viewModelContext: ViewModelContext): JitsiCallViewState? {
|
||||||
val args: VectorJitsiActivity.Args = viewModelContext.args()
|
val args: VectorJitsiActivity.Args = viewModelContext.args()
|
||||||
// val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession()
|
|
||||||
|
|
||||||
return JitsiCallViewState(
|
return JitsiCallViewState(
|
||||||
roomId = args.roomId,
|
roomId = args.roomId,
|
||||||
|
|
|
@ -55,7 +55,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMeetActivityInterface, Ji
|
||||||
|
|
||||||
@Inject lateinit var viewModelFactory: JitsiCallViewModel.Factory
|
@Inject lateinit var viewModelFactory: JitsiCallViewModel.Factory
|
||||||
|
|
||||||
var jitsiMeetView: JitsiMeetView? = null
|
private var jitsiMeetView: JitsiMeetView? = null
|
||||||
|
|
||||||
private val jitsiViewModel: JitsiCallViewModel by viewModel()
|
private val jitsiViewModel: JitsiCallViewModel by viewModel()
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,8 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
||||||
object SelectStickerAttachment : RoomDetailAction()
|
object SelectStickerAttachment : RoomDetailAction()
|
||||||
object OpenIntegrationManager: RoomDetailAction()
|
object OpenIntegrationManager: RoomDetailAction()
|
||||||
object ManageIntegrations: 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 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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,14 @@ import im.vector.app.features.widgets.WidgetActivity
|
||||||
import im.vector.app.features.widgets.WidgetArgs
|
import im.vector.app.features.widgets.WidgetArgs
|
||||||
import im.vector.app.features.widgets.WidgetKind
|
import im.vector.app.features.widgets.WidgetKind
|
||||||
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
|
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.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.permalinks.PermalinkFactory
|
import org.matrix.android.sdk.api.permalinks.PermalinkFactory
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
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.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.session.widgets.model.WidgetType
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
|
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.EncryptedEventContent
|
||||||
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
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 timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
@ -370,18 +370,18 @@ class RoomDetailFragment @Inject constructor(
|
||||||
|
|
||||||
private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) {
|
private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) {
|
||||||
val tag = RoomWidgetPermissionBottomSheet::class.java.name
|
val tag = RoomWidgetPermissionBottomSheet::class.java.name
|
||||||
val dFrag = childFragmentManager
|
val dFrag = childFragmentManager.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet
|
||||||
.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet
|
|
||||||
if (dFrag != null && dFrag.dialog?.isShowing == true && !dFrag.isRemoving) {
|
if (dFrag != null && dFrag.dialog?.isShowing == true && !dFrag.isRemoving) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
RoomWidgetPermissionBottomSheet
|
RoomWidgetPermissionBottomSheet.newInstance(
|
||||||
.newInstance(WidgetArgs(
|
WidgetArgs(
|
||||||
baseUrl = it.domain,
|
baseUrl = it.domain,
|
||||||
kind = WidgetKind.ROOM,
|
kind = WidgetKind.ROOM,
|
||||||
roomId = roomDetailArgs.roomId,
|
roomId = roomDetailArgs.roomId,
|
||||||
widgetId = it.widget.widgetId
|
widgetId = it.widget.widgetId
|
||||||
)).apply {
|
)
|
||||||
|
).apply {
|
||||||
directListener = { granted ->
|
directListener = { granted ->
|
||||||
if (granted) {
|
if (granted) {
|
||||||
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(it.widget, it.grantedEvents))
|
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(it.widget, it.grantedEvents))
|
||||||
|
@ -592,7 +592,8 @@ class RoomDetailFragment @Inject constructor(
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
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 {
|
menuItem.actionView.setOnClickListener {
|
||||||
onOptionsItemSelected(menuItem)
|
onOptionsItemSelected(menuItem)
|
||||||
}
|
}
|
||||||
|
@ -604,24 +605,23 @@ class RoomDetailFragment @Inject constructor(
|
||||||
it.isVisible = roomDetailViewModel.isMenuItemVisible(it.itemId)
|
it.isVisible = roomDetailViewModel.isMenuItemVisible(it.itemId)
|
||||||
}
|
}
|
||||||
withState(roomDetailViewModel) { state ->
|
withState(roomDetailViewModel) { state ->
|
||||||
val findItem = menu.findItem(R.id.open_matrix_apps)
|
val matrixAppsMenuItem = menu.findItem(R.id.open_matrix_apps)
|
||||||
val widgetsCount = state.activeRoomWidgets.invoke()?.size
|
val widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0
|
||||||
if (widgetsCount ?: 0 > 0) {
|
if (widgetsCount > 0) {
|
||||||
val actionView = findItem.actionView
|
val actionView = matrixAppsMenuItem.actionView
|
||||||
actionView
|
actionView
|
||||||
.findViewById<ImageView>(R.id.action_view_icon_image)
|
.findViewById<ImageView>(R.id.action_view_icon_image)
|
||||||
.setColorFilter(ContextCompat.getColor(requireContext(), R.color.riotx_accent))
|
.setColorFilter(ContextCompat.getColor(requireContext(), R.color.riotx_accent))
|
||||||
actionView.findViewById<TextView>(R.id.cart_badge).isVisible = true
|
actionView.findViewById<TextView>(R.id.cart_badge).setTextOrHide("$widgetsCount")
|
||||||
actionView.findViewById<TextView>(R.id.cart_badge).text = "$widgetsCount"
|
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
||||||
findItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
||||||
} else {
|
} else {
|
||||||
// icon should be default color no badge
|
// icon should be default color no badge
|
||||||
val actionView = findItem.actionView
|
val actionView = matrixAppsMenuItem.actionView
|
||||||
actionView
|
actionView
|
||||||
.findViewById<ImageView>(R.id.action_view_icon_image)
|
.findViewById<ImageView>(R.id.action_view_icon_image)
|
||||||
.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.riotx_text_secondary))
|
.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.riotx_text_secondary))
|
||||||
actionView.findViewById<TextView>(R.id.cart_badge).isVisible = false
|
actionView.findViewById<TextView>(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.voice_call,
|
||||||
R.id.video_call -> {
|
R.id.video_call -> {
|
||||||
handleCallRequest(item)
|
handleCallRequest(item)
|
||||||
|
true
|
||||||
}
|
}
|
||||||
R.id.hangup_call -> {
|
R.id.hangup_call -> {
|
||||||
roomDetailViewModel.handle(RoomDetailAction.EndCall)
|
roomDetailViewModel.handle(RoomDetailAction.EndCall)
|
||||||
|
@ -655,10 +656,10 @@ class RoomDetailFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCallRequest(item: MenuItem): Boolean = withState(roomDetailViewModel) { state ->
|
private fun handleCallRequest(item: MenuItem) = withState(roomDetailViewModel) { state ->
|
||||||
val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState true
|
val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState
|
||||||
val isVideoCall = item.itemId == R.id.video_call
|
val isVideoCall = item.itemId == R.id.video_call
|
||||||
return@withState when (roomSummary.joinedMembersCount) {
|
when (roomSummary.joinedMembersCount) {
|
||||||
1 -> {
|
1 -> {
|
||||||
val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0
|
val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0
|
||||||
if (pendingInvite) {
|
if (pendingInvite) {
|
||||||
|
@ -668,7 +669,6 @@ class RoomDetailFragment @Inject constructor(
|
||||||
// You cannot place a call with yourself.
|
// You cannot place a call with yourself.
|
||||||
showDialogWithMessage(getString(R.string.cannot_call_yourself))
|
showDialogWithMessage(getString(R.string.cannot_call_yourself))
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
val activeCall = sharedCallActionViewModel.activeCall.value
|
val activeCall = sharedCallActionViewModel.activeCall.value
|
||||||
|
@ -685,7 +685,6 @@ class RoomDetailFragment @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
safeStartCall(isVideoCall)
|
safeStartCall(isVideoCall)
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// it's jitsi call
|
// it's jitsi call
|
||||||
|
@ -709,7 +708,6 @@ class RoomDetailFragment @Inject constructor(
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1725,10 +1723,6 @@ class RoomDetailFragment @Inject constructor(
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun joinCurrentJitsiCall(withVideo: Boolean) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
// VectorInviteView.Callback
|
// VectorInviteView.Callback
|
||||||
|
|
||||||
override fun onAcceptInvite() {
|
override fun onAcceptInvite() {
|
||||||
|
|
|
@ -72,7 +72,9 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
|
||||||
|
|
||||||
object OpenIntegrationManager: RoomDetailViewEvents()
|
object OpenIntegrationManager: RoomDetailViewEvents()
|
||||||
object OpenActiveWidgetBottomSheet: 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()
|
object MessageSent : SendMessageResult()
|
||||||
data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult()
|
data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult()
|
||||||
|
|
|
@ -332,15 +332,9 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
||||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
// Build data for a jitsi widget
|
|
||||||
|
|
||||||
// Build data for a jitsi widget
|
// Build data for a jitsi widget
|
||||||
val widgetId: String = WidgetType.Jitsi.preferred + "_" + session.myUserId + "_" + System.currentTimeMillis()
|
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
|
// Create a random enough jitsi conference id
|
||||||
// Note: the jitsi server automatically creates conference when the conference
|
// Note: the jitsi server automatically creates conference when the conference
|
||||||
// id does not exist yet
|
// id does not exist yet
|
||||||
|
@ -356,9 +350,14 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
// We use the default element wrapper for this widget
|
// We use the default element wrapper for this widget
|
||||||
// https://github.com/vector-im/element-web/blob/develop/docs/jitsi-dev.md
|
// https://github.com/vector-im/element-web/blob/develop/docs/jitsi-dev.md
|
||||||
val url = "https://app.element.io/jitsi.html?" +
|
val url = "https://app.element.io/jitsi.html" +
|
||||||
"confId=$confId#conferenceDomain=\$domain&conferenceId=\$conferenceId&isAudioOnly=${action.video}" +
|
"?confId=$confId" +
|
||||||
"&displayName=\$matrix_display_name&avatarUrl=\$matrix_avatar_url&userId=\$matrix_user_id"
|
"#conferenceDomain=\$domain" +
|
||||||
|
"&conferenceId=\$conferenceId" +
|
||||||
|
"&isAudioOnly=${!action.withVideo}" +
|
||||||
|
"&displayName=\$matrix_display_name" +
|
||||||
|
"&avatarUrl=\$matrix_avatar_url" +
|
||||||
|
"&userId=\$matrix_user_id"
|
||||||
|
|
||||||
val widgetEventContent = mapOf(
|
val widgetEventContent = mapOf(
|
||||||
"url" to url,
|
"url" to url,
|
||||||
|
@ -366,7 +365,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
"data" to mapOf(
|
"data" to mapOf(
|
||||||
"conferenceId" to confId,
|
"conferenceId" to confId,
|
||||||
"domain" to jitsiDomain,
|
"domain" to jitsiDomain,
|
||||||
"isAudioOnly" to !action.video
|
"isAudioOnly" to !action.withVideo
|
||||||
),
|
),
|
||||||
"creatorUserId" to session.myUserId,
|
"creatorUserId" to session.myUserId,
|
||||||
"id" to widgetId,
|
"id" to widgetId,
|
||||||
|
@ -377,7 +376,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
val widget = awaitCallback<Widget> {
|
val widget = awaitCallback<Widget> {
|
||||||
session.widgetService().createRoomWidget(roomId, widgetId, widgetEventContent, it)
|
session.widgetService().createRoomWidget(roomId, widgetId, widgetEventContent, it)
|
||||||
}
|
}
|
||||||
_viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.video))
|
_viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.withVideo))
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
_viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_add_widget)))
|
_viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_add_widget)))
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -38,9 +38,9 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Bottom sheet displaying active widgets in a room
|
* 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 colorProvider: ColorProvider
|
||||||
@Inject lateinit var navigator: Navigator
|
@Inject lateinit var navigator: Navigator
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,10 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Epoxy controller for room widgets list
|
* Epoxy controller for room widgets list
|
||||||
*/
|
*/
|
||||||
class RoomWidgetController @Inject constructor(val stringProvider: StringProvider, val colorProvider: ColorProvider) : TypedEpoxyController<List<Widget>>() {
|
class RoomWidgetsController @Inject constructor(
|
||||||
|
val stringProvider: StringProvider,
|
||||||
|
val colorProvider: ColorProvider)
|
||||||
|
: TypedEpoxyController<List<Widget>>() {
|
||||||
|
|
||||||
var listener: Listener? = null
|
var listener: Listener? = null
|
||||||
|
|
||||||
|
@ -41,18 +44,18 @@ class RoomWidgetController @Inject constructor(val stringProvider: StringProvide
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
widgets.forEach {
|
widgets.forEach {
|
||||||
RoomWidgetItem_()
|
roomWidgetItem {
|
||||||
.id(it.widgetId)
|
id(it.widgetId)
|
||||||
.widget(it)
|
widget(it)
|
||||||
.widgetClicked { listener?.didSelectWidget(it) }
|
widgetClicked { listener?.didSelectWidget(it) }
|
||||||
.addTo(this)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
genericButtonItem {
|
genericButtonItem {
|
||||||
id("addIntegration")
|
id("addIntegration")
|
||||||
text(stringProvider.getString(R.string.room_manage_integrations))
|
text(stringProvider.getString(R.string.room_manage_integrations))
|
||||||
textColor(colorProvider.getColor(R.color.riotx_accent))
|
textColor(colorProvider.getColor(R.color.riotx_accent))
|
||||||
itemClickAction(View.OnClickListener { listener?.didSelectManageWidgets() })
|
buttonClickAction(View.OnClickListener { listener?.didSelectManageWidgets() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
|
||||||
// id("complete_security")
|
// id("complete_security")
|
||||||
// iconRes(R.drawable.ic_shield_warning)
|
// iconRes(R.drawable.ic_shield_warning)
|
||||||
// text(stringProvider.getString(R.string.complete_security))
|
// text(stringProvider.getString(R.string.complete_security))
|
||||||
// itemClickAction(DebouncedClickListener(View.OnClickListener { _ ->
|
// buttonClickAction(DebouncedClickListener(View.OnClickListener { _ ->
|
||||||
// callback?.completeSecurity()
|
// callback?.completeSecurity()
|
||||||
// }))
|
// }))
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -48,7 +48,7 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
injector.inject(this)
|
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
|
var directListener: ((Boolean) -> Unit)? = null
|
||||||
|
|
||||||
override fun invalidate() = withState(viewModel) { state ->
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
|
@ -91,16 +91,16 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
@OnClick(R.id.widgetPermissionDecline)
|
@OnClick(R.id.widgetPermissionDecline)
|
||||||
fun doDecline() {
|
fun doDecline() {
|
||||||
viewModel.handle(RoomWidgetPermissionActions.BlockWidget)
|
viewModel.handle(RoomWidgetPermissionActions.BlockWidget)
|
||||||
// optimistic dismiss
|
|
||||||
directListener?.invoke(false)
|
directListener?.invoke(false)
|
||||||
|
// optimistic dismiss
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.widgetPermissionContinue)
|
@OnClick(R.id.widgetPermissionContinue)
|
||||||
fun doAccept() {
|
fun doAccept() {
|
||||||
viewModel.handle(RoomWidgetPermissionActions.AllowWidget)
|
viewModel.handle(RoomWidgetPermissionActions.AllowWidget)
|
||||||
// optimistic dismiss
|
|
||||||
directListener?.invoke(true)
|
directListener?.invoke(true)
|
||||||
|
// optimistic dismiss
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,17 +129,17 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/activeCallView">
|
app:layout_constraintTop_toBottomOf="@id/activeConferenceView">
|
||||||
|
|
||||||
<!-- <im.vector.app.features.home.room.detail.widget.RoomWidgetsBannerView-->
|
<!-- <im.vector.app.features.home.room.detail.widget.RoomWidgetsBannerView-->
|
||||||
<!-- android:id="@+id/roomWidgetsBannerView"-->
|
<!-- android:id="@+id/roomWidgetsBannerView"-->
|
||||||
<!-- android:layout_width="match_parent"-->
|
<!-- android:layout_width="match_parent"-->
|
||||||
<!-- android:layout_height="wrap_content"-->
|
<!-- android:layout_height="wrap_content"-->
|
||||||
<!-- android:layout_marginStart="8dp"-->
|
<!-- android:layout_marginStart="8dp"-->
|
||||||
<!-- android:layout_marginTop="8dp"-->
|
<!-- android:layout_marginTop="8dp"-->
|
||||||
<!-- android:layout_marginEnd="8dp"-->
|
<!-- android:layout_marginEnd="8dp"-->
|
||||||
<!-- android:visibility="gone"-->
|
<!-- android:visibility="gone"-->
|
||||||
<!-- tools:visibility="visible" />-->
|
<!-- tools:visibility="visible" />-->
|
||||||
|
|
||||||
<im.vector.app.core.ui.views.JumpToReadMarkerView
|
<im.vector.app.core.ui.views.JumpToReadMarkerView
|
||||||
android:id="@+id/jumpToReadMarkerView"
|
android:id="@+id/jumpToReadMarkerView"
|
||||||
|
@ -198,7 +198,7 @@
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/activeCallView">
|
app:layout_constraintTop_toBottomOf="@id/activeConferenceView">
|
||||||
|
|
||||||
<org.webrtc.SurfaceViewRenderer
|
<org.webrtc.SurfaceViewRenderer
|
||||||
android:id="@+id/activeCallPiP"
|
android:id="@+id/activeCallPiP"
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:minHeight="64dp"
|
android:minHeight="64dp"
|
||||||
|
@ -14,36 +13,35 @@
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/roomWidgetAvatar"
|
android:id="@+id/roomWidgetAvatar"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="32dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
app:layout_constraintStart_toEndOf="@id/roomWidgetAvatar"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/roomWidgetUrl"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:id="@+id/roomWidgetName"
|
android:id="@+id/roomWidgetName"
|
||||||
style="@style/BottomSheetItemTextMain"
|
style="@style/BottomSheetItemTextMain"
|
||||||
tools:text="@sample/matrix.json/data/displayName" />
|
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" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
app:layout_constraintStart_toStartOf="@id/roomWidgetName"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/roomWidgetName"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/roomWidgetName"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:textStyle="normal"
|
|
||||||
android:id="@+id/roomWidgetUrl"
|
android:id="@+id/roomWidgetUrl"
|
||||||
style="@style/BottomSheetItemTextSecondary"
|
style="@style/BottomSheetItemTextSecondary"
|
||||||
|
android:textStyle="normal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/roomWidgetName"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/roomWidgetName"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/roomWidgetName"
|
||||||
tools:text="https://foobar" />
|
tools:text="https://foobar" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -25,8 +25,9 @@
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
app:drawableTint="@color/white" />
|
app:drawableTint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/returnToCallButton"
|
android:id="@+id/returnToCallButton"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignTop="@+id/activeCallInfo"
|
android:layout_alignTop="@+id/activeCallInfo"
|
||||||
|
@ -38,7 +39,6 @@
|
||||||
android:paddingStart="8dp"
|
android:paddingStart="8dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:text="@string/return_to_call"
|
android:text="@string/return_to_call"
|
||||||
android:textAllCaps="true"
|
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?colorPrimary"
|
android:background="?colorPrimary"
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
tools:parentTag="android.widget.RelativeLayout">
|
tools:parentTag="android.widget.RelativeLayout">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -13,7 +12,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toStartOf="@id/deleteWidgetButton"
|
android:layout_toStartOf="@id/deleteWidgetButton"
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_call"
|
android:drawableStart="@drawable/ic_call"
|
||||||
android:drawablePadding="10dp"
|
android:drawablePadding="10dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
@ -26,8 +24,9 @@
|
||||||
app:drawableTint="@color/white"
|
app:drawableTint="@color/white"
|
||||||
tools:text="@string/ongoing_conference_call" />
|
tools:text="@string/ongoing_conference_call" />
|
||||||
|
|
||||||
<TextView
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/deleteWidgetButton"
|
android:id="@+id/deleteWidgetButton"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignTop="@+id/activeConferenceInfo"
|
android:layout_alignTop="@+id/activeConferenceInfo"
|
||||||
|
@ -39,7 +38,6 @@
|
||||||
android:paddingStart="8dp"
|
android:paddingStart="8dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:text="@string/action_close"
|
android:text="@string/action_close"
|
||||||
android:textAllCaps="true"
|
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
Loading…
Reference in New Issue