mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Merge pull request #843 from vector-im/feature/room_profile
Feature/room profile
This commit is contained in:
commit
f128ed437f
@ -3,6 +3,8 @@ Changes in RiotX 0.13.0 (2020-XX-XX)
|
|||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
- Send and render typing events (#564)
|
- Send and render typing events (#564)
|
||||||
|
- Create Room Profile screen (#54)
|
||||||
|
- Create Room Member Profile screen (#59)
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
- Render events m.room.encryption and m.room.guest_access in the timeline
|
- Render events m.room.encryption and m.room.guest_access in the timeline
|
||||||
|
@ -22,3 +22,9 @@ import io.reactivex.Observable
|
|||||||
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
||||||
return filter { it.hasValue() }.map { it.get() }
|
return filter { it.hasValue() }.map { it.get() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T : Any, U : Any> Observable<Optional<T>>.mapOptional(fn: (T) -> U?): Observable<Optional<U>> {
|
||||||
|
return map {
|
||||||
|
it.map(fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
package im.vector.matrix.rx
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.notification.RoomNotificationState
|
import im.vector.matrix.android.api.session.room.notification.RoomNotificationState
|
||||||
import im.vector.matrix.android.api.session.room.send.UserDraft
|
import im.vector.matrix.android.api.session.room.send.UserDraft
|
||||||
@ -37,7 +38,7 @@ class RxRoom(private val room: Room) {
|
|||||||
.startWith(room.roomSummary().toOptional())
|
.startWith(room.roomSummary().toOptional())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMember>> {
|
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMemberSummary>> {
|
||||||
return room.getRoomMembersLive(queryParams).asObservable()
|
return room.getRoomMembersLive(queryParams).asObservable()
|
||||||
.startWith(room.getRoomMembers(queryParams))
|
.startWith(room.getRoomMembers(queryParams))
|
||||||
}
|
}
|
||||||
@ -52,6 +53,11 @@ class RxRoom(private val room: Room) {
|
|||||||
.startWith(room.getTimeLineEvent(eventId).toOptional())
|
.startWith(room.getTimeLineEvent(eventId).toOptional())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveStateEvent(eventType: String): Observable<Optional<Event>> {
|
||||||
|
return room.getStateEventLive(eventType).asObservable()
|
||||||
|
.startWith(room.getStateEvent(eventType).toOptional())
|
||||||
|
}
|
||||||
|
|
||||||
fun liveReadMarker(): Observable<Optional<String>> {
|
fun liveReadMarker(): Observable<Optional<String>> {
|
||||||
return room.getReadMarkerLive().asObservable()
|
return room.getReadMarkerLive().asObservable()
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,9 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
|
|||||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||||
import im.vector.matrix.android.api.session.sync.SyncState
|
import im.vector.matrix.android.api.session.sync.SyncState
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
import im.vector.matrix.android.api.util.Optional
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import im.vector.matrix.android.api.util.toOptional
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
@ -56,7 +58,8 @@ class RxSession(private val session: Session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun liveUser(userId: String): Observable<Optional<User>> {
|
fun liveUser(userId: String): Observable<Optional<User>> {
|
||||||
return session.getUserLive(userId).asObservable().distinctUntilChanged()
|
return session.getUserLive(userId).asObservable()
|
||||||
|
.startWith(session.getUser(userId).toOptional())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveUsers(): Observable<List<User>> {
|
fun liveUsers(): Observable<List<User>> {
|
||||||
@ -91,6 +94,10 @@ class RxSession(private val session: Session) {
|
|||||||
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
|
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
|
||||||
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder {
|
||||||
|
session.getProfile(userId, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Session.rx(): RxSession {
|
fun Session.rx(): RxSession {
|
||||||
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -63,7 +63,7 @@ object RoomDataHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createFakeRoomMemberEvent(): Event {
|
fun createFakeRoomMemberEvent(): Event {
|
||||||
val roomMember = RoomMember(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
|
val roomMember = RoomMemberSummary(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
|
||||||
return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember)
|
return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
package im.vector.matrix.android.api.pushrules
|
package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||||
|
import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
|
|
||||||
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
||||||
|
|
||||||
@ -28,7 +29,8 @@ class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.se
|
|||||||
return "User power level <$key>"
|
return "User power level <$key>"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
|
fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
|
||||||
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
|
val powerLevelsHelper = PowerLevelsHelper(powerLevels)
|
||||||
|
return event.senderId != null && powerLevelsHelper.getUserPowerLevel(event.senderId) >= powerLevelsHelper.notificationLevel(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
|
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
@ -51,6 +52,7 @@ interface Session :
|
|||||||
SignOutService,
|
SignOutService,
|
||||||
FilterService,
|
FilterService,
|
||||||
FileService,
|
FileService,
|
||||||
|
ProfileService,
|
||||||
PushRuleService,
|
PushRuleService,
|
||||||
PushersService,
|
PushersService,
|
||||||
InitialSyncProgressService,
|
InitialSyncProgressService,
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.api.session.profile
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines methods to handling profile information. It's implemented at the session level.
|
||||||
|
*/
|
||||||
|
interface ProfileService {
|
||||||
|
|
||||||
|
companion object Constants {
|
||||||
|
const val DISPLAY_NAME_KEY = "displayname"
|
||||||
|
const val AVATAR_URL_KEY = "avatar_url"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current dispayname for this user
|
||||||
|
* @param userId the userId param to look for
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current avatarUrl for this user.
|
||||||
|
* @param userId the userId param to look for
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the combined profile information for this user.
|
||||||
|
* This may return keys which are not limited to displayname or avatar_url.
|
||||||
|
* @param userId the userId param to look for
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable
|
||||||
|
}
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.api.session.room.members
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,21 +38,21 @@ interface MembershipService {
|
|||||||
*
|
*
|
||||||
* @return the roomMember with userId or null
|
* @return the roomMember with userId or null
|
||||||
*/
|
*/
|
||||||
fun getRoomMember(userId: String): RoomMember?
|
fun getRoomMember(userId: String): RoomMemberSummary?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all the roomMembers of the room with params
|
* Return all the roomMembers of the room with params
|
||||||
* @param queryParams the params to query for
|
* @param queryParams the params to query for
|
||||||
* @return a roomMember list.
|
* @return a roomMember list.
|
||||||
*/
|
*/
|
||||||
fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMember>
|
fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMemberSummary>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all the roomMembers of the room filtered by memberships
|
* Return all the roomMembers of the room filtered by memberships
|
||||||
* @param queryParams the params to query for
|
* @param queryParams the params to query for
|
||||||
* @return a [LiveData] of roomMember list.
|
* @return a [LiveData] of roomMember list.
|
||||||
*/
|
*/
|
||||||
fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMember>>
|
fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMemberSummary>>
|
||||||
|
|
||||||
fun getNumberOfJoinedMembers(): Int
|
fun getNumberOfJoinedMembers(): Int
|
||||||
|
|
||||||
|
@ -29,11 +29,13 @@ fun roomMemberQueryParams(init: (RoomMemberQueryParams.Builder.() -> Unit) = {})
|
|||||||
data class RoomMemberQueryParams(
|
data class RoomMemberQueryParams(
|
||||||
val displayName: QueryStringValue,
|
val displayName: QueryStringValue,
|
||||||
val memberships: List<Membership>,
|
val memberships: List<Membership>,
|
||||||
|
val userId: QueryStringValue,
|
||||||
val excludeSelf: Boolean
|
val excludeSelf: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
|
|
||||||
|
var userId: QueryStringValue = QueryStringValue.NoCondition
|
||||||
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
||||||
var memberships: List<Membership> = Membership.all()
|
var memberships: List<Membership> = Membership.all()
|
||||||
var excludeSelf: Boolean = false
|
var excludeSelf: Boolean = false
|
||||||
@ -41,6 +43,7 @@ data class RoomMemberQueryParams(
|
|||||||
fun build() = RoomMemberQueryParams(
|
fun build() = RoomMemberQueryParams(
|
||||||
displayName = displayName,
|
displayName = displayName,
|
||||||
memberships = memberships,
|
memberships = memberships,
|
||||||
|
userId = userId,
|
||||||
excludeSelf = excludeSelf
|
excludeSelf = excludeSelf
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.api.session.room.model
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
|
||||||
*/
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
data class PowerLevels(
|
|
||||||
@Json(name = "ban") val ban: Int = 50,
|
|
||||||
@Json(name = "kick") val kick: Int = 50,
|
|
||||||
@Json(name = "invite") val invite: Int = 50,
|
|
||||||
@Json(name = "redact") val redact: Int = 50,
|
|
||||||
@Json(name = "events_default") val eventsDefault: Int = 0,
|
|
||||||
@Json(name = "events") val events: MutableMap<String, Int> = HashMap(),
|
|
||||||
@Json(name = "users_default") val usersDefault: Int = 0,
|
|
||||||
@Json(name = "users") val users: MutableMap<String, Int> = HashMap(),
|
|
||||||
@Json(name = "state_default") val stateDefault: Int = 50,
|
|
||||||
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
|
||||||
) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the user power level of a dedicated user Id
|
|
||||||
*
|
|
||||||
* @param userId the user id
|
|
||||||
* @return the power level
|
|
||||||
*/
|
|
||||||
fun getUserPowerLevel(userId: String): Int {
|
|
||||||
return users.getOrElse(userId) { usersDefault }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the user power levels of a dedicated user id
|
|
||||||
*
|
|
||||||
* @param userId the user
|
|
||||||
* @param powerLevel the new power level
|
|
||||||
*/
|
|
||||||
fun setUserPowerLevel(userId: String, powerLevel: Int) {
|
|
||||||
users[userId] = powerLevel
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell if an user can send an event of type 'eventTypeString'.
|
|
||||||
*
|
|
||||||
* @param eventTypeString the event type (in Event.EVENT_TYPE_XXX values)
|
|
||||||
* @param userId the user id
|
|
||||||
* @return true if the user can send the event
|
|
||||||
*/
|
|
||||||
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
|
||||||
return if (eventTypeString.isNotEmpty() && userId.isNotEmpty()) {
|
|
||||||
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
|
||||||
} else false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells if an user can send a room message.
|
|
||||||
*
|
|
||||||
* @param userId the user id
|
|
||||||
* @return true if the user can send a room message
|
|
||||||
*/
|
|
||||||
fun maySendMessage(userId: String): Boolean {
|
|
||||||
return maySendEventOfType(EventType.MESSAGE, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to get the minimum power level the user must have to send an event of the given type
|
|
||||||
* as a message.
|
|
||||||
*
|
|
||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
|
||||||
* @return the required minimum power level.
|
|
||||||
*/
|
|
||||||
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
|
||||||
return events[eventTypeString] ?: eventsDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to get the minimum power level the user must have to send an event of the given type
|
|
||||||
* as a state event.
|
|
||||||
*
|
|
||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
|
||||||
* @return the required minimum power level.
|
|
||||||
*/
|
|
||||||
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
|
||||||
return events[eventTypeString] ?: stateDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the notification level for a dedicated key.
|
|
||||||
*
|
|
||||||
* @param key the notification key
|
|
||||||
* @return the level
|
|
||||||
*/
|
|
||||||
fun notificationLevel(key: String): Int {
|
|
||||||
val valAsVoid = notifications[key] ?: return 50
|
|
||||||
|
|
||||||
// the first implementation was a string value
|
|
||||||
return if (valAsVoid is String) {
|
|
||||||
valAsVoid.toInt()
|
|
||||||
} else {
|
|
||||||
valAsVoid as Int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.session.room.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsConstants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class PowerLevelsContent(
|
||||||
|
@Json(name = "ban") val ban: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||||
|
@Json(name = "kick") val kick: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||||
|
@Json(name = "invite") val invite: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||||
|
@Json(name = "redact") val redact: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||||
|
@Json(name = "events_default") val eventsDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
|
||||||
|
@Json(name = "events") val events: MutableMap<String, Int> = HashMap(),
|
||||||
|
@Json(name = "users_default") val usersDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
|
||||||
|
@Json(name = "users") val users: MutableMap<String, Int> = HashMap(),
|
||||||
|
@Json(name = "state_default") val stateDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
|
||||||
|
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
||||||
|
)
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.api.session.room.model
|
|||||||
/**
|
/**
|
||||||
* Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content
|
* Class representing a simplified version of EventType.STATE_ROOM_MEMBER state event content
|
||||||
*/
|
*/
|
||||||
data class RoomMember(
|
data class RoomMemberSummary(
|
||||||
val membership: Membership,
|
val membership: Membership,
|
||||||
val userId: String,
|
val userId: String,
|
||||||
val displayName: String? = null,
|
val displayName: String? = null,
|
@ -32,6 +32,8 @@ data class RoomSummary(
|
|||||||
val canonicalAlias: String? = null,
|
val canonicalAlias: String? = null,
|
||||||
val aliases: List<String> = emptyList(),
|
val aliases: List<String> = emptyList(),
|
||||||
val isDirect: Boolean = false,
|
val isDirect: Boolean = false,
|
||||||
|
val joinedMembersCount: Int? = 0,
|
||||||
|
val invitedMembersCount: Int? = 0,
|
||||||
val latestPreviewableEvent: TimelineEvent? = null,
|
val latestPreviewableEvent: TimelineEvent? = null,
|
||||||
val otherMemberIds: List<String> = emptyList(),
|
val otherMemberIds: List<String> = emptyList(),
|
||||||
val notificationCount: Int = 0,
|
val notificationCount: Int = 0,
|
||||||
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||||
@ -115,7 +115,7 @@ class CreateRoomParams {
|
|||||||
* The power level content to override in the default power level event
|
* The power level content to override in the default power level event
|
||||||
*/
|
*/
|
||||||
@Json(name = "power_level_content_override")
|
@Json(name = "power_level_content_override")
|
||||||
var powerLevelContentOverride: PowerLevels? = null
|
var powerLevelContentOverride: PowerLevelsContent? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the crypto algorithm to the room creation parameters.
|
* Add the crypto algorithm to the room creation parameters.
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.api.session.room.powerlevels
|
||||||
|
|
||||||
|
object PowerLevelsConstants {
|
||||||
|
|
||||||
|
const val DEFAULT_ROOM_ADMIN_LEVEL = 100
|
||||||
|
const val DEFAULT_ROOM_MODERATOR_LEVEL = 50
|
||||||
|
const val DEFAULT_ROOM_USER_LEVEL = 0
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.api.session.room.powerlevels
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
|
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an helper around PowerLevelsContent.
|
||||||
|
*/
|
||||||
|
class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user power level of a dedicated user Id
|
||||||
|
*
|
||||||
|
* @param userId the user id
|
||||||
|
* @return the power level
|
||||||
|
*/
|
||||||
|
fun getUserPowerLevel(userId: String): Int {
|
||||||
|
return powerLevelsContent.users.getOrElse(userId) {
|
||||||
|
powerLevelsContent.usersDefault
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell if an user can send an event of a certain type
|
||||||
|
*
|
||||||
|
* @param eventType the event type to check for
|
||||||
|
* @param userId the user id
|
||||||
|
* @return true if the user can send this type of event
|
||||||
|
*/
|
||||||
|
fun isAllowedToSend(eventType: String, userId: String): Boolean {
|
||||||
|
return if (eventType.isNotEmpty() && userId.isNotEmpty()) {
|
||||||
|
val powerLevel = getUserPowerLevel(userId)
|
||||||
|
val minimumPowerLevel = powerLevelsContent.events[eventType]
|
||||||
|
?: if (EventType.isStateEvent(eventType)) {
|
||||||
|
powerLevelsContent.stateDefault
|
||||||
|
} else {
|
||||||
|
powerLevelsContent.eventsDefault
|
||||||
|
}
|
||||||
|
powerLevel >= minimumPowerLevel
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification level for a dedicated key.
|
||||||
|
*
|
||||||
|
* @param key the notification key
|
||||||
|
* @return the level
|
||||||
|
*/
|
||||||
|
fun notificationLevel(key: String): Int {
|
||||||
|
return when (val value = powerLevelsContent.notifications[key]) {
|
||||||
|
// the first implementation was a string value
|
||||||
|
is String -> value.toInt()
|
||||||
|
is Int -> value
|
||||||
|
else -> PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.room.state
|
package im.vector.matrix.android.api.session.room.state
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
|
||||||
interface StateService {
|
interface StateService {
|
||||||
|
|
||||||
@ -32,4 +34,6 @@ interface StateService {
|
|||||||
fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>)
|
fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
fun getStateEvent(eventType: String): Event?
|
fun getStateEvent(eventType: String): Event?
|
||||||
|
|
||||||
|
fun getStateEventLive(eventType: String): LiveData<Optional<Event>>
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.api.util
|
|||||||
|
|
||||||
import im.vector.matrix.android.BuildConfig
|
import im.vector.matrix.android.BuildConfig
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
|
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
@ -147,4 +147,4 @@ fun GroupSummary.toMatrixItem() = MatrixItem.GroupItem(groupId, displayName, ava
|
|||||||
fun RoomSummary.toMatrixItem() = MatrixItem.RoomItem(roomId, displayName, avatarUrl)
|
fun RoomSummary.toMatrixItem() = MatrixItem.RoomItem(roomId, displayName, avatarUrl)
|
||||||
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
|
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
|
||||||
fun PublicRoom.toMatrixItem() = MatrixItem.RoomItem(roomId, name, avatarUrl)
|
fun PublicRoom.toMatrixItem() = MatrixItem.RoomItem(roomId, name, avatarUrl)
|
||||||
fun RoomMember.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl)
|
fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName, avatarUrl)
|
||||||
|
@ -27,6 +27,14 @@ data class Optional<T : Any> constructor(private val value: T?) {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <U : Any> map(fn: (T) -> U?): Optional<U> {
|
||||||
|
return if (value == null) {
|
||||||
|
from(null)
|
||||||
|
} else {
|
||||||
|
from(fn(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getOrElse(fn: () -> T): T {
|
fun getOrElse(fn: () -> T): T {
|
||||||
return value ?: fn()
|
return value ?: fn()
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter
|
import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter
|
||||||
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
||||||
@ -64,7 +64,7 @@ import im.vector.matrix.android.internal.di.MoshiProvider
|
|||||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
|
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
@ -697,9 +697,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
&& shouldEncryptForInvitedMembers(roomId)
|
&& shouldEncryptForInvitedMembers(roomId)
|
||||||
|
|
||||||
userIds = if (encryptForInvitedMembers) {
|
userIds = if (encryptForInvitedMembers) {
|
||||||
RoomMembers(realm, roomId).getActiveRoomMemberIds()
|
RoomMemberHelper(realm, roomId).getActiveRoomMemberIds()
|
||||||
} else {
|
} else {
|
||||||
RoomMembers(realm, roomId).getJoinedRoomMemberIds()
|
RoomMemberHelper(realm, roomId).getJoinedRoomMemberIds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return userIds
|
return userIds
|
||||||
@ -722,7 +722,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
event.stateKey?.let { userId ->
|
event.stateKey?.let { userId ->
|
||||||
val roomMember: RoomMember? = event.content.toModel()
|
val roomMember: RoomMemberSummary? = event.content.toModel()
|
||||||
val membership = roomMember?.membership
|
val membership = roomMember?.membership
|
||||||
if (membership == Membership.JOIN) {
|
if (membership == Membership.JOIN) {
|
||||||
// make sure we are tracking the deviceList for this user.
|
// make sure we are tracking the deviceList for this user.
|
||||||
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
|
|||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.fastContains
|
import im.vector.matrix.android.internal.database.query.fastContains
|
||||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
|
|
||||||
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
||||||
chunks.remove(chunkEntity)
|
chunks.remove(chunkEntity)
|
||||||
@ -59,7 +59,7 @@ internal fun RoomEntity.addSendingEvent(event: Event) {
|
|||||||
val eventEntity = event.toEntity(roomId).apply {
|
val eventEntity = event.toEntity(roomId).apply {
|
||||||
this.sendState = SendState.UNSENT
|
this.sendState = SendState.UNSENT
|
||||||
}
|
}
|
||||||
val roomMembers = RoomMembers(realm, roomId)
|
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||||
val myUser = roomMembers.getLastRoomMember(senderId)
|
val myUser = roomMembers.getLastRoomMember(senderId)
|
||||||
val localId = TimelineEventEntity.nextId(realm)
|
val localId = TimelineEventEntity.nextId(realm)
|
||||||
val timelineEventEntity = TimelineEventEntity(localId).also {
|
val timelineEventEntity = TimelineEventEntity(localId).also {
|
||||||
|
@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.database.query.prev
|
|||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -128,7 +128,7 @@ internal class TimelineEventSenderVisitor @Inject constructor() {
|
|||||||
ContentMapper.map(senderRoomMemberContent).toModel<RoomMemberContent>()?.also {
|
ContentMapper.map(senderRoomMemberContent).toModel<RoomMemberContent>()?.also {
|
||||||
result.senderAvatar = it.avatarUrl
|
result.senderAvatar = it.avatarUrl
|
||||||
result.senderName = it.displayName
|
result.senderName = it.displayName
|
||||||
result.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(it.displayName)
|
result.isUniqueDisplayName = RoomMemberHelper(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||||
}
|
}
|
||||||
// We try to fallback on prev content if we got a room member state events with null fields
|
// We try to fallback on prev content if we got a room member state events with null fields
|
||||||
if (root?.type == EventType.STATE_ROOM_MEMBER) {
|
if (root?.type == EventType.STATE_ROOM_MEMBER) {
|
||||||
@ -138,7 +138,7 @@ internal class TimelineEventSenderVisitor @Inject constructor() {
|
|||||||
}
|
}
|
||||||
if (result.senderName == null && it.displayName != null) {
|
if (result.senderName == null && it.displayName != null) {
|
||||||
result.senderName = it.displayName
|
result.senderName = it.displayName
|
||||||
result.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(it.displayName)
|
result.isUniqueDisplayName = RoomMemberHelper(realm, roomId).isUniqueDisplayName(it.displayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,21 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.database.mapper
|
package im.vector.matrix.android.internal.database.mapper
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
|
|
||||||
internal object RoomMemberMapper {
|
internal object RoomMemberSummaryMapper {
|
||||||
|
|
||||||
fun map(roomMemberEntity: RoomMemberEntity): RoomMember {
|
fun map(roomMemberSummaryEntity: RoomMemberSummaryEntity): RoomMemberSummary {
|
||||||
return RoomMember(
|
return RoomMemberSummary(
|
||||||
userId = roomMemberEntity.userId,
|
userId = roomMemberSummaryEntity.userId,
|
||||||
avatarUrl = roomMemberEntity.avatarUrl,
|
avatarUrl = roomMemberSummaryEntity.avatarUrl,
|
||||||
displayName = roomMemberEntity.displayName,
|
displayName = roomMemberSummaryEntity.displayName,
|
||||||
membership = roomMemberEntity.membership
|
membership = roomMemberSummaryEntity.membership
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RoomMemberEntity.asDomain(): RoomMember {
|
internal fun RoomMemberSummaryEntity.asDomain(): RoomMemberSummary {
|
||||||
return RoomMemberMapper.map(this)
|
return RoomMemberSummaryMapper.map(this)
|
||||||
}
|
}
|
@ -60,6 +60,8 @@ internal class RoomSummaryMapper @Inject constructor(
|
|||||||
avatarUrl = roomSummaryEntity.avatarUrl ?: "",
|
avatarUrl = roomSummaryEntity.avatarUrl ?: "",
|
||||||
isDirect = roomSummaryEntity.isDirect,
|
isDirect = roomSummaryEntity.isDirect,
|
||||||
latestPreviewableEvent = latestEvent,
|
latestPreviewableEvent = latestEvent,
|
||||||
|
joinedMembersCount = roomSummaryEntity.joinedMembersCount,
|
||||||
|
invitedMembersCount = roomSummaryEntity.invitedMembersCount,
|
||||||
otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
|
otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
|
||||||
highlightCount = roomSummaryEntity.highlightCount,
|
highlightCount = roomSummaryEntity.highlightCount,
|
||||||
notificationCount = roomSummaryEntity.notificationCount,
|
notificationCount = roomSummaryEntity.notificationCount,
|
||||||
|
@ -21,13 +21,13 @@ import io.realm.RealmObject
|
|||||||
import io.realm.annotations.Index
|
import io.realm.annotations.Index
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
|
|
||||||
internal open class RoomMemberEntity(@PrimaryKey var primaryKey: String = "",
|
internal open class RoomMemberSummaryEntity(@PrimaryKey var primaryKey: String = "",
|
||||||
@Index var userId: String = "",
|
@Index var userId: String = "",
|
||||||
@Index var roomId: String = "",
|
@Index var roomId: String = "",
|
||||||
var displayName: String = "",
|
var displayName: String? = null,
|
||||||
var avatarUrl: String = "",
|
var avatarUrl: String? = null,
|
||||||
var reason: String? = null,
|
var reason: String? = null,
|
||||||
var isDirect: Boolean = false
|
var isDirect: Boolean = false
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
private var membershipStr: String = Membership.NONE.name
|
private var membershipStr: String = Membership.NONE.name
|
@ -50,6 +50,6 @@ import io.realm.annotations.RealmModule
|
|||||||
UserDraftsEntity::class,
|
UserDraftsEntity::class,
|
||||||
DraftEntity::class,
|
DraftEntity::class,
|
||||||
HomeServerCapabilitiesEntity::class,
|
HomeServerCapabilitiesEntity::class,
|
||||||
RoomMemberEntity::class
|
RoomMemberSummaryEntity::class
|
||||||
])
|
])
|
||||||
internal class SessionRealmModule
|
internal class SessionRealmModule
|
||||||
|
@ -60,20 +60,7 @@ internal fun EventEntity.Companion.types(realm: Realm,
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
internal fun RealmQuery<EventEntity>.descending(since: Int? = null, strict: Boolean = false): RealmQuery<EventEntity> {
|
||||||
if (from != null) {
|
|
||||||
if (strict) {
|
|
||||||
this.greaterThan(EventEntityFields.STATE_INDEX, from)
|
|
||||||
} else {
|
|
||||||
this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
.sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING)
|
|
||||||
.findFirst()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean = false): EventEntity? {
|
|
||||||
if (since != null) {
|
if (since != null) {
|
||||||
if (strict) {
|
if (strict) {
|
||||||
this.lessThan(EventEntityFields.STATE_INDEX, since)
|
this.lessThan(EventEntityFields.STATE_INDEX, since)
|
||||||
@ -81,9 +68,26 @@ internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean =
|
|||||||
this.lessThanOrEqualTo(EventEntityFields.STATE_INDEX, since)
|
this.lessThanOrEqualTo(EventEntityFields.STATE_INDEX, since)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this
|
return this.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
||||||
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
}
|
||||||
.findFirst()
|
|
||||||
|
internal fun RealmQuery<EventEntity>.ascending(from: Int? = null, strict: Boolean = true): RealmQuery<EventEntity> {
|
||||||
|
if (from != null) {
|
||||||
|
if (strict) {
|
||||||
|
this.greaterThan(EventEntityFields.STATE_INDEX, from)
|
||||||
|
} else {
|
||||||
|
this.greaterThanOrEqualTo(EventEntityFields.STATE_INDEX, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun RealmQuery<EventEntity>.next(from: Int? = null, strict: Boolean = true): EventEntity? {
|
||||||
|
return this.ascending(from, strict).findFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun RealmQuery<EventEntity>.prev(since: Int? = null, strict: Boolean = false): EventEntity? {
|
||||||
|
return descending(since, strict).findFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RealmList<EventEntity>.find(eventId: String): EventEntity? {
|
internal fun RealmList<EventEntity>.find(eventId: String): EventEntity? {
|
||||||
|
@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.database.query
|
package im.vector.matrix.android.internal.database.query
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
|
|
||||||
internal fun RoomMemberEntity.Companion.where(realm: Realm, roomId: String, userId: String? = null): RealmQuery<RoomMemberEntity> {
|
internal fun RoomMemberSummaryEntity.Companion.where(realm: Realm, roomId: String, userId: String? = null): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
val query = realm
|
val query = realm
|
||||||
.where<RoomMemberEntity>()
|
.where<RoomMemberSummaryEntity>()
|
||||||
.equalTo(RoomMemberEntityFields.ROOM_ID, roomId)
|
.equalTo(RoomMemberSummaryEntityFields.ROOM_ID, roomId)
|
||||||
|
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
query.equalTo(RoomMemberEntityFields.USER_ID, userId)
|
query.equalTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||||
}
|
}
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
|
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
@ -80,6 +81,7 @@ internal class DefaultSession @Inject constructor(
|
|||||||
private val cryptoService: Lazy<DefaultCryptoService>,
|
private val cryptoService: Lazy<DefaultCryptoService>,
|
||||||
private val fileService: Lazy<FileService>,
|
private val fileService: Lazy<FileService>,
|
||||||
private val secureStorageService: Lazy<SecureStorageService>,
|
private val secureStorageService: Lazy<SecureStorageService>,
|
||||||
|
private val profileService: Lazy<ProfileService>,
|
||||||
private val syncThreadProvider: Provider<SyncThread>,
|
private val syncThreadProvider: Provider<SyncThread>,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
private val syncTokenStore: SyncTokenStore,
|
private val syncTokenStore: SyncTokenStore,
|
||||||
@ -101,7 +103,8 @@ internal class DefaultSession @Inject constructor(
|
|||||||
FileService by fileService.get(),
|
FileService by fileService.get(),
|
||||||
InitialSyncProgressService by initialSyncProgressService.get(),
|
InitialSyncProgressService by initialSyncProgressService.get(),
|
||||||
SecureStorageService by secureStorageService.get(),
|
SecureStorageService by secureStorageService.get(),
|
||||||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get() {
|
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||||
|
ProfileService by profileService.get() {
|
||||||
|
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.session.filter.FilterModule
|
|||||||
import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
|
import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
|
||||||
import im.vector.matrix.android.internal.session.group.GroupModule
|
import im.vector.matrix.android.internal.session.group.GroupModule
|
||||||
import im.vector.matrix.android.internal.session.homeserver.HomeServerCapabilitiesModule
|
import im.vector.matrix.android.internal.session.homeserver.HomeServerCapabilitiesModule
|
||||||
|
import im.vector.matrix.android.internal.session.profile.ProfileModule
|
||||||
import im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker
|
import im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker
|
||||||
import im.vector.matrix.android.internal.session.pushers.PushersModule
|
import im.vector.matrix.android.internal.session.pushers.PushersModule
|
||||||
import im.vector.matrix.android.internal.session.room.RoomModule
|
import im.vector.matrix.android.internal.session.room.RoomModule
|
||||||
@ -64,6 +65,7 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
|||||||
CryptoModule::class,
|
CryptoModule::class,
|
||||||
PushersModule::class,
|
PushersModule::class,
|
||||||
AccountDataModule::class,
|
AccountDataModule::class,
|
||||||
|
ProfileModule::class,
|
||||||
SessionAssistedInjectModule::class
|
SessionAssistedInjectModule::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.internal.session.profile
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class DefaultProfileService @Inject constructor(private val taskExecutor: TaskExecutor,
|
||||||
|
private val getProfileInfoTask: GetProfileInfoTask) : ProfileService {
|
||||||
|
|
||||||
|
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
||||||
|
val params = GetProfileInfoTask.Params(userId)
|
||||||
|
return getProfileInfoTask
|
||||||
|
.configureWith(params) {
|
||||||
|
this.callback = object : MatrixCallback<JsonDict> {
|
||||||
|
override fun onSuccess(data: JsonDict) {
|
||||||
|
val displayName = data[ProfileService.DISPLAY_NAME_KEY] as? String
|
||||||
|
matrixCallback.onSuccess(Optional.from(displayName))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
matrixCallback.onFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
||||||
|
val params = GetProfileInfoTask.Params(userId)
|
||||||
|
return getProfileInfoTask
|
||||||
|
.configureWith(params) {
|
||||||
|
this.callback = object : MatrixCallback<JsonDict> {
|
||||||
|
override fun onSuccess(data: JsonDict) {
|
||||||
|
val avatarUrl = data[ProfileService.AVATAR_URL_KEY] as? String
|
||||||
|
matrixCallback.onSuccess(Optional.from(avatarUrl))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
matrixCallback.onFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable {
|
||||||
|
val params = GetProfileInfoTask.Params(userId)
|
||||||
|
return getProfileInfoTask
|
||||||
|
.configureWith(params) {
|
||||||
|
this.callback = matrixCallback
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.internal.session.profile
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal abstract class GetProfileInfoTask : Task<GetProfileInfoTask.Params, JsonDict> {
|
||||||
|
data class Params(
|
||||||
|
val userId: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultGetProfileInfoTask @Inject constructor(private val profileAPI: ProfileAPI,
|
||||||
|
private val eventBus: EventBus) : GetProfileInfoTask() {
|
||||||
|
|
||||||
|
override suspend fun execute(params: Params): JsonDict {
|
||||||
|
return executeRequest(eventBus) {
|
||||||
|
apiCall = profileAPI.getProfile(params.userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.internal.session.profile
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
|
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Path
|
||||||
|
|
||||||
|
interface ProfileAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the combined profile information for this user.
|
||||||
|
* This API may be used to fetch the user's own profile information or other users; either locally or on remote homeservers.
|
||||||
|
* This API may return keys which are not limited to displayname or avatar_url.
|
||||||
|
* @param userId the user id to fetch profile info
|
||||||
|
*/
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}")
|
||||||
|
fun getProfile(@Path("userId") userId: String): Call<JsonDict>
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.matrix.android.internal.session.profile
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||||
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
|
||||||
|
@Module
|
||||||
|
internal abstract class ProfileModule {
|
||||||
|
|
||||||
|
@Module
|
||||||
|
companion object {
|
||||||
|
@Provides
|
||||||
|
@JvmStatic
|
||||||
|
@SessionScope
|
||||||
|
fun providesProfileAPI(retrofit: Retrofit): ProfileAPI {
|
||||||
|
return retrofit.create(ProfileAPI::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindProfileService(service: DefaultProfileService): ProfileService
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindGetProfileTask(task: DefaultGetProfileInfoTask): GetProfileInfoTask
|
||||||
|
}
|
@ -22,11 +22,11 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||||||
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
|
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
|
||||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy,
|
internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy,
|
||||||
@ -45,13 +45,13 @@ internal class RoomAvatarResolver @Inject constructor(private val monarchy: Mona
|
|||||||
if (!res.isNullOrEmpty()) {
|
if (!res.isNullOrEmpty()) {
|
||||||
return@doWithRealm
|
return@doWithRealm
|
||||||
}
|
}
|
||||||
val roomMembers = RoomMembers(realm, roomId)
|
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||||
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
|
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||||
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
|
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
|
||||||
if (members.size == 1) {
|
if (members.size == 1) {
|
||||||
res = members.firstOrNull()?.avatarUrl
|
res = members.firstOrNull()?.avatarUrl
|
||||||
} else if (members.size == 2) {
|
} else if (members.size == 2) {
|
||||||
val firstOtherMember = members.where().notEqualTo(RoomMemberEntityFields.USER_ID, userId).findFirst()
|
val firstOtherMember = members.where().notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId).findFirst()
|
||||||
res = firstOtherMember?.avatarUrl
|
res = firstOtherMember?.avatarUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,14 @@ import im.vector.matrix.android.api.session.room.model.RoomAliasesContent
|
|||||||
import im.vector.matrix.android.api.session.room.model.RoomCanonicalAliasContent
|
import im.vector.matrix.android.api.session.room.model.RoomCanonicalAliasContent
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomTopicContent
|
import im.vector.matrix.android.api.session.room.model.RoomTopicContent
|
||||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||||
|
import im.vector.matrix.android.internal.database.model.*
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.*
|
import im.vector.matrix.android.internal.database.query.*
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
|
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import im.vector.matrix.android.internal.session.sync.RoomSyncHandler
|
import im.vector.matrix.android.internal.session.sync.RoomSyncHandler
|
||||||
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
|
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
|
||||||
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
|
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
|
||||||
@ -115,9 +115,9 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||||||
roomSummaryEntity.typingUserIds.addAll(ephemeralResult?.typingUserIds.orEmpty())
|
roomSummaryEntity.typingUserIds.addAll(ephemeralResult?.typingUserIds.orEmpty())
|
||||||
|
|
||||||
if (updateMembers) {
|
if (updateMembers) {
|
||||||
val otherRoomMembers = RoomMembers(realm, roomId)
|
val otherRoomMembers = RoomMemberHelper(realm, roomId)
|
||||||
.queryRoomMembersEvent()
|
.queryRoomMembersEvent()
|
||||||
.notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||||
.findAll()
|
.findAll()
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.map { it.userId }
|
.map { it.userId }
|
||||||
|
@ -24,11 +24,11 @@ import im.vector.matrix.android.api.MatrixCallback
|
|||||||
import im.vector.matrix.android.api.session.room.members.MembershipService
|
import im.vector.matrix.android.api.session.room.members.MembershipService
|
||||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.query.process
|
import im.vector.matrix.android.internal.query.process
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
||||||
@ -66,14 +66,14 @@ internal class DefaultMembershipService @AssistedInject constructor(
|
|||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoomMember(userId: String): RoomMember? {
|
override fun getRoomMember(userId: String): RoomMemberSummary? {
|
||||||
val roomMemberEntity = monarchy.fetchCopied {
|
val roomMemberEntity = monarchy.fetchCopied {
|
||||||
RoomMembers(it, roomId).getLastRoomMember(userId)
|
RoomMemberHelper(it, roomId).getLastRoomMember(userId)
|
||||||
}
|
}
|
||||||
return roomMemberEntity?.asDomain()
|
return roomMemberEntity?.asDomain()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMember> {
|
override fun getRoomMembers(queryParams: RoomMemberQueryParams): List<RoomMemberSummary> {
|
||||||
return monarchy.fetchAllMappedSync(
|
return monarchy.fetchAllMappedSync(
|
||||||
{
|
{
|
||||||
roomMembersQuery(it, queryParams)
|
roomMembersQuery(it, queryParams)
|
||||||
@ -84,7 +84,7 @@ internal class DefaultMembershipService @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMember>> {
|
override fun getRoomMembersLive(queryParams: RoomMemberQueryParams): LiveData<List<RoomMemberSummary>> {
|
||||||
return monarchy.findAllMappedWithChanges(
|
return monarchy.findAllMappedWithChanges(
|
||||||
{
|
{
|
||||||
roomMembersQuery(it, queryParams)
|
roomMembersQuery(it, queryParams)
|
||||||
@ -95,20 +95,21 @@ internal class DefaultMembershipService @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberEntity> {
|
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
return RoomMembers(realm, roomId).queryRoomMembersEvent()
|
return RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
|
||||||
.process(RoomMemberEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
|
||||||
.process(RoomMemberEntityFields.DISPLAY_NAME, queryParams.displayName)
|
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
||||||
|
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
|
||||||
.apply {
|
.apply {
|
||||||
if (queryParams.excludeSelf) {
|
if (queryParams.excludeSelf) {
|
||||||
notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNumberOfJoinedMembers(): Int {
|
override fun getNumberOfJoinedMembers(): Int {
|
||||||
return Realm.getInstance(monarchy.realmConfiguration).use {
|
return Realm.getInstance(monarchy.realmConfiguration).use {
|
||||||
RoomMembers(it, roomId).getNumberOfJoinedMembers()
|
RoomMemberHelper(it, roomId).getNumberOfJoinedMembers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
|||||||
import im.vector.matrix.android.internal.database.model.*
|
import im.vector.matrix.android.internal.database.model.*
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
@ -75,7 +75,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||||||
return@doWithRealm
|
return@doWithRealm
|
||||||
}
|
}
|
||||||
|
|
||||||
val roomMembers = RoomMembers(realm, roomId)
|
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||||
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||||
|
|
||||||
if (roomEntity?.membership == Membership.INVITE) {
|
if (roomEntity?.membership == Membership.INVITE) {
|
||||||
@ -83,7 +83,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||||||
val inviterId = inviteMeEvent?.sender
|
val inviterId = inviteMeEvent?.sender
|
||||||
name = if (inviterId != null) {
|
name = if (inviterId != null) {
|
||||||
activeMembers.where()
|
activeMembers.where()
|
||||||
.equalTo(RoomMemberEntityFields.USER_ID, inviterId)
|
.equalTo(RoomMemberSummaryEntityFields.USER_ID, inviterId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
?.displayName
|
?.displayName
|
||||||
} else {
|
} else {
|
||||||
@ -91,7 +91,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||||||
}
|
}
|
||||||
} else if (roomEntity?.membership == Membership.JOIN) {
|
} else if (roomEntity?.membership == Membership.JOIN) {
|
||||||
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
||||||
val otherMembersSubset: List<RoomMemberEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
||||||
roomSummary.heroes.mapNotNull { userId ->
|
roomSummary.heroes.mapNotNull { userId ->
|
||||||
roomMembers.getLastRoomMember(userId)?.takeIf {
|
roomMembers.getLastRoomMember(userId)?.takeIf {
|
||||||
it.membership == Membership.INVITE || it.membership == Membership.JOIN
|
it.membership == Membership.INVITE || it.membership == Membership.JOIN
|
||||||
@ -99,7 +99,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activeMembers.where()
|
activeMembers.where()
|
||||||
.notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||||
.limit(3)
|
.limit(3)
|
||||||
.findAll()
|
.findAll()
|
||||||
.createSnapshot()
|
.createSnapshot()
|
||||||
@ -123,14 +123,14 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
|||||||
return name ?: roomId
|
return name ?: roomId
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveRoomMemberName(roomMember: RoomMemberEntity?,
|
private fun resolveRoomMemberName(roomMemberSummary: RoomMemberSummaryEntity?,
|
||||||
roomMembers: RoomMembers): String? {
|
roomMemberHelper: RoomMemberHelper): String? {
|
||||||
if (roomMember == null) return null
|
if (roomMemberSummary == null) return null
|
||||||
val isUnique = roomMembers.isUniqueDisplayName(roomMember.displayName)
|
val isUnique = roomMemberHelper.isUniqueDisplayName(roomMemberSummary.displayName)
|
||||||
return if (isUnique) {
|
return if (isUnique) {
|
||||||
roomMember.displayName
|
roomMemberSummary.displayName
|
||||||
} else {
|
} else {
|
||||||
"${roomMember.displayName} (${roomMember.userId})"
|
"${roomMemberSummary.displayName} (${roomMemberSummary.userId})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,18 @@
|
|||||||
package im.vector.matrix.android.internal.session.room.membership
|
package im.vector.matrix.android.internal.session.room.membership
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
|
|
||||||
internal object RoomMemberEntityFactory {
|
internal object RoomMemberEntityFactory {
|
||||||
|
|
||||||
fun create(roomId: String, userId: String, roomMember: RoomMemberContent): RoomMemberEntity {
|
fun create(roomId: String, userId: String, roomMember: RoomMemberContent): RoomMemberSummaryEntity {
|
||||||
val primaryKey = "${roomId}_$userId"
|
val primaryKey = "${roomId}_$userId"
|
||||||
return RoomMemberEntity(
|
return RoomMemberSummaryEntity(
|
||||||
primaryKey = primaryKey,
|
primaryKey = primaryKey,
|
||||||
userId = userId,
|
userId = userId,
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
displayName = roomMember.displayName ?: "",
|
displayName = roomMember.displayName,
|
||||||
avatarUrl = roomMember.avatarUrl ?: ""
|
avatarUrl = roomMember.avatarUrl
|
||||||
).apply {
|
).apply {
|
||||||
membership = roomMember.membership
|
membership = roomMember.membership
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
|||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.internal.database.model.*
|
import im.vector.matrix.android.internal.database.model.*
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
@ -32,8 +32,8 @@ import io.realm.Sort
|
|||||||
* It allows to get the live membership of a user.
|
* It allows to get the live membership of a user.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
internal class RoomMembers(private val realm: Realm,
|
internal class RoomMemberHelper(private val realm: Realm,
|
||||||
private val roomId: String
|
private val roomId: String
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val roomSummary: RoomSummaryEntity? by lazy {
|
private val roomSummary: RoomSummaryEntity? by lazy {
|
||||||
@ -48,8 +48,8 @@ internal class RoomMembers(private val realm: Realm,
|
|||||||
.findFirst()
|
.findFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLastRoomMember(userId: String): RoomMemberEntity? {
|
fun getLastRoomMember(userId: String): RoomMemberSummaryEntity? {
|
||||||
return RoomMemberEntity
|
return RoomMemberSummaryEntity
|
||||||
.where(realm, roomId, userId)
|
.where(realm, roomId, userId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
}
|
}
|
||||||
@ -66,26 +66,26 @@ internal class RoomMembers(private val realm: Realm,
|
|||||||
.size == 1
|
.size == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
fun queryRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
return RoomMemberEntity.where(realm, roomId)
|
return RoomMemberSummaryEntity.where(realm, roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryJoinedRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
fun queryJoinedRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
return queryRoomMembersEvent()
|
return queryRoomMembersEvent()
|
||||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryInvitedRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
fun queryInvitedRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
return queryRoomMembersEvent()
|
return queryRoomMembersEvent()
|
||||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryActiveRoomMembersEvent(): RealmQuery<RoomMemberEntity> {
|
fun queryActiveRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {
|
||||||
return queryRoomMembersEvent()
|
return queryRoomMembersEvent()
|
||||||
.beginGroup()
|
.beginGroup()
|
||||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.INVITE.name)
|
||||||
.or()
|
.or()
|
||||||
.equalTo(RoomMemberEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
.equalTo(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||||
.endGroup()
|
.endGroup()
|
||||||
}
|
}
|
||||||
|
|
@ -16,27 +16,30 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.session.room.state
|
package im.vector.matrix.android.internal.session.room.state
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Transformations
|
||||||
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 com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.room.state.StateService
|
import im.vector.matrix.android.api.session.room.state.StateService
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import im.vector.matrix.android.api.util.toOptional
|
||||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.descending
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
|
|
||||||
internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String,
|
internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String,
|
||||||
@SessionDatabase
|
private val monarchy: Monarchy,
|
||||||
private val realmConfiguration: RealmConfiguration,
|
|
||||||
private val taskExecutor: TaskExecutor,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val sendStateTask: SendStateTask
|
private val sendStateTask: SendStateTask
|
||||||
) : StateService {
|
) : StateService {
|
||||||
@ -47,11 +50,21 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getStateEvent(eventType: String): Event? {
|
override fun getStateEvent(eventType: String): Event? {
|
||||||
return Realm.getInstance(realmConfiguration).use { realm ->
|
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
||||||
EventEntity.where(realm, roomId, eventType).prev()?.asDomain()
|
EventEntity.where(realm, roomId, eventType).prev()?.asDomain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStateEventLive(eventType: String): LiveData<Optional<Event>> {
|
||||||
|
val liveData = monarchy.findAllMappedWithChanges(
|
||||||
|
{ realm -> EventEntity.where(realm, roomId, eventType).descending() },
|
||||||
|
{ it.asDomain() }
|
||||||
|
)
|
||||||
|
return Transformations.map(liveData) { results ->
|
||||||
|
results.firstOrNull().toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>) {
|
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>) {
|
||||||
val params = SendStateTask.Params(roomId,
|
val params = SendStateTask.Params(roomId,
|
||||||
EventType.STATE_ROOM_TOPIC,
|
EventType.STATE_ROOM_TOPIC,
|
||||||
|
@ -28,7 +28,7 @@ import im.vector.matrix.android.internal.database.query.getDirectRooms
|
|||||||
import im.vector.matrix.android.internal.database.query.getOrCreate
|
import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
|
||||||
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.*
|
import im.vector.matrix.android.internal.session.sync.model.accountdata.*
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
||||||
@ -70,7 +70,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
|||||||
var hasUpdate = false
|
var hasUpdate = false
|
||||||
monarchy.doWithRealm { realm ->
|
monarchy.doWithRealm { realm ->
|
||||||
invites.forEach { (roomId, _) ->
|
invites.forEach { (roomId, _) ->
|
||||||
val myUserStateEvent = RoomMembers(realm, roomId).getLastStateEvent(userId)
|
val myUserStateEvent = RoomMemberHelper(realm, roomId).getLastStateEvent(userId)
|
||||||
val inviterId = myUserStateEvent?.sender
|
val inviterId = myUserStateEvent?.sender
|
||||||
val myUserRoomMember: RoomMemberContent? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
val myUserRoomMember: RoomMemberContent? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
||||||
val isDirect = myUserRoomMember?.isDirect
|
val isDirect = myUserRoomMember?.isDirect
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
android:value=".features.home.HomeActivity" />
|
android:value=".features.home.HomeActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".features.debug.DebugMenuActivity" />
|
<activity android:name=".features.debug.DebugMenuActivity" />
|
||||||
<activity android:name=".features.home.createdirect.CreateDirectRoomActivity" />
|
<activity android:name="im.vector.riotx.features.createdirect.CreateDirectRoomActivity" />
|
||||||
<activity android:name=".features.webview.VectorWebViewActivity" />
|
<activity android:name=".features.webview.VectorWebViewActivity" />
|
||||||
<activity android:name=".features.link.LinkHandlerActivity">
|
<activity android:name=".features.link.LinkHandlerActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -106,6 +106,9 @@
|
|||||||
<category android:name="android.intent.category.OPENABLE" />
|
<category android:name="android.intent.category.OPENABLE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".features.roomprofile.RoomProfileActivity" />
|
||||||
|
|
||||||
<activity android:name=".features.signout.hard.SignedOutActivity" />
|
<activity android:name=".features.signout.hard.SignedOutActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.signout.soft.SoftLogoutActivity"
|
android:name=".features.signout.soft.SoftLogoutActivity"
|
||||||
@ -122,6 +125,14 @@
|
|||||||
<data android:host="matrix.to" />
|
<data android:host="matrix.to" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".features.roommemberprofile.RoomMemberProfileActivity"
|
||||||
|
android:parentActivityName=".features.home.HomeActivity">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".features.home.HomeActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
<!-- Services -->
|
<!-- Services -->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
@ -25,8 +25,8 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
|
|||||||
import im.vector.matrix.android.api.session.room.roomSummaryQueryParams
|
import im.vector.matrix.android.api.session.room.roomSummaryQueryParams
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.riotx.features.home.HomeRoomListDataSource
|
import im.vector.riotx.features.home.HomeRoomListDataSource
|
||||||
import im.vector.riotx.features.home.group.ALL_COMMUNITIES_GROUP_ID
|
import im.vector.riotx.features.grouplist.ALL_COMMUNITIES_GROUP_ID
|
||||||
import im.vector.riotx.features.home.group.SelectedGroupDataSource
|
import im.vector.riotx.features.grouplist.SelectedGroupDataSource
|
||||||
import im.vector.riotx.features.home.room.list.ChronologicalRoomComparator
|
import im.vector.riotx.features.home.room.list.ChronologicalRoomComparator
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.core.animations
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
abstract class AppBarStateChangeListener : OnOffsetChangedListener {
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
EXPANDED, COLLAPSED, IDLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private var currentState = State.IDLE
|
||||||
|
|
||||||
|
override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
|
||||||
|
currentState = if (i == 0) {
|
||||||
|
if (currentState != State.EXPANDED) {
|
||||||
|
onStateChanged(appBarLayout, State.EXPANDED)
|
||||||
|
}
|
||||||
|
State.EXPANDED
|
||||||
|
} else if (abs(i) >= appBarLayout.totalScrollRange) {
|
||||||
|
if (currentState != State.COLLAPSED) {
|
||||||
|
onStateChanged(appBarLayout, State.COLLAPSED)
|
||||||
|
}
|
||||||
|
State.COLLAPSED
|
||||||
|
} else {
|
||||||
|
if (currentState != State.IDLE) {
|
||||||
|
onStateChanged(appBarLayout, State.IDLE)
|
||||||
|
}
|
||||||
|
State.IDLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun onStateChanged(appBarLayout: AppBarLayout, state: State)
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.core.animations
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
|
||||||
|
class MatrixItemAppBarStateChangeListener(private val headerView: View, private val toolbarViews: List<View>) : AppBarStateChangeListener() {
|
||||||
|
|
||||||
|
override fun onStateChanged(appBarLayout: AppBarLayout, state: State) {
|
||||||
|
if (state == State.COLLAPSED) {
|
||||||
|
headerView.visibility = View.INVISIBLE
|
||||||
|
toolbarViews.forEach {
|
||||||
|
it.animate().alpha(1f).duration = 150
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
headerView.visibility = View.VISIBLE
|
||||||
|
toolbarViews.forEach {
|
||||||
|
it.animate().alpha(0f).duration = 150
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* 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.riotx.core.animations.behavior
|
||||||
|
|
||||||
|
import android.animation.ArgbEvaluator
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
private const val UNSPECIFIED_INT = Integer.MAX_VALUE
|
||||||
|
private val UNSPECIFIED_FLOAT = Float.MAX_VALUE
|
||||||
|
private const val DEPEND_TYPE_HEIGHT = 0
|
||||||
|
private const val DEPEND_TYPE_WIDTH = 1
|
||||||
|
private const val DEPEND_TYPE_X = 2
|
||||||
|
private const val DEPEND_TYPE_Y = 3
|
||||||
|
|
||||||
|
class PercentViewBehavior<V : View>(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<V>(context, attrs) {
|
||||||
|
|
||||||
|
private var dependType: Int = 0
|
||||||
|
private var dependViewId: Int = 0
|
||||||
|
private var dependTarget: Int = 0
|
||||||
|
private var dependStartX: Int = 0
|
||||||
|
private var dependStartY: Int = 0
|
||||||
|
private var dependStartWidth: Int = 0
|
||||||
|
private var dependStartHeight: Int = 0
|
||||||
|
|
||||||
|
private var startX: Int = 0
|
||||||
|
private var startY: Int = 0
|
||||||
|
private var startWidth: Int = 0
|
||||||
|
private var startHeight: Int = 0
|
||||||
|
private var startBackgroundColor: Int = 0
|
||||||
|
private var startAlpha: Float = 0f
|
||||||
|
private var startRotateX: Float = 0f
|
||||||
|
private var startRotateY: Float = 0f
|
||||||
|
|
||||||
|
private var targetX: Int = 0
|
||||||
|
private var targetY: Int = 0
|
||||||
|
private var targetWidth: Int = 0
|
||||||
|
private var targetHeight: Int = 0
|
||||||
|
private var targetBackgroundColor: Int = 0
|
||||||
|
private var targetAlpha: Float = 0f
|
||||||
|
private var targetRotateX: Float = 0f
|
||||||
|
private var targetRotateY: Float = 0f
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the values prepared to be use
|
||||||
|
*/
|
||||||
|
private var isPrepared: Boolean = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
val a = context.obtainStyledAttributes(attrs, R.styleable.PercentViewBehavior)
|
||||||
|
dependViewId = a.getResourceId(R.styleable.PercentViewBehavior_behavior_dependsOn, 0)
|
||||||
|
dependType = a.getInt(R.styleable.PercentViewBehavior_behavior_dependType, DEPEND_TYPE_WIDTH)
|
||||||
|
dependTarget = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_dependTarget, UNSPECIFIED_INT)
|
||||||
|
targetX = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetX, UNSPECIFIED_INT)
|
||||||
|
targetY = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetY, UNSPECIFIED_INT)
|
||||||
|
targetWidth = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetWidth, UNSPECIFIED_INT)
|
||||||
|
targetHeight = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetHeight, UNSPECIFIED_INT)
|
||||||
|
targetBackgroundColor = a.getColor(R.styleable.PercentViewBehavior_behavior_targetBackgroundColor, UNSPECIFIED_INT)
|
||||||
|
targetAlpha = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetAlpha, UNSPECIFIED_FLOAT)
|
||||||
|
targetRotateX = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateX, UNSPECIFIED_FLOAT)
|
||||||
|
targetRotateY = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateY, UNSPECIFIED_FLOAT)
|
||||||
|
a.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepare(parent: CoordinatorLayout, child: View, dependency: View) {
|
||||||
|
dependStartX = dependency.x.toInt()
|
||||||
|
dependStartY = dependency.y.toInt()
|
||||||
|
dependStartWidth = dependency.width
|
||||||
|
dependStartHeight = dependency.height
|
||||||
|
startX = child.x.toInt()
|
||||||
|
startY = child.y.toInt()
|
||||||
|
startWidth = child.width
|
||||||
|
startHeight = child.height
|
||||||
|
startAlpha = child.alpha
|
||||||
|
startRotateX = child.rotationX
|
||||||
|
startRotateY = child.rotationY
|
||||||
|
|
||||||
|
// only set the start background color when the background is color drawable
|
||||||
|
val background = child.background
|
||||||
|
if (background is ColorDrawable) {
|
||||||
|
startBackgroundColor = background.color
|
||||||
|
}
|
||||||
|
|
||||||
|
// if parent fitsSystemWindows is true, add status bar height to target y if specified
|
||||||
|
if (parent.fitsSystemWindows && targetY != UNSPECIFIED_INT) {
|
||||||
|
var result = 0
|
||||||
|
val resources = parent.context.resources
|
||||||
|
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
|
||||||
|
if (resourceId > 0) {
|
||||||
|
result = resources.getDimensionPixelSize(resourceId)
|
||||||
|
}
|
||||||
|
targetY += result
|
||||||
|
}
|
||||||
|
isPrepared = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
|
||||||
|
return dependency.id == dependViewId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDependentViewChanged(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
|
||||||
|
// first time, prepare values before continue
|
||||||
|
if (!isPrepared) {
|
||||||
|
prepare(parent, child, dependency)
|
||||||
|
}
|
||||||
|
updateView(child, dependency)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
|
||||||
|
val bool = super.onLayoutChild(parent, child, layoutDirection)
|
||||||
|
if (isPrepared) {
|
||||||
|
updateView(child, parent.getDependencies(child)[0])
|
||||||
|
}
|
||||||
|
return bool
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the child view from the dependency states
|
||||||
|
*
|
||||||
|
* @param child child view
|
||||||
|
* @param dependency dependency view
|
||||||
|
*/
|
||||||
|
private fun updateView(child: V, dependency: View) {
|
||||||
|
var percent = 0f
|
||||||
|
var start = 0f
|
||||||
|
var current = 0f
|
||||||
|
var end = UNSPECIFIED_INT.toFloat()
|
||||||
|
when (dependType) {
|
||||||
|
DEPEND_TYPE_WIDTH -> {
|
||||||
|
start = dependStartWidth.toFloat()
|
||||||
|
current = dependency.width.toFloat()
|
||||||
|
end = dependTarget.toFloat()
|
||||||
|
}
|
||||||
|
DEPEND_TYPE_HEIGHT -> {
|
||||||
|
start = dependStartHeight.toFloat()
|
||||||
|
current = dependency.height.toFloat()
|
||||||
|
end = dependTarget.toFloat()
|
||||||
|
}
|
||||||
|
DEPEND_TYPE_X -> {
|
||||||
|
start = dependStartX.toFloat()
|
||||||
|
current = dependency.x
|
||||||
|
end = dependTarget.toFloat()
|
||||||
|
}
|
||||||
|
DEPEND_TYPE_Y -> {
|
||||||
|
start = dependStartY.toFloat()
|
||||||
|
current = dependency.y
|
||||||
|
end = dependTarget.toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to define target value according to the depend type, if not then skip
|
||||||
|
if (end != UNSPECIFIED_INT.toFloat()) {
|
||||||
|
percent = abs(current - start) / abs(end - start)
|
||||||
|
}
|
||||||
|
updateViewWithPercent(child, if (percent > 1f) 1f else percent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateViewWithPercent(child: View, percent: Float) {
|
||||||
|
var newX = if (targetX == UNSPECIFIED_INT) 0f else (targetX - startX) * percent
|
||||||
|
var newY = if (targetY == UNSPECIFIED_INT) 0f else (targetY - startY) * percent
|
||||||
|
|
||||||
|
// set scale
|
||||||
|
if (targetWidth != UNSPECIFIED_INT) {
|
||||||
|
val newWidth = startWidth + (targetWidth - startWidth) * percent
|
||||||
|
child.scaleX = newWidth / startWidth
|
||||||
|
newX -= (startWidth - newWidth) / 2
|
||||||
|
}
|
||||||
|
if (targetHeight != UNSPECIFIED_INT) {
|
||||||
|
val newHeight = startHeight + (targetHeight - startHeight) * percent
|
||||||
|
child.scaleY = newHeight / startHeight
|
||||||
|
newY -= (startHeight - newHeight) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// set new position
|
||||||
|
child.translationX = newX
|
||||||
|
child.translationY = newY
|
||||||
|
|
||||||
|
// set alpha
|
||||||
|
if (targetAlpha != UNSPECIFIED_FLOAT) {
|
||||||
|
child.alpha = startAlpha + (targetAlpha - startAlpha) * percent
|
||||||
|
}
|
||||||
|
|
||||||
|
// set background color
|
||||||
|
if (targetBackgroundColor != UNSPECIFIED_INT && startBackgroundColor != 0) {
|
||||||
|
val evaluator = ArgbEvaluator()
|
||||||
|
val color = evaluator.evaluate(percent, startBackgroundColor, targetBackgroundColor) as Int
|
||||||
|
child.setBackgroundColor(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set rotation
|
||||||
|
if (targetRotateX != UNSPECIFIED_FLOAT) {
|
||||||
|
child.rotationX = startRotateX + (targetRotateX - startRotateX) * percent
|
||||||
|
}
|
||||||
|
if (targetRotateY != UNSPECIFIED_FLOAT) {
|
||||||
|
child.rotationY = startRotateY + (targetRotateY - startRotateY) * percent
|
||||||
|
}
|
||||||
|
|
||||||
|
child.requestLayout()
|
||||||
|
}
|
||||||
|
}
|
@ -30,20 +30,23 @@ import im.vector.riotx.features.crypto.verification.SASVerificationVerifiedFragm
|
|||||||
import im.vector.riotx.features.home.HomeDetailFragment
|
import im.vector.riotx.features.home.HomeDetailFragment
|
||||||
import im.vector.riotx.features.home.HomeDrawerFragment
|
import im.vector.riotx.features.home.HomeDrawerFragment
|
||||||
import im.vector.riotx.features.home.LoadingFragment
|
import im.vector.riotx.features.home.LoadingFragment
|
||||||
import im.vector.riotx.features.home.createdirect.CreateDirectRoomDirectoryUsersFragment
|
import im.vector.riotx.features.createdirect.CreateDirectRoomDirectoryUsersFragment
|
||||||
import im.vector.riotx.features.home.createdirect.CreateDirectRoomKnownUsersFragment
|
import im.vector.riotx.features.createdirect.CreateDirectRoomKnownUsersFragment
|
||||||
import im.vector.riotx.features.home.group.GroupListFragment
|
import im.vector.riotx.features.grouplist.GroupListFragment
|
||||||
import im.vector.riotx.features.home.room.breadcrumbs.BreadcrumbsFragment
|
import im.vector.riotx.features.home.room.breadcrumbs.BreadcrumbsFragment
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailFragment
|
import im.vector.riotx.features.home.room.detail.RoomDetailFragment
|
||||||
import im.vector.riotx.features.home.room.list.RoomListFragment
|
import im.vector.riotx.features.home.room.list.RoomListFragment
|
||||||
import im.vector.riotx.features.login.*
|
import im.vector.riotx.features.login.*
|
||||||
import im.vector.riotx.features.login.terms.LoginTermsFragment
|
import im.vector.riotx.features.login.terms.LoginTermsFragment
|
||||||
|
import im.vector.riotx.features.roommemberprofile.RoomMemberProfileFragment
|
||||||
import im.vector.riotx.features.reactions.EmojiChooserFragment
|
import im.vector.riotx.features.reactions.EmojiChooserFragment
|
||||||
import im.vector.riotx.features.reactions.EmojiSearchResultFragment
|
import im.vector.riotx.features.reactions.EmojiSearchResultFragment
|
||||||
import im.vector.riotx.features.roomdirectory.PublicRoomsFragment
|
import im.vector.riotx.features.roomdirectory.PublicRoomsFragment
|
||||||
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment
|
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment
|
||||||
import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment
|
import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment
|
||||||
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
|
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
|
||||||
|
import im.vector.riotx.features.roomprofile.RoomProfileFragment
|
||||||
|
import im.vector.riotx.features.roomprofile.members.RoomMemberListFragment
|
||||||
import im.vector.riotx.features.settings.*
|
import im.vector.riotx.features.settings.*
|
||||||
import im.vector.riotx.features.settings.devices.VectorSettingsDevicesFragment
|
import im.vector.riotx.features.settings.devices.VectorSettingsDevicesFragment
|
||||||
import im.vector.riotx.features.settings.ignored.VectorSettingsIgnoredUsersFragment
|
import im.vector.riotx.features.settings.ignored.VectorSettingsIgnoredUsersFragment
|
||||||
@ -259,6 +262,21 @@ interface FragmentModule {
|
|||||||
@FragmentKey(PublicRoomsFragment::class)
|
@FragmentKey(PublicRoomsFragment::class)
|
||||||
fun bindPublicRoomsFragment(fragment: PublicRoomsFragment): Fragment
|
fun bindPublicRoomsFragment(fragment: PublicRoomsFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(RoomProfileFragment::class)
|
||||||
|
fun bindRoomProfileFragment(fragment: RoomProfileFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(RoomMemberListFragment::class)
|
||||||
|
fun bindRoomMemberListFragment(fragment: RoomMemberListFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(RoomMemberProfileFragment::class)
|
||||||
|
fun bindRoomMemberProfileFragment(fragment: RoomMemberProfileFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(BreadcrumbsFragment::class)
|
@FragmentKey(BreadcrumbsFragment::class)
|
||||||
|
@ -27,7 +27,7 @@ import im.vector.riotx.features.MainActivity
|
|||||||
import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
||||||
import im.vector.riotx.features.home.HomeActivity
|
import im.vector.riotx.features.home.HomeActivity
|
||||||
import im.vector.riotx.features.home.HomeModule
|
import im.vector.riotx.features.home.HomeModule
|
||||||
import im.vector.riotx.features.home.createdirect.CreateDirectRoomActivity
|
import im.vector.riotx.features.createdirect.CreateDirectRoomActivity
|
||||||
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
||||||
|
@ -36,7 +36,7 @@ import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler
|
|||||||
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
|
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.HomeRoomListDataSource
|
import im.vector.riotx.features.home.HomeRoomListDataSource
|
||||||
import im.vector.riotx.features.home.group.SelectedGroupDataSource
|
import im.vector.riotx.features.grouplist.SelectedGroupDataSource
|
||||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import im.vector.riotx.features.html.VectorHtmlCompressor
|
import im.vector.riotx.features.html.VectorHtmlCompressor
|
||||||
import im.vector.riotx.features.navigation.Navigator
|
import im.vector.riotx.features.navigation.Navigator
|
||||||
|
@ -22,19 +22,20 @@ import dagger.Binds
|
|||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.multibindings.IntoMap
|
import dagger.multibindings.IntoMap
|
||||||
import im.vector.riotx.core.platform.ConfigurationViewModel
|
import im.vector.riotx.core.platform.ConfigurationViewModel
|
||||||
|
import im.vector.riotx.features.createdirect.CreateDirectRoomSharedActionViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyViewModel
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
|
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
|
||||||
import im.vector.riotx.features.crypto.verification.SasVerificationViewModel
|
import im.vector.riotx.features.crypto.verification.SasVerificationViewModel
|
||||||
import im.vector.riotx.features.home.HomeSharedActionViewModel
|
import im.vector.riotx.features.home.HomeSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.createdirect.CreateDirectRoomSharedActionViewModel
|
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailSharedActionViewModel
|
import im.vector.riotx.features.home.room.detail.RoomDetailSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||||
import im.vector.riotx.features.login.LoginSharedActionViewModel
|
import im.vector.riotx.features.login.LoginSharedActionViewModel
|
||||||
import im.vector.riotx.features.reactions.EmojiChooserViewModel
|
import im.vector.riotx.features.reactions.EmojiChooserViewModel
|
||||||
import im.vector.riotx.features.roomdirectory.RoomDirectorySharedActionViewModel
|
import im.vector.riotx.features.roomdirectory.RoomDirectorySharedActionViewModel
|
||||||
|
import im.vector.riotx.features.roomprofile.RoomProfileSharedActionViewModel
|
||||||
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@ -124,4 +125,9 @@ interface ViewModelModule {
|
|||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(RoomDetailSharedActionViewModel::class)
|
@ViewModelKey(RoomDetailSharedActionViewModel::class)
|
||||||
fun bindRoomDetailSharedActionViewModel(viewModel: RoomDetailSharedActionViewModel): ViewModel
|
fun bindRoomDetailSharedActionViewModel(viewModel: RoomDetailSharedActionViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(RoomProfileSharedActionViewModel::class)
|
||||||
|
fun bindRoomProfileSharedActionViewModel(viewModel: RoomProfileSharedActionViewModel): ViewModel
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,14 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.core.epoxy.bottomsheet
|
package im.vector.riotx.core.epoxy
|
||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
|
||||||
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_bottom_sheet_divider)
|
@EpoxyModelClass(layout = R.layout.item_divider)
|
||||||
abstract class BottomSheetSeparatorItem : VectorEpoxyModel<BottomSheetSeparatorItem.Holder>() {
|
abstract class DividerItem : VectorEpoxyModel<DividerItem.Holder>() {
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder()
|
class Holder : VectorEpoxyHolder()
|
||||||
}
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.riotx.core.epoxy.profiles
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.riotx.core.extensions.setTextOrHide
|
||||||
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
|
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_profile_action)
|
||||||
|
abstract class ProfileActionItem : VectorEpoxyModel<ProfileActionItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var title: String
|
||||||
|
@EpoxyAttribute
|
||||||
|
var subtitle: String? = null
|
||||||
|
@EpoxyAttribute
|
||||||
|
var iconRes: Int = 0
|
||||||
|
@EpoxyAttribute
|
||||||
|
var editable: Boolean = true
|
||||||
|
@EpoxyAttribute
|
||||||
|
var destructive: Boolean = false
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var listener: View.OnClickListener
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.view.setOnClickListener(listener)
|
||||||
|
holder.editable.isVisible = editable
|
||||||
|
holder.title.text = title
|
||||||
|
val tintColor = if (destructive) {
|
||||||
|
ContextCompat.getColor(holder.view.context, R.color.riotx_notice)
|
||||||
|
} else {
|
||||||
|
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary)
|
||||||
|
}
|
||||||
|
holder.title.setTextColor(tintColor)
|
||||||
|
holder.subtitle.setTextOrHide(subtitle)
|
||||||
|
if (iconRes != 0) {
|
||||||
|
holder.icon.setImageResource(iconRes)
|
||||||
|
holder.icon.isVisible = true
|
||||||
|
} else {
|
||||||
|
holder.icon.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val icon by bind<ImageView>(R.id.actionIcon)
|
||||||
|
val title by bind<TextView>(R.id.actionTitle)
|
||||||
|
val subtitle by bind<TextView>(R.id.actionSubtitle)
|
||||||
|
val editable by bind<ImageView>(R.id.actionEditable)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.core.epoxy.profiles
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import com.airbnb.epoxy.EpoxyController
|
||||||
|
import im.vector.riotx.core.epoxy.DividerItem_
|
||||||
|
|
||||||
|
fun EpoxyController.buildProfileSection(title: String) {
|
||||||
|
profileSectionItem {
|
||||||
|
id("section_$title")
|
||||||
|
title(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun EpoxyController.buildProfileAction(
|
||||||
|
id: String,
|
||||||
|
title: String,
|
||||||
|
subtitle: String? = null,
|
||||||
|
editable: Boolean = true,
|
||||||
|
@DrawableRes icon: Int = 0,
|
||||||
|
destructive: Boolean = false,
|
||||||
|
divider: Boolean = true,
|
||||||
|
action: () -> Unit
|
||||||
|
) {
|
||||||
|
profileActionItem {
|
||||||
|
iconRes(icon)
|
||||||
|
id("action_$id")
|
||||||
|
subtitle(subtitle)
|
||||||
|
editable(editable)
|
||||||
|
destructive(destructive)
|
||||||
|
title(title)
|
||||||
|
listener { _ ->
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerItem_()
|
||||||
|
.id("divider_$title")
|
||||||
|
.addIf(divider, this)
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.core.epoxy.profiles
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.matrix.android.api.util.MatrixItem
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.riotx.core.extensions.setTextOrHide
|
||||||
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
|
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_profile_matrix_item)
|
||||||
|
abstract class ProfileMatrixItem : VectorEpoxyModel<ProfileMatrixItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||||
|
@EpoxyAttribute var clickListener: View.OnClickListener? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
val bestName = matrixItem.getBestName()
|
||||||
|
val matrixId = matrixItem.id.takeIf { it != bestName }
|
||||||
|
holder.view.setOnClickListener(clickListener)
|
||||||
|
holder.titleView.text = bestName
|
||||||
|
holder.subtitleView.setTextOrHide(matrixId)
|
||||||
|
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val titleView by bind<TextView>(R.id.matrixItemTitle)
|
||||||
|
val subtitleView by bind<TextView>(R.id.matrixItemSubtitle)
|
||||||
|
val avatarImageView by bind<ImageView>(R.id.matrixItemAvatar)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.riotx.core.epoxy.profiles
|
||||||
|
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
|
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_profile_section)
|
||||||
|
abstract class ProfileSectionItem: VectorEpoxyModel<ProfileSectionItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var title: String
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.sectionView.text = title
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val sectionView by bind<TextView>(R.id.itemProfileSectionView)
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||||||
data class Error(val message: CharSequence? = null) : State()
|
data class Error(val message: CharSequence? = null) : State()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var eventCallback: EventCallback? = null
|
var eventCallback: EventCallback? = null
|
||||||
|
|
||||||
var contentView: View? = null
|
var contentView: View? = null
|
||||||
|
|
||||||
|
@ -23,11 +23,18 @@ import android.os.Parcelable
|
|||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.*
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.annotation.MainThread
|
||||||
|
import androidx.annotation.MenuRes
|
||||||
|
import androidx.annotation.Nullable
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentFactory
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
@ -41,7 +48,12 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import im.vector.matrix.android.api.failure.GlobalError
|
import im.vector.matrix.android.api.failure.GlobalError
|
||||||
import im.vector.riotx.BuildConfig
|
import im.vector.riotx.BuildConfig
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.*
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
|
import im.vector.riotx.core.di.DaggerScreenComponent
|
||||||
|
import im.vector.riotx.core.di.HasScreenInjector
|
||||||
|
import im.vector.riotx.core.di.HasVectorInjector
|
||||||
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
|
import im.vector.riotx.core.di.VectorComponent
|
||||||
import im.vector.riotx.core.dialogs.DialogLocker
|
import im.vector.riotx.core.dialogs.DialogLocker
|
||||||
import im.vector.riotx.core.extensions.observeEvent
|
import im.vector.riotx.core.extensions.observeEvent
|
||||||
import im.vector.riotx.core.utils.toast
|
import im.vector.riotx.core.utils.toast
|
||||||
@ -92,6 +104,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
lateinit var rageShake: RageShake
|
lateinit var rageShake: RageShake
|
||||||
private set
|
private set
|
||||||
protected lateinit var navigator: Navigator
|
protected lateinit var navigator: Navigator
|
||||||
|
private lateinit var fragmentFactory: FragmentFactory
|
||||||
private lateinit var activeSessionHolder: ActiveSessionHolder
|
private lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
private lateinit var vectorPreferences: VectorPreferences
|
private lateinit var vectorPreferences: VectorPreferences
|
||||||
|
|
||||||
@ -145,7 +158,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
}
|
}
|
||||||
Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
|
Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
|
||||||
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
||||||
supportFragmentManager.fragmentFactory = screenComponent.fragmentFactory()
|
fragmentFactory = screenComponent.fragmentFactory()
|
||||||
|
supportFragmentManager.fragmentFactory = fragmentFactory
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
viewModelFactory = screenComponent.viewModelFactory()
|
viewModelFactory = screenComponent.viewModelFactory()
|
||||||
configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java)
|
configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java)
|
||||||
@ -196,7 +210,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
handleInvalidToken(globalError)
|
handleInvalidToken(globalError)
|
||||||
is GlobalError.ConsentNotGivenError ->
|
is GlobalError.ConsentNotGivenError ->
|
||||||
consentNotGivenHelper.displayDialog(globalError.consentUri,
|
consentNotGivenHelper.displayDialog(globalError.consentUri,
|
||||||
activeSessionHolder.getActiveSession().sessionParams.homeServerConnectionConfig.homeServerUri.host ?: "")
|
activeSessionHolder.getActiveSession().sessionParams.homeServerConnectionConfig.homeServerUri.host
|
||||||
|
?: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,11 +224,11 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
mainActivityStarted = true
|
mainActivityStarted = true
|
||||||
|
|
||||||
MainActivity.restartApp(this,
|
MainActivity.restartApp(this,
|
||||||
MainActivityArgs(
|
MainActivityArgs(
|
||||||
clearCredentials = !globalError.softLogout,
|
clearCredentials = !globalError.softLogout,
|
||||||
isUserLoggedOut = true,
|
isUserLoggedOut = true,
|
||||||
isSoftLogout = globalError.softLogout
|
isSoftLogout = globalError.softLogout
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +291,12 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
|
|
||||||
protected open fun injectWith(injector: ScreenComponent) = Unit
|
protected open fun injectWith(injector: ScreenComponent) = Unit
|
||||||
|
|
||||||
|
protected fun createFragment(fragmentClass: Class<out Fragment>, args: Bundle?): Fragment {
|
||||||
|
return fragmentFactory.instantiate(classLoader, fragmentClass.name).apply {
|
||||||
|
arguments = args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* PRIVATE METHODS
|
* PRIVATE METHODS
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
@ -372,12 +393,10 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
*/
|
*/
|
||||||
protected fun configureToolbar(toolbar: Toolbar, displayBack: Boolean = true) {
|
protected fun configureToolbar(toolbar: Toolbar, displayBack: Boolean = true) {
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
|
supportActionBar?.let {
|
||||||
if (displayBack) {
|
it.setDisplayShowHomeEnabled(displayBack)
|
||||||
supportActionBar?.let {
|
it.setDisplayHomeAsUpEnabled(displayBack)
|
||||||
it.setDisplayShowHomeEnabled(true)
|
it.title = null
|
||||||
it.setDisplayHomeAsUpEnabled(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package im.vector.riotx.core.platform
|
package im.vector.riotx.core.platform
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
@ -59,6 +62,8 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
|
|||||||
protected lateinit var navigator: Navigator
|
protected lateinit var navigator: Navigator
|
||||||
protected lateinit var errorFormatter: ErrorFormatter
|
protected lateinit var errorFormatter: ErrorFormatter
|
||||||
|
|
||||||
|
private var progress: ProgressDialog? = null
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* View model
|
* View model
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
@ -96,6 +101,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
final override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
Timber.i("onCreateView Fragment ${this.javaClass.simpleName}")
|
||||||
return inflater.inflate(getLayoutResId(), container, false)
|
return inflater.inflate(getLayoutResId(), container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +123,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
|
|||||||
@CallSuper
|
@CallSuper
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
Timber.i("onDestroyView Fragment ${this.javaClass.simpleName}")
|
||||||
mUnBinder?.unbind()
|
mUnBinder?.unbind()
|
||||||
mUnBinder = null
|
mUnBinder = null
|
||||||
uiDisposables.clear()
|
uiDisposables.clear()
|
||||||
@ -175,6 +182,19 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun showLoadingDialog(message: CharSequence, cancelable: Boolean = false) {
|
||||||
|
progress = ProgressDialog(requireContext()).apply {
|
||||||
|
setCancelable(cancelable)
|
||||||
|
setMessage(message)
|
||||||
|
setProgressStyle(ProgressDialog.STYLE_SPINNER)
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun dismissLoadingDialog() {
|
||||||
|
progress?.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* Toolbar
|
* Toolbar
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
@ -19,7 +19,7 @@ package im.vector.riotx.core.utils
|
|||||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay2.PublishRelay
|
import com.jakewharton.rxrelay2.PublishRelay
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
|
||||||
interface DataSource<T> {
|
interface DataSource<T> {
|
||||||
fun observe(): Observable<T>
|
fun observe(): Observable<T>
|
||||||
@ -37,7 +37,7 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
|
|||||||
private val behaviorRelay = createRelay()
|
private val behaviorRelay = createRelay()
|
||||||
|
|
||||||
override fun observe(): Observable<T> {
|
override fun observe(): Observable<T> {
|
||||||
return behaviorRelay.hide().observeOn(Schedulers.computation())
|
return behaviorRelay.hide().observeOn(AndroidSchedulers.mainThread())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun post(value: T) {
|
override fun post(value: T) {
|
||||||
@ -61,7 +61,7 @@ open class PublishDataSource<T> : MutableDataSource<T> {
|
|||||||
private val publishRelay = PublishRelay.create<T>()
|
private val publishRelay = PublishRelay.create<T>()
|
||||||
|
|
||||||
override fun observe(): Observable<T> {
|
override fun observe(): Observable<T> {
|
||||||
return publishRelay.hide()
|
return publishRelay.hide().observeOn(AndroidSchedulers.mainThread())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun post(value: T) {
|
override fun post(value: T) {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home
|
package im.vector.riotx.core.utils
|
||||||
|
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
@ -17,20 +17,20 @@
|
|||||||
package im.vector.riotx.features.autocomplete.member
|
package im.vector.riotx.features.autocomplete.member
|
||||||
|
|
||||||
import com.airbnb.epoxy.TypedEpoxyController
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.util.toMatrixItem
|
import im.vector.matrix.android.api.util.toMatrixItem
|
||||||
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
||||||
import im.vector.riotx.features.autocomplete.autocompleteMatrixItem
|
import im.vector.riotx.features.autocomplete.autocompleteMatrixItem
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<List<RoomMember>>() {
|
class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<List<RoomMemberSummary>>() {
|
||||||
|
|
||||||
var listener: AutocompleteClickListener<RoomMember>? = null
|
var listener: AutocompleteClickListener<RoomMemberSummary>? = null
|
||||||
|
|
||||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
|
||||||
override fun buildModels(data: List<RoomMember>?) {
|
override fun buildModels(data: List<RoomMemberSummary>?) {
|
||||||
if (data.isNullOrEmpty()) {
|
if (data.isNullOrEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,14 @@ import im.vector.matrix.android.api.query.QueryStringValue
|
|||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.room.members.roomMemberQueryParams
|
import im.vector.matrix.android.api.session.room.members.roomMemberQueryParams
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
import im.vector.riotx.features.autocomplete.AutocompleteClickListener
|
||||||
|
|
||||||
class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
||||||
@Assisted val roomId: String,
|
@Assisted val roomId: String,
|
||||||
private val session: Session,
|
private val session: Session,
|
||||||
private val controller: AutocompleteMemberController
|
private val controller: AutocompleteMemberController
|
||||||
) : RecyclerViewPresenter<RoomMember>(context), AutocompleteClickListener<RoomMember> {
|
) : RecyclerViewPresenter<RoomMemberSummary>(context), AutocompleteClickListener<RoomMemberSummary> {
|
||||||
|
|
||||||
private val room = session.getRoom(roomId)!!
|
private val room = session.getRoom(roomId)!!
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
|||||||
return controller.adapter
|
return controller.adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(t: RoomMember) {
|
override fun onItemClick(t: RoomMemberSummary) {
|
||||||
dispatchClick(t)
|
dispatchClick(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
import im.vector.riotx.core.platform.VectorViewModelAction
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import im.vector.riotx.core.platform.VectorSharedAction
|
import im.vector.riotx.core.platform.VectorSharedAction
|
||||||
|
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import im.vector.riotx.core.platform.VectorSharedActionViewModel
|
import im.vector.riotx.core.platform.VectorSharedActionViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import androidx.paging.PagedList
|
import androidx.paging.PagedList
|
||||||
import arrow.core.Option
|
import arrow.core.Option
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.createdirect
|
package im.vector.riotx.features.createdirect
|
||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import com.airbnb.epoxy.paging.PagedListEpoxyController
|
import com.airbnb.epoxy.paging.PagedListEpoxyController
|
@ -12,9 +12,10 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
import im.vector.riotx.core.platform.VectorViewModelAction
|
@ -12,9 +12,10 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
@ -12,9 +12,10 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
@ -12,9 +12,10 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
@ -12,9 +12,10 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.features.home.group
|
package im.vector.riotx.features.grouplist
|
||||||
|
|
||||||
import arrow.core.Option
|
import arrow.core.Option
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
@ -32,6 +32,7 @@ import im.vector.riotx.core.di.ActiveSessionHolder
|
|||||||
import im.vector.riotx.core.glide.GlideApp
|
import im.vector.riotx.core.glide.GlideApp
|
||||||
import im.vector.riotx.core.glide.GlideRequest
|
import im.vector.riotx.core.glide.GlideRequest
|
||||||
import im.vector.riotx.core.glide.GlideRequests
|
import im.vector.riotx.core.glide.GlideRequests
|
||||||
|
import im.vector.riotx.core.utils.getColorFromUserId
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,7 @@ import im.vector.matrix.rx.rx
|
|||||||
import im.vector.riotx.core.di.HasScreenInjector
|
import im.vector.riotx.core.di.HasScreenInjector
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.group.SelectedGroupDataSource
|
import im.vector.riotx.features.grouplist.SelectedGroupDataSource
|
||||||
import im.vector.riotx.features.ui.UiStateRepository
|
import im.vector.riotx.features.ui.UiStateRepository
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import im.vector.riotx.R
|
|||||||
import im.vector.riotx.core.extensions.observeK
|
import im.vector.riotx.core.extensions.observeK
|
||||||
import im.vector.riotx.core.extensions.replaceChildFragment
|
import im.vector.riotx.core.extensions.replaceChildFragment
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.features.home.group.GroupListFragment
|
import im.vector.riotx.features.grouplist.GroupListFragment
|
||||||
import kotlinx.android.synthetic.main.fragment_home_drawer.*
|
import kotlinx.android.synthetic.main.fragment_home_drawer.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import com.otaliastudios.autocomplete.CharPolicy
|
|||||||
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.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.util.MatrixItem
|
import im.vector.matrix.android.api.util.MatrixItem
|
||||||
import im.vector.matrix.android.api.util.toMatrixItem
|
import im.vector.matrix.android.api.util.toMatrixItem
|
||||||
@ -108,13 +108,13 @@ class AutoCompleter @AssistedInject constructor(
|
|||||||
|
|
||||||
private fun setupMembers(backgroundDrawable: ColorDrawable, editText: EditText) {
|
private fun setupMembers(backgroundDrawable: ColorDrawable, editText: EditText) {
|
||||||
val autocompleteMemberPresenter = autocompleteMemberPresenterFactory.create(roomId)
|
val autocompleteMemberPresenter = autocompleteMemberPresenterFactory.create(roomId)
|
||||||
Autocomplete.on<RoomMember>(editText)
|
Autocomplete.on<RoomMemberSummary>(editText)
|
||||||
.with(CharPolicy('@', true))
|
.with(CharPolicy('@', true))
|
||||||
.with(autocompleteMemberPresenter)
|
.with(autocompleteMemberPresenter)
|
||||||
.with(ELEVATION)
|
.with(ELEVATION)
|
||||||
.with(backgroundDrawable)
|
.with(backgroundDrawable)
|
||||||
.with(object : AutocompleteCallback<RoomMember> {
|
.with(object : AutocompleteCallback<RoomMemberSummary> {
|
||||||
override fun onPopupItemClicked(editable: Editable, item: RoomMember): Boolean {
|
override fun onPopupItemClicked(editable: Editable, item: RoomMemberSummary): Boolean {
|
||||||
insertMatrixItem(editText, editable, "@", item.toMatrixItem())
|
insertMatrixItem(editText, editable, "@", item.toMatrixItem())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,12 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.view.*
|
import android.view.HapticFeedbackConstants
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.Window
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
@ -46,7 +51,13 @@ import butterknife.BindView
|
|||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
||||||
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
||||||
import com.airbnb.mvrx.*
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.args
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
import com.github.piasy.biv.BigImageViewer
|
import com.github.piasy.biv.BigImageViewer
|
||||||
import com.github.piasy.biv.loader.ImageLoader
|
import com.github.piasy.biv.loader.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
@ -57,7 +68,13 @@ import im.vector.matrix.android.api.session.Session
|
|||||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
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.TimelineEvent
|
||||||
@ -67,19 +84,36 @@ import im.vector.matrix.android.api.util.toMatrixItem
|
|||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.dialogs.withColoredButton
|
import im.vector.riotx.core.dialogs.withColoredButton
|
||||||
import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer
|
import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer
|
||||||
import im.vector.riotx.core.extensions.*
|
import im.vector.riotx.core.extensions.cleanup
|
||||||
|
import im.vector.riotx.core.extensions.hideKeyboard
|
||||||
|
import im.vector.riotx.core.extensions.observeEvent
|
||||||
|
import im.vector.riotx.core.extensions.setTextOrHide
|
||||||
|
import im.vector.riotx.core.extensions.showKeyboard
|
||||||
import im.vector.riotx.core.files.addEntryToDownloadManager
|
import im.vector.riotx.core.files.addEntryToDownloadManager
|
||||||
import im.vector.riotx.core.glide.GlideApp
|
import im.vector.riotx.core.glide.GlideApp
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.core.ui.views.JumpToReadMarkerView
|
import im.vector.riotx.core.ui.views.JumpToReadMarkerView
|
||||||
import im.vector.riotx.core.ui.views.NotificationAreaView
|
import im.vector.riotx.core.ui.views.NotificationAreaView
|
||||||
import im.vector.riotx.core.utils.*
|
import im.vector.riotx.core.utils.Debouncer
|
||||||
|
import im.vector.riotx.core.utils.KeyboardStateUtils
|
||||||
|
import im.vector.riotx.core.utils.PERMISSIONS_FOR_WRITING_FILES
|
||||||
|
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_DOWNLOAD_FILE
|
||||||
|
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_INCOMING_URI
|
||||||
|
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT
|
||||||
|
import im.vector.riotx.core.utils.TextUtils
|
||||||
|
import im.vector.riotx.core.utils.allGranted
|
||||||
|
import im.vector.riotx.core.utils.checkPermissions
|
||||||
|
import im.vector.riotx.core.utils.copyToClipboard
|
||||||
|
import im.vector.riotx.core.utils.createUIHandler
|
||||||
|
import im.vector.riotx.core.utils.getColorFromUserId
|
||||||
|
import im.vector.riotx.core.utils.openUrlInExternalBrowser
|
||||||
|
import im.vector.riotx.core.utils.shareMedia
|
||||||
|
import im.vector.riotx.core.utils.toast
|
||||||
import im.vector.riotx.features.attachments.AttachmentTypeSelectorView
|
import im.vector.riotx.features.attachments.AttachmentTypeSelectorView
|
||||||
import im.vector.riotx.features.attachments.AttachmentsHelper
|
import im.vector.riotx.features.attachments.AttachmentsHelper
|
||||||
import im.vector.riotx.features.attachments.ContactAttachment
|
import im.vector.riotx.features.attachments.ContactAttachment
|
||||||
import im.vector.riotx.features.command.Command
|
import im.vector.riotx.features.command.Command
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.getColorFromUserId
|
|
||||||
import im.vector.riotx.features.home.room.detail.composer.TextComposerView
|
import im.vector.riotx.features.home.room.detail.composer.TextComposerView
|
||||||
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
@ -87,7 +121,12 @@ import im.vector.riotx.features.home.room.detail.timeline.action.EventSharedActi
|
|||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.*
|
import im.vector.riotx.features.home.room.detail.timeline.item.AbsMessageItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
|
||||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import im.vector.riotx.features.html.PillImageSpan
|
import im.vector.riotx.features.html.PillImageSpan
|
||||||
@ -97,7 +136,7 @@ import im.vector.riotx.features.media.ImageMediaViewerActivity
|
|||||||
import im.vector.riotx.features.media.VideoContentRenderer
|
import im.vector.riotx.features.media.VideoContentRenderer
|
||||||
import im.vector.riotx.features.media.VideoMediaViewerActivity
|
import im.vector.riotx.features.media.VideoMediaViewerActivity
|
||||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||||
import im.vector.riotx.features.permalink.NavigateToRoomInterceptor
|
import im.vector.riotx.features.permalink.NavigationInterceptor
|
||||||
import im.vector.riotx.features.permalink.PermalinkHandler
|
import im.vector.riotx.features.permalink.PermalinkHandler
|
||||||
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
@ -205,7 +244,9 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
setupNotificationView()
|
setupNotificationView()
|
||||||
setupJumpToReadMarkerView()
|
setupJumpToReadMarkerView()
|
||||||
setupJumpToBottomView()
|
setupJumpToBottomView()
|
||||||
|
roomToolbarContentView.setOnClickListener {
|
||||||
|
navigator.openRoomProfile(requireActivity(), roomDetailArgs.roomId)
|
||||||
|
}
|
||||||
roomDetailViewModel.subscribe { renderState(it) }
|
roomDetailViewModel.subscribe { renderState(it) }
|
||||||
roomDetailViewModel.sendMessageResultLiveData.observeEvent(viewLifecycleOwner) { renderSendMessageResult(it) }
|
roomDetailViewModel.sendMessageResultLiveData.observeEvent(viewLifecycleOwner) { renderSendMessageResult(it) }
|
||||||
|
|
||||||
@ -328,9 +369,9 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
AlertDialog.Builder(requireActivity())
|
AlertDialog.Builder(requireActivity())
|
||||||
.setTitle(R.string.dialog_title_error)
|
.setTitle(R.string.dialog_title_error)
|
||||||
.setMessage(getString(R.string.error_file_too_big,
|
.setMessage(getString(R.string.error_file_too_big,
|
||||||
error.filename,
|
error.filename,
|
||||||
TextUtils.formatFileSize(requireContext(), error.fileSizeInBytes),
|
TextUtils.formatFileSize(requireContext(), error.fileSizeInBytes),
|
||||||
TextUtils.formatFileSize(requireContext(), error.homeServerLimitInBytes)
|
TextUtils.formatFileSize(requireContext(), error.homeServerLimitInBytes)
|
||||||
))
|
))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
@ -417,9 +458,10 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
|
|
||||||
avatarRenderer.render(
|
avatarRenderer.render(
|
||||||
MatrixItem.UserItem(event.root.senderId
|
MatrixItem.UserItem(event.root.senderId
|
||||||
?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
|
?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
|
||||||
composerLayout.composerRelatedMessageAvatar
|
composerLayout.composerRelatedMessageAvatar
|
||||||
)
|
)
|
||||||
|
|
||||||
composerLayout.expand {
|
composerLayout.expand {
|
||||||
if (isAdded) {
|
if (isAdded) {
|
||||||
// need to do it here also when not using quick reply
|
// need to do it here also when not using quick reply
|
||||||
@ -435,7 +477,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
// Ignore update to avoid saving a draft
|
// Ignore update to avoid saving a draft
|
||||||
composerLayout.composerEditText.setText(text)
|
composerLayout.composerEditText.setText(text)
|
||||||
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text?.length
|
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text?.length
|
||||||
?: 0)
|
?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,7 +841,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
|
|
||||||
override fun onUrlClicked(url: String): Boolean {
|
override fun onUrlClicked(url: String): Boolean {
|
||||||
permalinkHandler
|
permalinkHandler
|
||||||
.launch(requireActivity(), url, object : NavigateToRoomInterceptor {
|
.launch(requireActivity(), url, object : NavigationInterceptor {
|
||||||
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
||||||
// Same room?
|
// Same room?
|
||||||
if (roomId == roomDetailArgs.roomId) {
|
if (roomId == roomDetailArgs.roomId) {
|
||||||
@ -815,6 +857,11 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
// Not handled
|
// Not handled
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun navToMemberProfile(userId: String): Boolean {
|
||||||
|
navigator.openRoomMemberProfile(userId, roomDetailArgs.roomId, vectorBaseActivity)
|
||||||
|
return true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -944,7 +991,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onAvatarClicked(informationData: MessageInformationData) {
|
override fun onAvatarClicked(informationData: MessageInformationData) {
|
||||||
vectorBaseActivity.notImplemented("Click on user avatar")
|
navigator.openRoomMemberProfile(userId = informationData.senderId, roomId = roomDetailArgs.roomId, context = requireActivity())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMemberNameClicked(informationData: MessageInformationData) {
|
override fun onMemberNameClicked(informationData: MessageInformationData) {
|
||||||
@ -973,7 +1020,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
|
|
||||||
override fun onRoomCreateLinkClicked(url: String) {
|
override fun onRoomCreateLinkClicked(url: String) {
|
||||||
permalinkHandler
|
permalinkHandler
|
||||||
.launch(requireContext(), url, object : NavigateToRoomInterceptor {
|
.launch(requireContext(), url, object : NavigationInterceptor {
|
||||||
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
||||||
requireActivity().finish()
|
requireActivity().finish()
|
||||||
return false
|
return false
|
||||||
@ -1124,7 +1171,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
val startToCompose = composerLayout.composerEditText.text.isNullOrBlank()
|
val startToCompose = composerLayout.composerEditText.text.isNullOrBlank()
|
||||||
|
|
||||||
if (startToCompose
|
if (startToCompose
|
||||||
&& userId == session.myUserId) {
|
&& userId == session.myUserId) {
|
||||||
// Empty composer, current user: start an emote
|
// Empty composer, current user: start an emote
|
||||||
composerLayout.composerEditText.setText(Command.EMOTE.command + " ")
|
composerLayout.composerEditText.setText(Command.EMOTE.command + " ")
|
||||||
composerLayout.composerEditText.setSelection(Command.EMOTE.length)
|
composerLayout.composerEditText.setSelection(Command.EMOTE.length)
|
||||||
@ -1162,7 +1209,6 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
focusComposerAndShowKeyboard()
|
focusComposerAndShowKeyboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilities
|
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilities
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
@ -207,7 +207,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
invisibleEventsObservable.accept(action)
|
invisibleEventsObservable.accept(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMember(userId: String): RoomMember? {
|
fun getMember(userId: String): RoomMemberSummary? {
|
||||||
return room.getRoomMember(userId)
|
return room.getRoomMember(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import com.airbnb.mvrx.Success
|
|||||||
import im.vector.riotx.EmojiCompatFontProvider
|
import im.vector.riotx.EmojiCompatFontProvider
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.epoxy.bottomsheet.*
|
import im.vector.riotx.core.epoxy.bottomsheet.*
|
||||||
|
import im.vector.riotx.core.epoxy.dividerItem
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
@ -70,7 +71,7 @@ class MessageActionsEpoxyController @Inject constructor(private val stringProvid
|
|||||||
// Quick reactions
|
// Quick reactions
|
||||||
if (state.canReact() && state.quickStates is Success) {
|
if (state.canReact() && state.quickStates is Success) {
|
||||||
// Separator
|
// Separator
|
||||||
bottomSheetSeparatorItem {
|
dividerItem {
|
||||||
id("reaction_separator")
|
id("reaction_separator")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,14 +89,14 @@ class MessageActionsEpoxyController @Inject constructor(private val stringProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Separator
|
// Separator
|
||||||
bottomSheetSeparatorItem {
|
dividerItem {
|
||||||
id("actions_separator")
|
id("actions_separator")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action
|
// Action
|
||||||
state.actions.forEachIndexed { index, action ->
|
state.actions.forEachIndexed { index, action ->
|
||||||
if (action is EventSharedAction.Separator) {
|
if (action is EventSharedAction.Separator) {
|
||||||
bottomSheetSeparatorItem {
|
dividerItem {
|
||||||
id("separator_$index")
|
id("separator_$index")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
|||||||
import im.vector.matrix.android.api.session.room.timeline.hasBeenEdited
|
import im.vector.matrix.android.api.session.room.timeline.hasBeenEdited
|
||||||
import im.vector.riotx.core.extensions.localDateTime
|
import im.vector.riotx.core.extensions.localDateTime
|
||||||
import im.vector.riotx.core.resources.ColorProvider
|
import im.vector.riotx.core.resources.ColorProvider
|
||||||
import im.vector.riotx.features.home.getColorFromUserId
|
import im.vector.riotx.core.utils.getColorFromUserId
|
||||||
import im.vector.riotx.core.date.VectorDateFormatter
|
import im.vector.riotx.core.date.VectorDateFormatter
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.ReactionInfoData
|
import im.vector.riotx.features.home.room.detail.timeline.item.ReactionInfoData
|
||||||
|
@ -39,6 +39,7 @@ import im.vector.riotx.core.platform.OnBackPressed
|
|||||||
import im.vector.riotx.core.platform.StateView
|
import im.vector.riotx.core.platform.StateView
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.features.home.RoomListDisplayMode
|
import im.vector.riotx.features.home.RoomListDisplayMode
|
||||||
|
import im.vector.riotx.features.home.room.list.actions.RoomListActionsArgs
|
||||||
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||||
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||||
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||||
@ -228,7 +229,7 @@ class RoomListFragment @Inject constructor(
|
|||||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE))
|
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE))
|
||||||
}
|
}
|
||||||
is RoomListQuickActionsSharedAction.Settings -> {
|
is RoomListQuickActionsSharedAction.Settings -> {
|
||||||
vectorBaseActivity.notImplemented("Opening room settings")
|
navigator.openRoomProfile(requireActivity(), quickAction.roomId)
|
||||||
}
|
}
|
||||||
is RoomListQuickActionsSharedAction.Leave -> {
|
is RoomListQuickActionsSharedAction.Leave -> {
|
||||||
AlertDialog.Builder(requireContext())
|
AlertDialog.Builder(requireContext())
|
||||||
@ -346,7 +347,7 @@ class RoomListFragment @Inject constructor(
|
|||||||
roomController.onRoomLongClicked()
|
roomController.onRoomLongClicked()
|
||||||
|
|
||||||
RoomListQuickActionsBottomSheet
|
RoomListQuickActionsBottomSheet
|
||||||
.newInstance(room.roomId)
|
.newInstance(room.roomId, RoomListActionsArgs.Mode.FULL)
|
||||||
.show(childFragmentManager, "ROOM_LIST_QUICK_ACTIONS")
|
.show(childFragmentManager, "ROOM_LIST_QUICK_ACTIONS")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,15 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class RoomListActionsArgs(
|
data class RoomListActionsArgs(
|
||||||
val roomId: String
|
val roomId: String,
|
||||||
) : Parcelable
|
val mode: Mode
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
FULL,
|
||||||
|
NOTIFICATIONS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom sheet fragment that shows room information with list of contextual actions
|
* Bottom sheet fragment that shows room information with list of contextual actions
|
||||||
@ -93,9 +100,9 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(roomId: String): RoomListQuickActionsBottomSheet {
|
fun newInstance(roomId: String, mode: RoomListActionsArgs.Mode): RoomListQuickActionsBottomSheet {
|
||||||
return RoomListQuickActionsBottomSheet().apply {
|
return RoomListQuickActionsBottomSheet().apply {
|
||||||
setArguments(RoomListActionsArgs(roomId))
|
setArguments(RoomListActionsArgs(roomId, mode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.room.notification.RoomNotificationSt
|
|||||||
import im.vector.matrix.android.api.util.toMatrixItem
|
import im.vector.matrix.android.api.util.toMatrixItem
|
||||||
import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetActionItem
|
import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetActionItem
|
||||||
import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem
|
import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem
|
||||||
import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetSeparatorItem
|
import im.vector.riotx.core.epoxy.dividerItem
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -35,18 +35,21 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val avatar
|
|||||||
|
|
||||||
override fun buildModels(state: RoomListQuickActionsState) {
|
override fun buildModels(state: RoomListQuickActionsState) {
|
||||||
val roomSummary = state.roomSummary() ?: return
|
val roomSummary = state.roomSummary() ?: return
|
||||||
|
val showAll = state.mode == RoomListActionsArgs.Mode.FULL
|
||||||
|
|
||||||
// Preview
|
if (showAll) {
|
||||||
bottomSheetRoomPreviewItem {
|
// Preview
|
||||||
id("preview")
|
bottomSheetRoomPreviewItem {
|
||||||
avatarRenderer(avatarRenderer)
|
id("room_preview")
|
||||||
matrixItem(roomSummary.toMatrixItem())
|
avatarRenderer(avatarRenderer)
|
||||||
settingsClickListener(View.OnClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) })
|
matrixItem(roomSummary.toMatrixItem())
|
||||||
}
|
settingsClickListener(View.OnClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) })
|
||||||
|
}
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
bottomSheetSeparatorItem {
|
dividerItem {
|
||||||
id("notifications_separator")
|
id("notifications_separator")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedRoomState = state.roomNotificationState()
|
val selectedRoomState = state.roomNotificationState()
|
||||||
@ -55,11 +58,13 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val avatar
|
|||||||
RoomListQuickActionsSharedAction.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState)
|
RoomListQuickActionsSharedAction.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState)
|
||||||
RoomListQuickActionsSharedAction.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState)
|
RoomListQuickActionsSharedAction.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState)
|
||||||
|
|
||||||
// Leave
|
if (showAll) {
|
||||||
bottomSheetSeparatorItem {
|
// Leave
|
||||||
id("leave_separator")
|
dividerItem {
|
||||||
|
id("leave_separator")
|
||||||
|
}
|
||||||
|
RoomListQuickActionsSharedAction.Leave(roomSummary.roomId).toBottomSheetItem(5)
|
||||||
}
|
}
|
||||||
RoomListQuickActionsSharedAction.Leave(roomSummary.roomId).toBottomSheetItem(5)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RoomListQuickActionsSharedAction.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) {
|
private fun RoomListQuickActionsSharedAction.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) {
|
||||||
|
@ -24,9 +24,10 @@ import im.vector.matrix.android.api.session.room.notification.RoomNotificationSt
|
|||||||
|
|
||||||
data class RoomListQuickActionsState(
|
data class RoomListQuickActionsState(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
|
val mode: RoomListActionsArgs.Mode,
|
||||||
val roomSummary: Async<RoomSummary> = Uninitialized,
|
val roomSummary: Async<RoomSummary> = Uninitialized,
|
||||||
val roomNotificationState: Async<RoomNotificationState> = Uninitialized
|
val roomNotificationState: Async<RoomNotificationState> = Uninitialized
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
|
|
||||||
constructor(args: RoomListActionsArgs) : this(roomId = args.roomId)
|
constructor(args: RoomListActionsArgs) : this(roomId = args.roomId, mode = args.mode)
|
||||||
}
|
}
|
||||||
|
@ -26,20 +26,22 @@ import im.vector.riotx.core.di.ActiveSessionHolder
|
|||||||
import im.vector.riotx.core.error.fatalError
|
import im.vector.riotx.core.error.fatalError
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
import im.vector.riotx.core.utils.toast
|
import im.vector.riotx.core.utils.toast
|
||||||
|
import im.vector.riotx.features.createdirect.CreateDirectRoomActivity
|
||||||
import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
||||||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity
|
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity
|
||||||
import im.vector.riotx.features.debug.DebugMenuActivity
|
import im.vector.riotx.features.debug.DebugMenuActivity
|
||||||
import im.vector.riotx.features.home.createdirect.CreateDirectRoomActivity
|
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
||||||
import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
||||||
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
||||||
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
||||||
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity
|
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity
|
||||||
|
import im.vector.riotx.features.roommemberprofile.RoomMemberProfileActivity
|
||||||
|
import im.vector.riotx.features.roommemberprofile.RoomMemberProfileArgs
|
||||||
|
import im.vector.riotx.features.roomprofile.RoomProfileActivity
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import im.vector.riotx.features.settings.VectorSettingsActivity
|
import im.vector.riotx.features.settings.VectorSettingsActivity
|
||||||
import im.vector.riotx.features.share.SharedData
|
import im.vector.riotx.features.share.SharedData
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -54,16 +56,9 @@ class DefaultNavigator @Inject constructor(
|
|||||||
fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast())
|
fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val args = RoomDetailArgs(roomId, eventId)
|
val args = RoomDetailArgs(roomId, eventId)
|
||||||
val intent = RoomDetailActivity.newIntent(context, args)
|
val intent = RoomDetailActivity.newIntent(context, args)
|
||||||
if (buildTask) {
|
startActivity(context, intent, buildTask)
|
||||||
val stackBuilder = TaskStackBuilder.create(context)
|
|
||||||
stackBuilder.addNextIntentWithParentStack(intent)
|
|
||||||
stackBuilder.startActivities()
|
|
||||||
} else {
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openNotJoinedRoom(context: Context, roomIdOrAlias: String?, eventId: String?, buildTask: Boolean) {
|
override fun openNotJoinedRoom(context: Context, roomIdOrAlias: String?, eventId: String?, buildTask: Boolean) {
|
||||||
@ -82,12 +77,10 @@ class DefaultNavigator @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openUserDetail(userId: String, context: Context, buildTask: Boolean) {
|
override fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean) {
|
||||||
if (context is VectorBaseActivity) {
|
val args = RoomMemberProfileArgs(userId = userId, roomId = roomId)
|
||||||
context.notImplemented("Open user detail")
|
val intent = RoomMemberProfileActivity.newIntent(context, args)
|
||||||
} else {
|
startActivity(context, intent, buildTask)
|
||||||
context.toast(R.string.not_implemented)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openRoomForSharing(activity: Activity, roomId: String, sharedData: SharedData) {
|
override fun openRoomForSharing(activity: Activity, roomId: String, sharedData: SharedData) {
|
||||||
@ -139,7 +132,17 @@ class DefaultNavigator @Inject constructor(
|
|||||||
context.startActivity(KeysBackupManageActivity.intent(context))
|
context.startActivity(KeysBackupManageActivity.intent(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openRoomSettings(context: Context, roomId: String) {
|
override fun openRoomProfile(context: Context, roomId: String) {
|
||||||
Timber.v("Open room settings$roomId")
|
context.startActivity(RoomProfileActivity.newIntent(context, roomId))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) {
|
||||||
|
if (buildTask) {
|
||||||
|
val stackBuilder = TaskStackBuilder.create(context)
|
||||||
|
stackBuilder.addNextIntentWithParentStack(intent)
|
||||||
|
stackBuilder.startActivities()
|
||||||
|
} else {
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ interface Navigator {
|
|||||||
|
|
||||||
fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean = false)
|
fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean = false)
|
||||||
|
|
||||||
fun openUserDetail(userId: String, context: Context, buildTask: Boolean = false)
|
fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean = false)
|
||||||
|
|
||||||
fun openRoomSettings(context: Context, roomId: String)
|
fun openRoomProfile(context: Context, roomId: String)
|
||||||
}
|
}
|
||||||
|
@ -35,17 +35,17 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||||||
fun launch(
|
fun launch(
|
||||||
context: Context,
|
context: Context,
|
||||||
deepLink: String?,
|
deepLink: String?,
|
||||||
navigateToRoomInterceptor: NavigateToRoomInterceptor? = null,
|
navigationInterceptor: NavigationInterceptor? = null,
|
||||||
buildTask: Boolean = false
|
buildTask: Boolean = false
|
||||||
): Single<Boolean> {
|
): Single<Boolean> {
|
||||||
val uri = deepLink?.let { Uri.parse(it) }
|
val uri = deepLink?.let { Uri.parse(it) }
|
||||||
return launch(context, uri, navigateToRoomInterceptor, buildTask)
|
return launch(context, uri, navigationInterceptor, buildTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun launch(
|
fun launch(
|
||||||
context: Context,
|
context: Context,
|
||||||
deepLink: Uri?,
|
deepLink: Uri?,
|
||||||
navigateToRoomInterceptor: NavigateToRoomInterceptor? = null,
|
navigationInterceptor: NavigationInterceptor? = null,
|
||||||
buildTask: Boolean = false
|
buildTask: Boolean = false
|
||||||
): Single<Boolean> {
|
): Single<Boolean> {
|
||||||
if (deepLink == null) {
|
if (deepLink == null) {
|
||||||
@ -57,7 +57,7 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.map {
|
.map {
|
||||||
val roomId = it.getOrNull()
|
val roomId = it.getOrNull()
|
||||||
if (navigateToRoomInterceptor?.navToRoom(roomId, permalinkData.eventId) != true) {
|
if (navigationInterceptor?.navToRoom(roomId, permalinkData.eventId) != true) {
|
||||||
openRoom(context, roomId, permalinkData.eventId, buildTask)
|
openRoom(context, roomId, permalinkData.eventId, buildTask)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@ -68,7 +68,9 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||||||
Single.just(true)
|
Single.just(true)
|
||||||
}
|
}
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
navigator.openUserDetail(permalinkData.userId, context, buildTask)
|
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId) != true) {
|
||||||
|
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
||||||
|
}
|
||||||
Single.just(true)
|
Single.just(true)
|
||||||
}
|
}
|
||||||
is PermalinkData.FallbackLink -> {
|
is PermalinkData.FallbackLink -> {
|
||||||
@ -98,10 +100,19 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NavigateToRoomInterceptor {
|
interface NavigationInterceptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the navigation has been intercepted
|
* Return true if the navigation has been intercepted
|
||||||
*/
|
*/
|
||||||
fun navToRoom(roomId: String?, eventId: String? = null): Boolean
|
fun navToRoom(roomId: String?, eventId: String? = null): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the navigation has been intercepted
|
||||||
|
*/
|
||||||
|
fun navToMemberProfile(userId: String): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.features.roommemberprofile
|
||||||
|
|
||||||
|
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||||
|
|
||||||
|
sealed class RoomMemberProfileAction : VectorViewModelAction {
|
||||||
|
|
||||||
|
object RetryFetchingInfo: RoomMemberProfileAction()
|
||||||
|
object IgnoreUser: RoomMemberProfileAction()
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.riotx.features.roommemberprofile
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.extensions.addFragment
|
||||||
|
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||||
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
|
|
||||||
|
class RoomMemberProfileActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val EXTRA_FRAGMENT_ARGS = "EXTRA_FRAGMENT_ARGS"
|
||||||
|
|
||||||
|
fun newIntent(context: Context, args: RoomMemberProfileArgs): Intent {
|
||||||
|
return Intent(context, RoomMemberProfileActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_FRAGMENT_ARGS, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.activity_simple
|
||||||
|
|
||||||
|
override fun initUiAndData() {
|
||||||
|
if (isFirstCreation()) {
|
||||||
|
val fragmentArgs: RoomMemberProfileArgs = intent?.extras?.getParcelable(EXTRA_FRAGMENT_ARGS)
|
||||||
|
?: return
|
||||||
|
addFragment(R.id.simpleFragmentContainer, RoomMemberProfileFragment::class.java, fragmentArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configure(toolbar: Toolbar) {
|
||||||
|
configureToolbar(toolbar)
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user