Migrate to ViewBindings (#1072) - WIP
This commit is contained in:
parent
7de2494af2
commit
4d3c4b5afc
|
@ -23,7 +23,7 @@ import android.widget.LinearLayout
|
|||
import androidx.core.content.withStyledAttributes
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
|
||||
import im.vector.app.databinding.ItemTimelineEventPollResultItemBinding
|
||||
|
||||
class PollResultLineView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
|
@ -31,34 +31,37 @@ class PollResultLineView @JvmOverloads constructor(
|
|||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val views: ItemTimelineEventPollResultItemBinding
|
||||
|
||||
var label: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
pollResultItemLabel.setTextOrHide(value)
|
||||
views.pollResultItemLabel.setTextOrHide(value)
|
||||
}
|
||||
|
||||
var percent: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
pollResultItemPercent.setTextOrHide(value)
|
||||
views.pollResultItemPercent.setTextOrHide(value)
|
||||
}
|
||||
|
||||
var optionSelected: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
pollResultItemSelectedIcon.visibility = if (value) View.VISIBLE else View.INVISIBLE
|
||||
views.pollResultItemSelectedIcon.visibility = if (value) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
|
||||
var isWinner: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
// Text in main color
|
||||
pollResultItemLabel.setTypeface(pollResultItemLabel.typeface, if (value) Typeface.BOLD else Typeface.NORMAL)
|
||||
pollResultItemPercent.setTypeface(pollResultItemPercent.typeface, if (value) Typeface.BOLD else Typeface.NORMAL)
|
||||
views.pollResultItemLabel.setTypeface(views.pollResultItemLabel.typeface, if (value) Typeface.BOLD else Typeface.NORMAL)
|
||||
views.pollResultItemPercent.setTypeface(views.pollResultItemPercent.typeface, if (value) Typeface.BOLD else Typeface.NORMAL)
|
||||
}
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.item_timeline_event_poll_result_item, this)
|
||||
views = ItemTimelineEventPollResultItemBinding.bind(this)
|
||||
orientation = HORIZONTAL
|
||||
|
||||
context.withStyledAttributes(attrs, R.styleable.PollResultLineView) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.databinding.UrlPreviewBinding
|
||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
|
||||
|
@ -38,10 +39,13 @@ class PreviewUrlView @JvmOverloads constructor(
|
|||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), View.OnClickListener {
|
||||
|
||||
private val views: UrlPreviewBinding
|
||||
|
||||
var delegate: TimelineEventController.PreviewUrlCallback? = null
|
||||
|
||||
init {
|
||||
setupView()
|
||||
views = UrlPreviewBinding.bind(this)
|
||||
}
|
||||
|
||||
private var state: PreviewUrlUiState = PreviewUrlUiState.Unknown
|
||||
|
@ -90,7 +94,7 @@ class PreviewUrlView @JvmOverloads constructor(
|
|||
inflate(context, R.layout.url_preview, this)
|
||||
|
||||
setOnClickListener(this)
|
||||
url_preview_close.setOnClickListener { onCloseClick() }
|
||||
views.urlPreviewClose.setOnClickListener { onCloseClick() }
|
||||
}
|
||||
|
||||
private fun renderHidden() {
|
||||
|
@ -104,19 +108,19 @@ class PreviewUrlView @JvmOverloads constructor(
|
|||
|
||||
private fun renderData(previewUrlData: PreviewUrlData, imageContentRenderer: ImageContentRenderer) {
|
||||
isVisible = true
|
||||
url_preview_title.setTextOrHide(previewUrlData.title)
|
||||
url_preview_image.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, url_preview_image) }.orFalse()
|
||||
url_preview_description.setTextOrHide(previewUrlData.description)
|
||||
url_preview_site.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title })
|
||||
views.urlPreviewTitle.setTextOrHide(previewUrlData.title)
|
||||
views.urlPreviewImage.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, views.urlPreviewImage) }.orFalse()
|
||||
views.urlPreviewDescription.setTextOrHide(previewUrlData.description)
|
||||
views.urlPreviewSite.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title })
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide all views that are not visible in all state
|
||||
*/
|
||||
private fun hideAll() {
|
||||
url_preview_title.isVisible = false
|
||||
url_preview_image.isVisible = false
|
||||
url_preview_description.isVisible = false
|
||||
url_preview_site.isVisible = false
|
||||
views.urlPreviewTitle.isVisible = false
|
||||
views.urlPreviewImage.isVisible = false
|
||||
views.urlPreviewDescription.isVisible = false
|
||||
views.urlPreviewSite.isVisible = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.util.AttributeSet
|
|||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.ViewRoomWidgetsBannerBinding
|
||||
|
||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||
|
||||
|
@ -34,10 +35,13 @@ class RoomWidgetsBannerView @JvmOverloads constructor(
|
|||
fun onViewWidgetsClicked()
|
||||
}
|
||||
|
||||
private val views: ViewRoomWidgetsBannerBinding
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
init {
|
||||
setupView()
|
||||
views = ViewRoomWidgetsBannerBinding.bind(this)
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
|
@ -53,7 +57,7 @@ class RoomWidgetsBannerView @JvmOverloads constructor(
|
|||
visibility = View.GONE
|
||||
} else {
|
||||
visibility = View.VISIBLE
|
||||
activeWidgetsLabel.text = context.resources.getQuantityString(R.plurals.active_widgets, widgets.size, widgets.size)
|
||||
views.activeWidgetsLabel.text = context.resources.getQuantityString(R.plurals.active_widgets, widgets.size, widgets.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ class RoomListFragment @Inject constructor(
|
|||
}.exhaustive
|
||||
}
|
||||
|
||||
createChatFabMenu.listener = this
|
||||
views.createChatFabMenu.listener = this
|
||||
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
|
@ -134,10 +134,10 @@ class RoomListFragment @Inject constructor(
|
|||
override fun onDestroyView() {
|
||||
roomController.removeModelBuildListener(modelBuildListener)
|
||||
modelBuildListener = null
|
||||
roomListView.cleanup()
|
||||
views.roomListView.cleanup()
|
||||
roomController.listener = null
|
||||
stateRestorer.clear()
|
||||
createChatFabMenu.listener = null
|
||||
views.createChatFabMenu.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -147,35 +147,35 @@ class RoomListFragment @Inject constructor(
|
|||
|
||||
private fun setupCreateRoomButton() {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.isVisible = true
|
||||
else -> Unit // No button in this mode
|
||||
}
|
||||
|
||||
createChatRoomButton.debouncedClicks {
|
||||
views.createChatRoomButton.debouncedClicks {
|
||||
createDirectChat()
|
||||
}
|
||||
createGroupRoomButton.debouncedClicks {
|
||||
views.createGroupRoomButton.debouncedClicks {
|
||||
openRoomDirectory()
|
||||
}
|
||||
|
||||
// Hide FAB when list is scrolling
|
||||
roomListView.addOnScrollListener(
|
||||
views.roomListView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
createChatFabMenu.removeCallbacks(showFabRunnable)
|
||||
views.createChatFabMenu.removeCallbacks(showFabRunnable)
|
||||
|
||||
when (newState) {
|
||||
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||
createChatFabMenu.postDelayed(showFabRunnable, 250)
|
||||
views.createChatFabMenu.postDelayed(showFabRunnable, 250)
|
||||
}
|
||||
RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.hide()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.hide()
|
||||
RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.hide()
|
||||
RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.hide()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ class RoomListFragment @Inject constructor(
|
|||
|
||||
fun filterRoomsWith(filter: String) {
|
||||
// Scroll the list to top
|
||||
roomListView.scrollToPosition(0)
|
||||
views.roomListView.scrollToPosition(0)
|
||||
|
||||
roomListViewModel.handle(RoomListAction.FilterWith(filter))
|
||||
}
|
||||
|
@ -202,23 +202,23 @@ class RoomListFragment @Inject constructor(
|
|||
private fun setupRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
roomListView.layoutManager = layoutManager
|
||||
roomListView.itemAnimator = RoomListAnimator()
|
||||
roomListView.setRecycledViewPool(sharedViewPool)
|
||||
views.roomListView.layoutManager = layoutManager
|
||||
views.roomListView.itemAnimator = RoomListAnimator()
|
||||
views.roomListView.setRecycledViewPool(sharedViewPool)
|
||||
layoutManager.recycleChildrenOnDetach = true
|
||||
roomController.listener = this
|
||||
modelBuildListener = OnModelBuildFinishedListener { it.dispatchTo(stateRestorer) }
|
||||
roomController.addModelBuildListener(modelBuildListener)
|
||||
roomListView.adapter = roomController.adapter
|
||||
stateView.contentView = roomListView
|
||||
views.roomListView.adapter = roomController.adapter
|
||||
views.stateView.contentView = views.roomListView
|
||||
}
|
||||
|
||||
private val showFabRunnable = Runnable {
|
||||
if (isAdded) {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.show()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
RoomListDisplayMode.NOTIFICATIONS -> views.createChatFabMenu.show()
|
||||
RoomListDisplayMode.PEOPLE -> views.createChatRoomButton.show()
|
||||
RoomListDisplayMode.ROOMS -> views.createGroupRoomButton.show()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ class RoomListFragment @Inject constructor(
|
|||
if (filteredRooms.isNullOrEmpty()) {
|
||||
renderEmptyState(allRooms)
|
||||
} else {
|
||||
stateView.state = StateView.State.Content
|
||||
views.stateView.state = StateView.State.Content
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,11 +332,11 @@ class RoomListFragment @Inject constructor(
|
|||
// Always display the content in this mode, because if the footer
|
||||
StateView.State.Content
|
||||
}
|
||||
stateView.state = emptyState
|
||||
views.stateView.state = emptyState
|
||||
}
|
||||
|
||||
private fun renderLoading() {
|
||||
stateView.state = StateView.State.Loading
|
||||
views.stateView.state = StateView.State.Loading
|
||||
}
|
||||
|
||||
private fun renderFailure(error: Throwable) {
|
||||
|
@ -344,11 +344,11 @@ class RoomListFragment @Inject constructor(
|
|||
is Failure.NetworkConnection -> getString(R.string.network_error_please_check_and_retry)
|
||||
else -> getString(R.string.unknown_error)
|
||||
}
|
||||
stateView.state = StateView.State.Error(message)
|
||||
views.stateView.state = StateView.State.Error(message)
|
||||
}
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
if (createChatFabMenu.onBackPressed()) {
|
||||
if (views.createChatFabMenu.onBackPressed()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -75,12 +75,12 @@ class RoomListQuickActionsBottomSheet :
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||
views.views.bottomSheetRecyclerView.configureWith(roomListActionsEpoxyController, viewPool = sharedViewPool, hasFixedSize = false, disableItemAnimation = true)
|
||||
views.bottomSheetRecyclerView.configureWith(roomListActionsEpoxyController, viewPool = sharedViewPool, hasFixedSize = false, disableItemAnimation = true)
|
||||
roomListActionsEpoxyController.listener = this
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
views.views.bottomSheetRecyclerView.cleanup()
|
||||
views.bottomSheetRecyclerView.cleanup()
|
||||
roomListActionsEpoxyController.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
|
|
@ -22,28 +22,31 @@ import androidx.constraintlayout.motion.widget.MotionLayout
|
|||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import im.vector.app.R
|
||||
|
||||
import im.vector.app.databinding.MotionNotifsFabMenuMergeBinding
|
||||
|
||||
class NotifsFabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val views: MotionNotifsFabMenuMergeBinding
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.motion_notifs_fab_menu_merge, this)
|
||||
views = MotionNotifsFabMenuMergeBinding.bind(this)
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
|
||||
listOf(createRoomItemChat, createRoomItemChatLabel)
|
||||
listOf(views.createRoomItemChat, views.createRoomItemChatLabel)
|
||||
.forEach {
|
||||
it.setOnClickListener {
|
||||
closeFabMenu()
|
||||
listener?.createDirectChat()
|
||||
}
|
||||
}
|
||||
listOf(createRoomItemGroup, createRoomItemGroupLabel)
|
||||
listOf(views.createRoomItemGroup, views.createRoomItemGroupLabel)
|
||||
.forEach {
|
||||
it.setOnClickListener {
|
||||
closeFabMenu()
|
||||
|
@ -51,7 +54,7 @@ class NotifsFabMenuView @JvmOverloads constructor(context: Context, attrs: Attri
|
|||
}
|
||||
}
|
||||
|
||||
createRoomTouchGuard.setOnClickListener {
|
||||
views.createRoomTouchGuard.setOnClickListener {
|
||||
closeFabMenu()
|
||||
}
|
||||
}
|
||||
|
@ -59,22 +62,22 @@ class NotifsFabMenuView @JvmOverloads constructor(context: Context, attrs: Attri
|
|||
override fun transitionToEnd() {
|
||||
super.transitionToEnd()
|
||||
|
||||
createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_close)
|
||||
views.createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_close)
|
||||
}
|
||||
|
||||
override fun transitionToStart() {
|
||||
super.transitionToStart()
|
||||
|
||||
createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_open)
|
||||
views.createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_open)
|
||||
}
|
||||
|
||||
fun show() {
|
||||
isVisible = true
|
||||
createRoomButton.show()
|
||||
views.createRoomButton.show()
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
createRoomButton.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
views.createRoomButton.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
override fun onHidden(fab: FloatingActionButton?) {
|
||||
super.onHidden(fab)
|
||||
isVisible = false
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.content.Intent
|
|||
import android.view.View
|
||||
import android.view.Window
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import androidx.core.util.Pair
|
||||
|
@ -99,7 +100,7 @@ class DefaultNavigator @Inject constructor(
|
|||
val tx = session.cryptoService().verificationService().getExistingTransaction(otherUserId, sasTransactionId)
|
||||
?: return
|
||||
(tx as? IncomingSasVerificationTransaction)?.performAccept()
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
VerificationBottomSheet.withArgs(
|
||||
roomId = null,
|
||||
otherUserId = otherUserId,
|
||||
|
@ -115,7 +116,7 @@ class DefaultNavigator @Inject constructor(
|
|||
session.myUserId,
|
||||
listOf(otherSessionId)
|
||||
)
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
VerificationBottomSheet.withArgs(
|
||||
roomId = null,
|
||||
otherUserId = session.myUserId,
|
||||
|
@ -130,7 +131,7 @@ class DefaultNavigator @Inject constructor(
|
|||
.getCryptoDeviceInfo(session.myUserId)
|
||||
.filter { it.deviceId != session.sessionParams.deviceId }
|
||||
.map { it.deviceId }
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
if (otherSessions.isNotEmpty()) {
|
||||
val pr = session.cryptoService().verificationService().requestKeyVerification(
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
|
@ -147,14 +148,14 @@ class DefaultNavigator @Inject constructor(
|
|||
|
||||
override fun waitSessionVerification(context: Context) {
|
||||
val session = sessionHolder.getSafeActiveSession() ?: return
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
VerificationBottomSheet.forSelfVerification(session)
|
||||
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
|
||||
}
|
||||
}
|
||||
|
||||
override fun upgradeSessionSecurity(context: Context, initCrossSigningOnly: Boolean) {
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
BootstrapBottomSheet.show(
|
||||
context.supportFragmentManager,
|
||||
if (initCrossSigningOnly) SetupMode.CROSS_SIGNING_ONLY else SetupMode.NORMAL
|
||||
|
@ -163,7 +164,7 @@ class DefaultNavigator @Inject constructor(
|
|||
}
|
||||
|
||||
override fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean) {
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is VectorBaseActivity<*>) {
|
||||
context.notImplemented("Open group detail")
|
||||
} else {
|
||||
context.toast(R.string.not_implemented)
|
||||
|
@ -230,7 +231,7 @@ class DefaultNavigator @Inject constructor(
|
|||
override fun openKeysBackupSetup(context: Context, showManualExport: Boolean) {
|
||||
// if cross signing is enabled we should propose full 4S
|
||||
sessionHolder.getSafeActiveSession()?.let { session ->
|
||||
if (session.cryptoService().crossSigningService().canCrossSign() && context is VectorBaseActivity) {
|
||||
if (session.cryptoService().crossSigningService().canCrossSign() && context is AppCompatActivity) {
|
||||
BootstrapBottomSheet.show(context.supportFragmentManager, SetupMode.NORMAL)
|
||||
} else {
|
||||
context.startActivity(KeysBackupSetupActivity.intent(context, showManualExport))
|
||||
|
@ -239,7 +240,7 @@ class DefaultNavigator @Inject constructor(
|
|||
}
|
||||
|
||||
override fun open4SSetup(context: Context, setupMode: SetupMode) {
|
||||
if (context is VectorBaseActivity) {
|
||||
if (context is AppCompatActivity) {
|
||||
BootstrapBottomSheet.show(context.supportFragmentManager, setupMode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
|||
private fun shouldBeDisplayedIn(alert: VectorAlert?, activity: Activity): Boolean {
|
||||
return alert != null
|
||||
&& activity !is PinActivity
|
||||
&& activity is VectorBaseActivity
|
||||
&& activity is VectorBaseActivity<*>
|
||||
&& alert.shouldBeDisplayedIn.invoke(activity)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue