diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentUploadStateTracker.kt index 540b164aa5..dedf9a83cf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentUploadStateTracker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentUploadStateTracker.kt @@ -22,6 +22,8 @@ interface ContentUploadStateTracker { fun untrack(key: String, updateListener: UpdateListener) + fun clear() + interface UpdateListener { fun onUpdate(state: State) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt index 68f48d20db..66a8341801 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/DefaultContentUploadStateTracker.kt @@ -42,6 +42,10 @@ internal class DefaultContentUploadStateTracker @Inject constructor() : ContentU } } + override fun clear() { + listeners.clear() + } + internal fun setFailure(key: String, throwable: Throwable) { val failure = ContentUploadStateTracker.State.Failure(throwable) updateState(key, failure) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt index b83240a681..693855edbc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt @@ -289,6 +289,9 @@ internal class DefaultTimeline( } override fun addListener(listener: Timeline.Listener) = synchronized(listeners) { + if (listeners.contains(listener)) { + return false + } listeners.add(listener).also { postSnapshot() } @@ -494,9 +497,9 @@ internal class DefaultTimeline( return } val params = PaginationTask.Params(roomId = roomId, - from = token, - direction = direction.toPaginationDirection(), - limit = limit) + from = token, + direction = direction.toPaginationDirection(), + limit = limit) Timber.v("Should fetch $limit items $direction") cancelableBag += paginationTask @@ -571,7 +574,7 @@ internal class DefaultTimeline( val timelineEvent = buildTimelineEvent(eventEntity) if (timelineEvent.isEncrypted() - && timelineEvent.root.mxDecryptionResult == null) { + && timelineEvent.root.mxDecryptionResult == null) { timelineEvent.root.eventId?.let { eventDecryptor.requestDecryption(it) } } diff --git a/vector/src/debug/java/im/vector/riotx/features/debug/sas/DebugSasEmojiActivity.kt b/vector/src/debug/java/im/vector/riotx/features/debug/sas/DebugSasEmojiActivity.kt index ba1c47c08c..17a78f1c6a 100644 --- a/vector/src/debug/java/im/vector/riotx/features/debug/sas/DebugSasEmojiActivity.kt +++ b/vector/src/debug/java/im/vector/riotx/features/debug/sas/DebugSasEmojiActivity.kt @@ -18,18 +18,24 @@ package im.vector.riotx.features.debug.sas import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager import im.vector.matrix.android.api.crypto.getAllVerificationEmojis import im.vector.riotx.R -import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import kotlinx.android.synthetic.main.fragment_generic_recycler.* class DebugSasEmojiActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.fragment_generic_recycler_epoxy) - + setContentView(R.layout.fragment_generic_recycler) val controller = SasEmojiController() - epoxyRecyclerView.setController(controller) + recyclerView.adapter = controller.adapter + recyclerView.layoutManager = LinearLayoutManager(this) controller.setData(SasState(getAllVerificationEmojis())) } + + override fun onDestroy() { + recyclerView.adapter = null + super.onDestroy() + } } diff --git a/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt index 9f94c15edd..924cb6c7bc 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/VectorBaseFragment.kt @@ -135,6 +135,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector { override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) restorables.forEach { it.onSaveInstanceState(outState) } + restorables.clear() } override fun onViewStateRestored(savedInstanceState: Bundle?) { diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt b/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt index 9994ee5002..a00f71e5f8 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/keysbackup/settings/KeysBackupSettingsFragment.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.crypto.keysbackup.settings import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog +import androidx.recyclerview.widget.LinearLayoutManager import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import im.vector.riotx.R @@ -37,12 +38,17 @@ class KeysBackupSettingsFragment @Inject constructor(private val keysBackupSetti override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - keysBackupSettingsRecyclerView.setController(keysBackupSettingsRecyclerViewController) - + keysBackupSettingsRecyclerView.layoutManager = LinearLayoutManager(requireContext()) + keysBackupSettingsRecyclerView.adapter = keysBackupSettingsRecyclerViewController.adapter keysBackupSettingsRecyclerViewController.listener = this } + override fun onDestroyView() { + keysBackupSettingsRecyclerViewController.listener = null + keysBackupSettingsRecyclerView.adapter = null + super.onDestroyView() + } + override fun invalidate() = withState(viewModel) { state -> keysBackupSettingsRecyclerViewController.setData(state) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt index 59f31ec2ee..575940a376 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomDirectoryUsersFragment.kt @@ -18,6 +18,8 @@ package im.vector.riotx.features.home.createdirect import android.os.Bundle import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.jakewharton.rxbinding3.widget.textChanges @@ -48,10 +50,17 @@ class CreateDirectRoomDirectoryUsersFragment @Inject constructor( setupCloseView() } + override fun onDestroyView() { + recyclerView.adapter = null + directRoomController.callback = null + super.onDestroyView() + } + private fun setupRecyclerView() { recyclerView.setHasFixedSize(true) directRoomController.callback = this - recyclerView.setController(directRoomController) + recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) + recyclerView.adapter = directRoomController.adapter } private fun setupSearchByMatrixIdView() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt index 12019fa39e..bad322292b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt @@ -24,6 +24,7 @@ import android.view.MenuItem import android.view.View import android.widget.ScrollView import androidx.core.view.size +import androidx.recyclerview.widget.LinearLayoutManager import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import com.google.android.material.chip.Chip @@ -67,6 +68,12 @@ class CreateDirectRoomKnownUsersFragment @Inject constructor( } } + override fun onDestroyView() { + knownUsersController.callback = null + recyclerView.adapter = null + super.onDestroyView() + } + override fun onPrepareOptionsMenu(menu: Menu) { withState(viewModel) { val createMenuItem = menu.findItem(R.id.action_create_direct_room) @@ -98,7 +105,8 @@ class CreateDirectRoomKnownUsersFragment @Inject constructor( // Don't activate animation as we might have way to much item animation when filtering recyclerView.itemAnimator = null knownUsersController.callback = this - recyclerView.setController(knownUsersController) + recyclerView.layoutManager = LinearLayoutManager(requireContext()) + recyclerView.adapter = knownUsersController.adapter } private fun setupFilterView() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt index 39f8c17f05..5bc0c0f61d 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/GroupListFragment.kt @@ -18,6 +18,8 @@ package im.vector.riotx.features.home.group import android.os.Bundle import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success import com.airbnb.mvrx.fragmentViewModel @@ -45,14 +47,21 @@ class GroupListFragment @Inject constructor( super.onViewCreated(view, savedInstanceState) sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java) groupController.callback = this - stateView.contentView = groupListEpoxyRecyclerView - groupListEpoxyRecyclerView.setController(groupController) + stateView.contentView = groupListView + groupListView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) + groupListView.adapter = groupController.adapter viewModel.subscribe { renderState(it) } viewModel.openGroupLiveData.observeEvent(this) { sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup) } } + override fun onDestroyView() { + groupController.callback = null + groupListView.adapter = null + super.onDestroyView() + } + private fun renderState(state: GroupListViewState) { when (state.asyncGroups) { is Incomplete -> stateView.state = StateView.State.Loading diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 27edc6bc5d..0d869048fb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -194,7 +194,7 @@ class RoomDetailFragment @Inject constructor( private lateinit var sharedActionViewModel: MessageSharedActionViewModel private lateinit var layoutManager: LinearLayoutManager - private lateinit var modelBuildListener: OnModelBuildFinishedListener + private var modelBuildListener: OnModelBuildFinishedListener? = null private lateinit var attachmentsHelper: AttachmentsHelper private lateinit var keyboardStateUtils: KeyboardStateUtils @@ -289,14 +289,16 @@ class RoomDetailFragment @Inject constructor( } override fun onDestroyView() { + timelineEventController.callback = null timelineEventController.removeModelBuildListener(modelBuildListener) + modelBuildListener = null + debouncer.cancelAll() recyclerView.adapter = null super.onDestroyView() } override fun onDestroy() { roomDetailViewModel.handle(RoomDetailAction.ExitTrackingUnreadMessagesState) - debouncer.cancelAll() super.onDestroy() } @@ -481,7 +483,7 @@ class RoomDetailFragment @Inject constructor( updateJumpToReadMarkerViewVisibility() updateJumpToBottomViewVisibility() } - timelineEventController.addModelBuildListener { modelBuildListener } + timelineEventController.addModelBuildListener(modelBuildListener) recyclerView.adapter = timelineEventController.adapter recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { @@ -554,13 +556,11 @@ class RoomDetailFragment @Inject constructor( private fun updateJumpToBottomViewVisibility() { debouncer.debounce("jump_to_bottom_visibility", 250, Runnable { - if (isAdded) { - Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}") - if (layoutManager.findFirstVisibleItemPosition() != 0) { - jumpToBottomView.show() - } else { - jumpToBottomView.hide() - } + Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}") + if (layoutManager.findFirstVisibleItemPosition() != 0) { + jumpToBottomView.show() + } else { + jumpToBottomView.hide() } }) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 00a31db455..e7a18753cd 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -863,7 +863,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro override fun onCleared() { timeline.dispose() - timeline.removeAllListeners() + timeline.removeListener(this) super.onCleared() } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt index 326e19c431..83f9163496 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt @@ -44,7 +44,7 @@ import org.threeten.bp.LocalDateTime import javax.inject.Inject class TimelineEventController @Inject constructor(private val dateFormatter: VectorDateFormatter, - private val session: Session, + private val contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder, private val timelineItemFactory: TimelineItemFactory, private val timelineMediaSizeProvider: TimelineMediaSizeProvider, private val mergedHeaderItemFactory: MergedHeaderItemFactory, @@ -209,6 +209,13 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec timelineMediaSizeProvider.recyclerView = recyclerView } + override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { + timelineMediaSizeProvider.recyclerView = null + contentUploadStateTrackerBinder.clear() + timeline?.removeListener(this) + super.onDetachedFromRecyclerView(recyclerView) + } + override fun buildModels() { val timestamp = System.currentTimeMillis() showingForwardLoader = LoadingItem_() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt index 3fdce63668..bbc3474e1e 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt @@ -25,12 +25,14 @@ import im.vector.matrix.android.api.session.content.ContentUploadStateTracker import im.vector.matrix.android.api.session.room.send.SendState import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder +import im.vector.riotx.core.di.ScreenScope import im.vector.riotx.core.error.ErrorFormatter import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.TextUtils import im.vector.riotx.features.ui.getMessageTextColor import javax.inject.Inject +@ScreenScope class ContentUploadStateTrackerBinder @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, private val colorProvider: ColorProvider, private val errorFormatter: ErrorFormatter) { @@ -40,7 +42,7 @@ class ContentUploadStateTrackerBinder @Inject constructor(private val activeSess fun bind(eventId: String, isLocalFile: Boolean, progressLayout: ViewGroup) { - activeSessionHolder.getActiveSession().also { session -> + activeSessionHolder.getSafeActiveSession()?.also { session -> val uploadStateTracker = session.contentUploadProgressTracker() val updateListener = ContentMediaProgressUpdater(progressLayout, isLocalFile, colorProvider, errorFormatter) updateListeners[eventId] = updateListener @@ -49,13 +51,20 @@ class ContentUploadStateTrackerBinder @Inject constructor(private val activeSess } fun unbind(eventId: String) { - activeSessionHolder.getActiveSession().also { session -> + activeSessionHolder.getSafeActiveSession()?.also { session -> val uploadStateTracker = session.contentUploadProgressTracker() updateListeners[eventId]?.also { uploadStateTracker.untrack(eventId, it) } } } + + fun clear() { + activeSessionHolder.getSafeActiveSession()?.also { + it.contentUploadProgressTracker().clear() + } + } + } private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt index 0d11cf8a31..fc3ae98f5c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineMediaSizeProvider.kt @@ -19,11 +19,12 @@ package im.vector.riotx.features.home.room.detail.timeline.helper import androidx.recyclerview.widget.RecyclerView import im.vector.riotx.core.di.ScreenScope import javax.inject.Inject +import kotlin.math.roundToInt @ScreenScope class TimelineMediaSizeProvider @Inject constructor() { - lateinit var recyclerView: RecyclerView + var recyclerView: RecyclerView? = null private var cachedSize: Pair? = null fun getMaxSize(): Pair { @@ -31,17 +32,17 @@ class TimelineMediaSizeProvider @Inject constructor() { } private fun computeMaxSize(): Pair { - val width = recyclerView.width - val height = recyclerView.height + val width = recyclerView?.width ?: 0 + val height = recyclerView?.height ?: 0 val maxImageWidth: Int val maxImageHeight: Int // landscape / portrait if (width < height) { - maxImageWidth = Math.round(width * 0.7f) - maxImageHeight = Math.round(height * 0.5f) + maxImageWidth = (width * 0.7f).roundToInt() + maxImageHeight = (height * 0.5f).roundToInt() } else { - maxImageWidth = Math.round(width * 0.5f) - maxImageHeight = Math.round(height * 0.7f) + maxImageWidth = (width * 0.5f).roundToInt() + maxImageHeight = (height * 0.7f).roundToInt() } return Pair(maxImageWidth, maxImageHeight) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt index 0fab14867c..334f8b3417 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt @@ -65,7 +65,7 @@ class RoomListFragment @Inject constructor( ) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener { - private lateinit var modelBuildListener: OnModelBuildFinishedListener + private var modelBuildListener: OnModelBuildFinishedListener? = null private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel private val roomListParams: RoomListParams by args() private val roomListViewModel: RoomListViewModel by fragmentViewModel() @@ -120,7 +120,10 @@ class RoomListFragment @Inject constructor( override fun onDestroyView() { roomController.removeModelBuildListener(modelBuildListener) + modelBuildListener = null roomListView.adapter = null + roomController.listener = null + createChatFabMenu.listener = null super.onDestroyView() } diff --git a/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt index 08110f3b33..b50e7cfdcd 100755 --- a/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/terms/LoginTermsFragment.kt @@ -20,6 +20,7 @@ import android.os.Bundle import android.os.Parcelable import android.view.View import androidx.appcompat.app.AlertDialog +import androidx.recyclerview.widget.LinearLayoutManager import butterknife.OnClick import com.airbnb.mvrx.args import im.vector.riotx.R @@ -55,8 +56,9 @@ class LoginTermsFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - loginTermsPolicyList.setController(policyController) + loginTermsPolicyList.setHasFixedSize(true) + loginTermsPolicyList.layoutManager = LinearLayoutManager(requireContext()) + loginTermsPolicyList.adapter = policyController.adapter policyController.listener = this val list = ArrayList() @@ -69,6 +71,12 @@ class LoginTermsFragment @Inject constructor( loginTermsViewState = LoginTermsViewState(list) } + override fun onDestroyView() { + loginTermsPolicyList.adapter = null + policyController.listener = null + super.onDestroyView() + } + private fun renderState() { policyController.setData(loginTermsViewState.localizedFlowDataLoginTermsChecked) diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultFragment.kt b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultFragment.kt index e5b46c2176..bef8a65542 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/EmojiSearchResultFragment.kt @@ -25,14 +25,14 @@ import com.airbnb.mvrx.withState import im.vector.riotx.R import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.utils.LiveEvent -import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import kotlinx.android.synthetic.main.fragment_generic_recycler.* import javax.inject.Inject class EmojiSearchResultFragment @Inject constructor( private val epoxyController: EmojiSearchResultController ) : VectorBaseFragment() { - override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler_epoxy + override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler val viewModel: EmojiSearchResultViewModel by activityViewModel() @@ -50,10 +50,16 @@ class EmojiSearchResultFragment @Inject constructor( } val lmgr = LinearLayoutManager(context, RecyclerView.VERTICAL, false) - epoxyRecyclerView.layoutManager = lmgr - val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context, lmgr.orientation) - epoxyRecyclerView.addItemDecoration(dividerItemDecoration) - epoxyRecyclerView.setController(epoxyController) + recyclerView.layoutManager = lmgr + val dividerItemDecoration = DividerItemDecoration(recyclerView.context, lmgr.orientation) + recyclerView.addItemDecoration(dividerItemDecoration) + recyclerView.adapter = epoxyController.adapter + } + + override fun onDestroyView() { + epoxyController.listener = null + recyclerView.adapter = null + super.onDestroyView() } override fun invalidate() = withState(viewModel) { state -> diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt index b41c563256..109364194d 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsFragment.kt @@ -62,6 +62,9 @@ class PublicRoomsFragment @Inject constructor( it.setDisplayHomeAsUpEnabled(true) } + sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java) + setupRecyclerView() + publicRoomsFilter.queryTextChanges() .debounce(500, TimeUnit.MILLISECONDS) .subscribeBy { @@ -79,6 +82,12 @@ class PublicRoomsFragment @Inject constructor( } } + override fun onDestroyView() { + publicRoomsController.callback = null + publicRoomsList.adapter = null + super.onDestroyView() + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_room_directory_change_protocol -> { @@ -90,22 +99,12 @@ class PublicRoomsFragment @Inject constructor( } } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java) - setupRecyclerView() - } - private fun setupRecyclerView() { val epoxyVisibilityTracker = EpoxyVisibilityTracker() epoxyVisibilityTracker.attach(publicRoomsList) - - val layoutManager = LinearLayoutManager(context) - - publicRoomsList.layoutManager = layoutManager + publicRoomsList.layoutManager = LinearLayoutManager(context) publicRoomsController.callback = this - - publicRoomsList.setController(publicRoomsController) + publicRoomsList.adapter = publicRoomsController.adapter } override fun onPublicRoomClicked(publicRoom: PublicRoom, joinState: JoinState) { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt index 0dec14f50e..95d9c198ee 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/createroom/CreateRoomFragment.kt @@ -50,6 +50,12 @@ class CreateRoomFragment @Inject constructor(private val createRoomController: C } } + override fun onDestroyView() { + createRoomForm.adapter = null + createRoomController.listener = null + super.onDestroyView() + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_create_room -> { @@ -63,11 +69,9 @@ class CreateRoomFragment @Inject constructor(private val createRoomController: C private fun setupRecyclerView() { val layoutManager = LinearLayoutManager(context) - createRoomForm.layoutManager = layoutManager createRoomController.listener = this - - createRoomForm.setController(createRoomController) + createRoomForm.adapter = createRoomController.adapter } override fun onNameChange(newName: String) { diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt index ce7a57deba..cc56de7cd7 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/picker/RoomDirectoryPickerFragment.kt @@ -60,6 +60,12 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie setupRecyclerView() } + override fun onDestroyView() { + roomDirectoryPickerList.adapter = null + roomDirectoryPickerController.callback = null + super.onDestroyView() + } + override fun getMenuRes() = R.menu.menu_directory_server_picker override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -74,11 +80,9 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie private fun setupRecyclerView() { val layoutManager = LinearLayoutManager(context) - roomDirectoryPickerList.layoutManager = layoutManager roomDirectoryPickerController.callback = this - - roomDirectoryPickerList.setController(roomDirectoryPickerController) + roomDirectoryPickerList.adapter = roomDirectoryPickerController.adapter } override fun onRoomDirectoryClicked(roomDirectoryData: RoomDirectoryData) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index 11e473ae24..de267047b9 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -20,6 +20,7 @@ import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible +import androidx.recyclerview.widget.LinearLayoutManager import com.airbnb.mvrx.Async import com.airbnb.mvrx.Loading import com.airbnb.mvrx.fragmentViewModel @@ -29,7 +30,7 @@ import im.vector.riotx.core.error.ErrorFormatter import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment -import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import kotlinx.android.synthetic.main.fragment_generic_recycler.* import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* import javax.inject.Inject @@ -39,7 +40,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( private val errorFormatter: ErrorFormatter ) : VectorBaseFragment(), IgnoredUsersController.Callback { - override fun getLayoutResId() = R.layout.fragment_generic_recycler_epoxy + override fun getLayoutResId() = R.layout.fragment_generic_recycler private val ignoredUsersViewModel: IgnoredUsersViewModel by fragmentViewModel() @@ -49,12 +50,19 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( waiting_view_status_text.setText(R.string.please_wait) waiting_view_status_text.isVisible = true ignoredUsersController.callback = this - epoxyRecyclerView.setController(ignoredUsersController) + recyclerView.layoutManager = LinearLayoutManager(requireContext()) + recyclerView.adapter = ignoredUsersController.adapter ignoredUsersViewModel.requestErrorLiveData.observeEvent(this) { displayErrorDialog(it) } } + override fun onDestroyView() { + ignoredUsersController.callback = null + recyclerView.adapter = null + super.onDestroyView() + } + override fun onResume() { super.onResume() diff --git a/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysFragment.kt index ea23ba2583..e35ec6b5ff 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/push/PushGatewaysFragment.kt @@ -17,6 +17,7 @@ package im.vector.riotx.features.settings.push import android.os.Bundle +import android.view.View import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -28,7 +29,7 @@ import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.ui.list.genericFooterItem -import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import kotlinx.android.synthetic.main.fragment_generic_recycler.* import javax.inject.Inject // Referenced in vector_settings_notifications.xml @@ -36,7 +37,7 @@ class PushGatewaysFragment @Inject constructor( val pushGatewaysViewModelFactory: PushGatewaysViewModel.Factory ) : VectorBaseFragment() { - override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler_epoxy + override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler private val viewModel: PushGatewaysViewModel by fragmentViewModel(PushGatewaysViewModel::class) private val epoxyController by lazy { PushGateWayController(StringProvider(requireContext().resources)) } @@ -46,14 +47,19 @@ class PushGatewaysFragment @Inject constructor( (activity as? VectorBaseActivity)?.supportActionBar?.setTitle(R.string.settings_notifications_targets) } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) val lmgr = LinearLayoutManager(context, RecyclerView.VERTICAL, false) - epoxyRecyclerView.layoutManager = lmgr - val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context, + recyclerView.layoutManager = lmgr + val dividerItemDecoration = DividerItemDecoration(recyclerView.context, lmgr.orientation) - epoxyRecyclerView.addItemDecoration(dividerItemDecoration) - epoxyRecyclerView.setController(epoxyController) + recyclerView.addItemDecoration(dividerItemDecoration) + recyclerView.adapter = epoxyController.adapter + } + + override fun onDestroyView() { + recyclerView.adapter = null + super.onDestroyView() } override fun invalidate() = withState(viewModel) { state -> diff --git a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesFragment.kt index 5e14053d0b..52a5928e5d 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesFragment.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.settings.push import android.os.Bundle +import android.view.View import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -27,12 +28,12 @@ import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.ui.list.genericFooterItem -import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import kotlinx.android.synthetic.main.fragment_generic_recycler.* // Referenced in vector_settings_notifications.xml class PushRulesFragment : VectorBaseFragment() { - override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler_epoxy + override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler private val viewModel: PushRulesViewModel by fragmentViewModel(PushRulesViewModel::class) @@ -43,14 +44,19 @@ class PushRulesFragment : VectorBaseFragment() { (activity as? VectorBaseActivity)?.supportActionBar?.setTitle(R.string.settings_push_rules) } - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) val lmgr = LinearLayoutManager(context, RecyclerView.VERTICAL, false) - epoxyRecyclerView.layoutManager = lmgr - val dividerItemDecoration = DividerItemDecoration(epoxyRecyclerView.context, + recyclerView.layoutManager = lmgr + val dividerItemDecoration = DividerItemDecoration(recyclerView.context, lmgr.orientation) - epoxyRecyclerView.addItemDecoration(dividerItemDecoration) - epoxyRecyclerView.setController(epoxyController) + recyclerView.addItemDecoration(dividerItemDecoration) + recyclerView.adapter = epoxyController.adapter + } + + override fun onDestroyView() { + recyclerView.adapter = null + super.onDestroyView() } override fun invalidate() = withState(viewModel) { state -> diff --git a/vector/src/main/res/layout/fragment_create_direct_room.xml b/vector/src/main/res/layout/fragment_create_direct_room.xml index f8450d1e6e..5ad2da1032 100644 --- a/vector/src/main/res/layout/fragment_create_direct_room.xml +++ b/vector/src/main/res/layout/fragment_create_direct_room.xml @@ -122,7 +122,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/createDirectRoomFilterDivider" /> - - - - - - - - -