Mark all as read

This commit is contained in:
Benoit Marty 2019-10-11 15:42:22 +02:00
parent 82fc97f619
commit 3622c0ecb4
14 changed files with 111 additions and 47 deletions

View file

@ -8,6 +8,7 @@ Improvements:
- Persist active tab between sessions (#503)
- Do not upload file too big for the homeserver (#587)
- Handle read markers (#84)
- Mark all messages as read (#396)
Other changes:
- Accessibility improvements to read receipts in the room timeline and reactions emoji chooser

View file

@ -53,4 +53,9 @@ interface RoomService {
* @return the [LiveData] of [RoomSummary]
*/
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
/**
* Mark all rooms as read
*/
fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable
}

View file

@ -32,6 +32,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import io.realm.Realm
@ -41,6 +42,7 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
private val roomSummaryMapper: RoomSummaryMapper,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
private val roomFactory: RoomFactory,
private val taskExecutor: TaskExecutor) : RoomService {
@ -80,4 +82,12 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
}
.executeBy(taskExecutor)
}
override fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable {
return markAllRoomsReadTask
.configureWith(MarkAllRoomsReadTask.Params(roomIds)) {
this.callback = callback
}
.executeBy(taskExecutor)
}
}

View file

@ -40,22 +40,14 @@ import im.vector.matrix.android.internal.session.room.membership.leaving.Default
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
import im.vector.matrix.android.internal.session.room.prune.DefaultPruneEventTask
import im.vector.matrix.android.internal.session.room.prune.PruneEventTask
import im.vector.matrix.android.internal.session.room.read.DefaultMarkAllRoomsReadTask
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.relation.DefaultFetchEditHistoryTask
import im.vector.matrix.android.internal.session.room.relation.DefaultFindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.DefaultUpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.relation.FetchEditHistoryTask
import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.relation.*
import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask
import im.vector.matrix.android.internal.session.room.state.SendStateTask
import im.vector.matrix.android.internal.session.room.timeline.*
import im.vector.matrix.android.internal.session.room.timeline.ClearUnlinkedEventsTask
import im.vector.matrix.android.internal.session.room.timeline.DefaultGetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.DefaultPaginationTask
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
import retrofit2.Retrofit
@Module
@ -110,6 +102,9 @@ internal abstract class RoomModule {
@Binds
abstract fun bindSetReadMarkersTask(setReadMarkersTask: DefaultSetReadMarkersTask): SetReadMarkersTask
@Binds
abstract fun bindMarkAllRoomsReadTask(markAllRoomsReadTask: DefaultMarkAllRoomsReadTask): MarkAllRoomsReadTask
@Binds
abstract fun bindFindReactionEventForUndoTask(findReactionEventForUndoTask: DefaultFindReactionEventForUndoTask): FindReactionEventForUndoTask

View file

@ -0,0 +1,35 @@
/*
* Copyright 2019 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.matrix.android.internal.session.room.read
import im.vector.matrix.android.internal.task.Task
import javax.inject.Inject
internal interface MarkAllRoomsReadTask : Task<MarkAllRoomsReadTask.Params, Unit> {
data class Params(
val roomIds: List<String>
)
}
internal class DefaultMarkAllRoomsReadTask @Inject constructor(private val readMarkersTask: SetReadMarkersTask) : MarkAllRoomsReadTask {
override suspend fun execute(params: MarkAllRoomsReadTask.Params) {
params.roomIds.forEach { roomId ->
readMarkersTask.execute(SetReadMarkersTask.Params(roomId, markAllAsRead = true))
}
}
}

View file

@ -25,7 +25,7 @@ import io.realm.Realm
import timber.log.Timber
import javax.inject.Inject
// the receipts dictionnaries
// the receipts dictionaries
// key : $EventId
// value : dict key $UserId
// value dict key ts

View file

@ -32,6 +32,7 @@ import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.Optional
import org.junit.Assert
import org.junit.Test
@ -172,7 +173,6 @@ class PushrulesConditionTest {
}
class MockRoomService() : RoomService {
override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
@ -192,9 +192,21 @@ class PushrulesConditionTest {
override fun liveRoomSummaries(): LiveData<List<RoomSummary>> {
return MutableLiveData()
}
override fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
}
class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room {
override fun getReadMarkerLive(): LiveData<Optional<String>> {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
override fun getMyReadReceiptLive(): LiveData<Optional<String>> {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
@ -242,7 +254,7 @@ class PushrulesConditionTest {
override fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>) {
}
override fun liveTimeLineEvent(eventId: String): LiveData<TimelineEvent> {
override fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
@ -250,7 +262,7 @@ class PushrulesConditionTest {
return _numberOfJoinedMembers
}
override fun liveRoomSummary(): LiveData<RoomSummary> {
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
@ -347,7 +359,7 @@ class PushrulesConditionTest {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}
override fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary> {
override fun getEventSummaryLive(eventId: String): LiveData<Optional<EventAnnotationsSummary>> {
TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
}

View file

@ -59,7 +59,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.vector_home, menu)
menuInflater.inflate(R.menu.home, menu)
return true
}
}

View file

@ -182,7 +182,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
}
}
return true
return super.onOptionsItemSelected(item)
}
override fun onBackPressed() {

View file

@ -19,14 +19,10 @@ package im.vector.riotx.features.home.room.list
import im.vector.matrix.android.api.session.room.model.RoomSummary
sealed class RoomListActions {
data class SelectRoom(val roomSummary: RoomSummary) : RoomListActions()
data class ToggleCategory(val category: RoomCategory) : RoomListActions()
data class AcceptInvitation(val roomSummary: RoomSummary) : RoomListActions()
data class RejectInvitation(val roomSummary: RoomSummary) : RoomListActions()
data class FilterWith(val filter: String) : RoomListActions()
object MarkAllRoomsRead : RoomListActions()
}

View file

@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.list
import android.os.Bundle
import android.os.Parcelable
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
@ -78,6 +79,19 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
injector.inject(this)
}
override fun getMenuRes() = R.menu.room_list
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_home_mark_all_as_read -> {
roomListViewModel.accept(RoomListActions.MarkAllRoomsRead)
return true
}
}
return super.onOptionsItemSelected(item)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupCreateRoomButton()

View file

@ -78,6 +78,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
is RoomListActions.AcceptInvitation -> handleAcceptInvitation(action)
is RoomListActions.RejectInvitation -> handleRejectInvitation(action)
is RoomListActions.FilterWith -> handleFilter(action)
is RoomListActions.MarkAllRoomsRead -> handleMarkAllRoomsRead()
}
}
@ -193,6 +194,16 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room
})
}
private fun handleMarkAllRoomsRead() = withState { state ->
state.asyncFilteredRooms.invoke()
?.flatMap { it.value }
?.filter { it.membership == Membership.JOIN }
?.map { it.roomId }
?.toList()
?.let { session.markAllAsRead(it, object : MatrixCallback<Unit> {}) }
}
private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries {
val invites = ArrayList<RoomSummary>()
val favourites = ArrayList<RoomSummary>()

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_home_mark_all_as_read"
android:icon="@drawable/ic_material_done"
android:title="@string/action_mark_all_as_read" />
</menu>

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu 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"
tools:context="org.matrix.vector.activity.VectorHomeActivity">
<item
android:id="@+id/ic_action_global_search"
android:icon="@drawable/ic_material_search_white"
android:title="@string/action_global_search"
app:showAsAction="collapseActionView" />
<item
android:id="@+id/ic_action_historical"
android:icon="@drawable/ic_material_history_white"
android:title="@string/action_historical"
app:showAsAction="collapseActionView" />
<item
android:id="@+id/ic_action_mark_all_as_read"
android:icon="@drawable/ic_material_done_all_white"
android:title="@string/action_mark_all_as_read"
app:showAsAction="collapseActionView" />
</menu>