Merge branch 'develop' into feature/bma/fix_cancel
This commit is contained in:
commit
5237eb0638
1
.idea/dictionaries/bmarty.xml
generated
1
.idea/dictionaries/bmarty.xml
generated
@ -31,6 +31,7 @@
|
|||||||
<w>ssss</w>
|
<w>ssss</w>
|
||||||
<w>sygnal</w>
|
<w>sygnal</w>
|
||||||
<w>threepid</w>
|
<w>threepid</w>
|
||||||
|
<w>unpublish</w>
|
||||||
<w>unwedging</w>
|
<w>unwedging</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
13
CHANGES.md
13
CHANGES.md
@ -2,13 +2,17 @@ Changes in Element 1.0.12 (2020-XX-XX)
|
|||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
-
|
- Add room aliases management, and room directory visibility management in a dedicated screen (#1579, #2428)
|
||||||
|
- Room setting: update join rules and guest access (#2442)
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
-
|
- Add Setting Item to Change PIN (#2462)
|
||||||
|
- Improve room history visibility setting UX (#1579)
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Fix cancellation of sending event (#2438)
|
- Fix cancellation of sending event (#2438)
|
||||||
|
- Double bottomsheet effect after verify with passphrase
|
||||||
|
- EditText cursor jumps to the start while typing fast (#2469)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
@ -17,13 +21,14 @@ SDK API changes ⚠️:
|
|||||||
-
|
-
|
||||||
|
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
- Upgrade some dependencies and Kotlin version
|
||||||
|
- Use fragment-ktx and preference-ktx dependencies (fix lint issue KtxExtensionAvailable)
|
||||||
|
|
||||||
Test:
|
Test:
|
||||||
-
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
- Remove "Status.im" theme #2424
|
||||||
|
|
||||||
Changes in Element 1.0.11 (2020-11-27)
|
Changes in Element 1.0.11 (2020-11-27)
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -66,7 +66,6 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
// Ref: https://kotlinlang.org/releases.html
|
// Ref: https://kotlinlang.org/releases.html
|
||||||
ext.kotlin_version = '1.4.10'
|
ext.kotlin_version = '1.4.20'
|
||||||
ext.kotlin_coroutines_version = "1.3.9"
|
ext.kotlin_coroutines_version = "1.4.1"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
@ -12,7 +12,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||||
classpath 'com.google.gms:google-services:4.3.4'
|
classpath 'com.google.gms:google-services:4.3.4'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
||||||
|
@ -36,9 +36,9 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
||||||
|
|
||||||
|
@ -21,34 +21,36 @@ import org.matrix.android.sdk.api.util.Cancelable
|
|||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
|
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
it.onSuccess(data)
|
// Add `!!` to fix the warning:
|
||||||
|
// "Type mismatch: type parameter with nullable bounds is used T is used where T was expected. This warning will become an error soon"
|
||||||
|
emitter.onSuccess(data!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
|
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
it.onComplete()
|
emitter.onComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
@ -127,18 +129,14 @@ class RxRoom(private val room: Room) {
|
|||||||
room.updateName(name, it)
|
room.updateName(name, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addRoomAlias(alias: String): Completable = completableBuilder<Unit> {
|
|
||||||
room.addRoomAlias(alias, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateCanonicalAlias(alias: String): Completable = completableBuilder<Unit> {
|
|
||||||
room.updateCanonicalAlias(alias, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
||||||
room.updateHistoryReadability(readability, it)
|
room.updateHistoryReadability(readability, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?): Completable = completableBuilder<Unit> {
|
||||||
|
room.updateJoinRule(joinRules, guestAccess, it)
|
||||||
|
}
|
||||||
|
|
||||||
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder<Unit> {
|
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder<Unit> {
|
||||||
room.updateAvatar(avatarUri, fileName, it)
|
room.updateAvatar(avatarUri, fileName, it)
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,6 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation "androidx.core:core-ktx:1.3.2"
|
implementation "androidx.core:core-ktx:1.3.2"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
@ -146,7 +145,7 @@ dependencies {
|
|||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.3.0'
|
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
||||||
|
@ -49,6 +49,12 @@ object EventType {
|
|||||||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that this Event has been deprecated, see
|
||||||
|
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||||
|
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||||
|
*/
|
||||||
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
||||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||||
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.integrationmanager
|
package org.matrix.android.sdk.api.session.integrationmanager
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
||||||
*/
|
*/
|
||||||
@ -80,19 +77,17 @@ interface IntegrationManagerService {
|
|||||||
/**
|
/**
|
||||||
* Offers to enable or disable the integration.
|
* Offers to enable or disable the integration.
|
||||||
* @param enable the param to change
|
* @param enable the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @return Cancelable
|
||||||
*/
|
*/
|
||||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setIntegrationEnabled(enable: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offers to allow or disallow a widget.
|
* Offers to allow or disallow a widget.
|
||||||
* @param stateEventId the eventId of the state event defining the widget.
|
* @param stateEventId the eventId of the state event defining the widget.
|
||||||
* @param allowed the param to change
|
* @param allowed the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @return Cancelable
|
||||||
*/
|
*/
|
||||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the widget is allowed, false otherwise.
|
* Returns true if the widget is allowed, false otherwise.
|
||||||
@ -105,7 +100,7 @@ interface IntegrationManagerService {
|
|||||||
* @param widgetType the widget type to check for
|
* @param widgetType the widget type to check for
|
||||||
* @param domain the domain to check for
|
* @param domain the domain to check for
|
||||||
*/
|
*/
|
||||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the widget domain is allowed, false otherwise.
|
* Returns true if the widget domain is allowed, false otherwise.
|
||||||
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
@ -46,6 +47,7 @@ interface Room :
|
|||||||
DraftService,
|
DraftService,
|
||||||
ReadService,
|
ReadService,
|
||||||
TypingService,
|
TypingService,
|
||||||
|
AliasService,
|
||||||
TagsService,
|
TagsService,
|
||||||
MembershipService,
|
MembershipService,
|
||||||
StateService,
|
StateService,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||||
@ -39,4 +40,14 @@ interface RoomDirectoryService {
|
|||||||
* Includes both the available protocols and all fields required for queries against each protocol.
|
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||||
*/
|
*/
|
||||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the visibility of a room in the directory
|
||||||
|
*/
|
||||||
|
suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the visibility of a room in the directory
|
||||||
|
*/
|
||||||
|
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,11 @@ interface RoomService {
|
|||||||
searchOnServer: Boolean,
|
searchOnServer: Boolean,
|
||||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
callback: MatrixCallback<Optional<String>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a room alias
|
||||||
|
*/
|
||||||
|
suspend fun deleteRoomAlias(roomAlias: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a live data of all local changes membership that happened since the session has been opened.
|
* Return a live data of all local changes membership that happened since the session has been opened.
|
||||||
* It allows you to track this in your client to known what is currently being processed by the SDK.
|
* It allows you to track this in your client to known what is currently being processed by the SDK.
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room.alias
|
||||||
|
|
||||||
|
interface AliasService {
|
||||||
|
/**
|
||||||
|
* Get list of local alias of the room
|
||||||
|
* @return the list of the aliases (full aliases, not only the local part)
|
||||||
|
*/
|
||||||
|
suspend fun getRoomAliases(): List<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add local alias to the room
|
||||||
|
* @param aliasLocalPart the local part of the alias.
|
||||||
|
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||||
|
*/
|
||||||
|
suspend fun addAlias(aliasLocalPart: String)
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room.alias
|
||||||
|
|
||||||
|
sealed class RoomAliasError : Throwable() {
|
||||||
|
object AliasEmpty : RoomAliasError()
|
||||||
|
object AliasNotAvailable : RoomAliasError()
|
||||||
|
object AliasInvalid : RoomAliasError()
|
||||||
|
}
|
@ -18,13 +18,10 @@ package org.matrix.android.sdk.api.session.room.failure
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.failure.MatrixError
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
|
||||||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||||
object CreatedWithTimeout : CreateRoomFailure()
|
object CreatedWithTimeout : CreateRoomFailure()
|
||||||
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
||||||
sealed class RoomAliasError : CreateRoomFailure() {
|
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
|
||||||
object AliasEmpty : RoomAliasError()
|
|
||||||
object AliasNotAvailable : RoomAliasError()
|
|
||||||
object AliasInvalid : RoomAliasError()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
||||||
|
* Note that this Event has been deprecated, see
|
||||||
|
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||||
|
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomAliasesContent(
|
data class RoomAliasesContent(
|
||||||
|
@ -24,5 +24,14 @@ import com.squareup.moshi.JsonClass
|
|||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomCanonicalAliasContent(
|
data class RoomCanonicalAliasContent(
|
||||||
@Json(name = "alias") val canonicalAlias: String? = null
|
/**
|
||||||
|
* The canonical alias for the room. If not present, null, or empty the room should be considered to have no canonical alias.
|
||||||
|
*/
|
||||||
|
@Json(name = "alias") val canonicalAlias: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative aliases the room advertises.
|
||||||
|
* This list can have aliases despite the alias field being null, empty, or otherwise not present.
|
||||||
|
*/
|
||||||
|
@Json(name = "alt_aliases") val alternativeAliases: List<String>? = null
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,9 @@ import androidx.lifecycle.LiveData
|
|||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
@ -38,21 +40,23 @@ interface StateService {
|
|||||||
*/
|
*/
|
||||||
fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
|
fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new alias to the room.
|
|
||||||
*/
|
|
||||||
fun addRoomAlias(roomAlias: String, callback: MatrixCallback<Unit>): Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the canonical alias of the room
|
* Update the canonical alias of the room
|
||||||
|
* @param alias the canonical alias, or null to reset the canonical alias of this room
|
||||||
|
* @param altAliases the alternative aliases for this room. It should include the canonical alias if any.
|
||||||
*/
|
*/
|
||||||
fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable
|
fun updateCanonicalAlias(alias: String?, altAliases: List<String>, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the history readability of the room
|
* Update the history readability of the room
|
||||||
*/
|
*/
|
||||||
fun updateHistoryReadability(readability: RoomHistoryVisibility, callback: MatrixCallback<Unit>): Cancelable
|
fun updateHistoryReadability(readability: RoomHistoryVisibility, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the join rule and/or the guest access
|
||||||
|
*/
|
||||||
|
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the avatar of the room
|
* Update the avatar of the room
|
||||||
*/
|
*/
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room.uploads
|
package org.matrix.android.sdk.api.session.room.uploads
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to get event with uploads (= attachments) sent to a room. It's implemented at the room level.
|
* This interface defines methods to get event with uploads (= attachments) sent to a room. It's implemented at the room level.
|
||||||
*/
|
*/
|
||||||
@ -29,7 +26,5 @@ interface UploadsService {
|
|||||||
* @param numberOfEvents the expected number of events to retrieve. The result can contain less events.
|
* @param numberOfEvents the expected number of events to retrieve. The result can contain less events.
|
||||||
* @param since token to get next page, or null to get the first page
|
* @param since token to get next page, or null to get the first page
|
||||||
*/
|
*/
|
||||||
fun getUploads(numberOfEvents: Int,
|
suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult
|
||||||
since: String?,
|
|
||||||
callback: MatrixCallback<GetUploadsResult>): Cancelable
|
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,16 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.terms
|
package org.matrix.android.sdk.api.session.terms
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
interface TermsService {
|
interface TermsService {
|
||||||
enum class ServiceType {
|
enum class ServiceType {
|
||||||
IntegrationManager,
|
IntegrationManager,
|
||||||
IdentityService
|
IdentityService
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTerms(serviceType: ServiceType,
|
suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse
|
||||||
baseUrl: String,
|
|
||||||
callback: MatrixCallback<GetTermsResponse>): Cancelable
|
|
||||||
|
|
||||||
fun agreeToTerms(serviceType: ServiceType,
|
suspend fun agreeToTerms(serviceType: ServiceType,
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
agreedUrls: List<String>,
|
agreedUrls: List<String>,
|
||||||
token: String?,
|
token: String?)
|
||||||
callback: MatrixCallback<Unit>): Cancelable
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import org.matrix.android.sdk.internal.extensions.toUnsignedInt
|
|||||||
import org.matrix.olm.OlmSAS
|
import org.matrix.olm.OlmSAS
|
||||||
import org.matrix.olm.OlmUtility
|
import org.matrix.olm.OlmUtility
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an ongoing short code interactive key verification between two devices.
|
* Represents an ongoing short code interactive key verification between two devices.
|
||||||
@ -344,7 +345,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
|
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
|
||||||
if ("sha256".toLowerCase() == accepted?.hash?.toLowerCase()) {
|
if ("sha256" == accepted?.hash?.toLowerCase(Locale.ROOT)) {
|
||||||
val olmUtil = OlmUtility()
|
val olmUtil = OlmUtility()
|
||||||
val hashBytes = olmUtil.sha256(toHash)
|
val hashBytes = olmUtil.sha256(toHash)
|
||||||
olmUtil.releaseUtility()
|
olmUtil.releaseUtility()
|
||||||
@ -354,12 +355,11 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun macUsingAgreedMethod(message: String, info: String): String? {
|
private fun macUsingAgreedMethod(message: String, info: String): String? {
|
||||||
if (SAS_MAC_SHA256_LONGKDF.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
return when (accepted?.messageAuthenticationCode?.toLowerCase(Locale.ROOT)) {
|
||||||
return getSAS().calculateMacLongKdf(message, info)
|
SAS_MAC_SHA256_LONGKDF -> getSAS().calculateMacLongKdf(message, info)
|
||||||
} else if (SAS_MAC_SHA256.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
SAS_MAC_SHA256 -> getSAS().calculateMac(message, info)
|
||||||
return getSAS().calculateMac(message, info)
|
else -> null
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDecimalCodeRepresentation(): String {
|
override fun getDecimalCodeRepresentation(): String {
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.directory
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.DELETE
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.PUT
|
||||||
|
import retrofit2.http.Path
|
||||||
|
|
||||||
|
internal interface DirectoryAPI {
|
||||||
|
/**
|
||||||
|
* Get the room ID associated to the room alias.
|
||||||
|
*
|
||||||
|
* @param roomAlias the room alias.
|
||||||
|
*/
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||||
|
fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call<RoomAliasDescription>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the room directory visibility.
|
||||||
|
*
|
||||||
|
* @param roomId the room id.
|
||||||
|
*/
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||||
|
fun getRoomDirectoryVisibility(@Path("roomId") roomId: String): Call<RoomDirectoryVisibilityJson>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the room directory visibility.
|
||||||
|
*
|
||||||
|
* @param roomId the room id.
|
||||||
|
* @param body the body containing the new directory visibility
|
||||||
|
*/
|
||||||
|
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||||
|
fun setRoomDirectoryVisibility(@Path("roomId") roomId: String,
|
||||||
|
@Body body: RoomDirectoryVisibilityJson): Call<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add alias to the room.
|
||||||
|
* @param roomAlias the room alias.
|
||||||
|
*/
|
||||||
|
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||||
|
fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
||||||
|
@Body body: AddRoomAliasBody): Call<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a room alias
|
||||||
|
* @param roomAlias the room alias.
|
||||||
|
*/
|
||||||
|
@DELETE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||||
|
fun deleteRoomAlias(@Path("roomAlias") roomAlias: String): Call<Unit>
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.directory
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class RoomDirectoryVisibilityJson(
|
||||||
|
/**
|
||||||
|
* The visibility of the room in the directory. One of: ["private", "public"]
|
||||||
|
*/
|
||||||
|
@Json(name = "visibility") val visibility: RoomDirectoryVisibility
|
||||||
|
)
|
@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.integrationmanager
|
package org.matrix.android.sdk.internal.session.integrationmanager
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
||||||
@ -44,20 +42,20 @@ internal class DefaultIntegrationManagerService @Inject constructor(private val
|
|||||||
return integrationManager.isIntegrationEnabled()
|
return integrationManager.isIntegrationEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||||
return integrationManager.setIntegrationEnabled(enable, callback)
|
integrationManager.setIntegrationEnabled(enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||||
return integrationManager.setWidgetAllowed(stateEventId, allowed, callback)
|
integrationManager.setWidgetAllowed(stateEventId, allowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||||
return integrationManager.isWidgetAllowed(stateEventId)
|
return integrationManager.isWidgetAllowed(stateEventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||||
return integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed, callback)
|
integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
||||||
|
@ -20,15 +20,12 @@ import androidx.lifecycle.Lifecycle
|
|||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.LifecycleRegistry
|
import androidx.lifecycle.LifecycleRegistry
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import org.matrix.android.sdk.api.util.NoOpCancellable
|
|
||||||
import org.matrix.android.sdk.internal.database.model.WellknownIntegrationManagerConfigEntity
|
import org.matrix.android.sdk.internal.database.model.WellknownIntegrationManagerConfigEntity
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.extensions.observeNotNull
|
import org.matrix.android.sdk.internal.extensions.observeNotNull
|
||||||
@ -41,7 +38,6 @@ import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccoun
|
|||||||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
||||||
import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
|
import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -137,22 +133,17 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||||||
return integrationProvisioningContent?.enabled ?: false
|
return integrationProvisioningContent?.enabled ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||||
val isIntegrationEnabled = isIntegrationEnabled()
|
val isIntegrationEnabled = isIntegrationEnabled()
|
||||||
if (enable == isIntegrationEnabled) {
|
if (enable == isIntegrationEnabled) {
|
||||||
callback.onSuccess(Unit)
|
return
|
||||||
return NoOpCancellable
|
|
||||||
}
|
}
|
||||||
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
||||||
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||||
val newContent = if (currentContent == null) {
|
val newContent = if (currentContent == null) {
|
||||||
@ -165,11 +156,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||||||
currentContent.copy(widgets = allowedWidgets)
|
currentContent.copy(widgets = allowedWidgets)
|
||||||
}
|
}
|
||||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isWidgetAllowed(stateEventId: String): Boolean {
|
fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||||
@ -178,7 +165,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||||||
return currentContent?.widgets?.get(stateEventId) ?: false
|
return currentContent?.widgets?.get(stateEventId) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||||
val newContent = if (currentContent == null) {
|
val newContent = if (currentContent == null) {
|
||||||
@ -195,11 +182,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||||||
currentContent.copy(native = nativeAllowedWidgets)
|
currentContent.copy(native = nativeAllowedWidgets)
|
||||||
}
|
}
|
||||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
||||||
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.MatrixCallback
|
|||||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
@ -58,6 +59,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
private val roomCallService: RoomCallService,
|
private val roomCallService: RoomCallService,
|
||||||
private val readService: ReadService,
|
private val readService: ReadService,
|
||||||
private val typingService: TypingService,
|
private val typingService: TypingService,
|
||||||
|
private val aliasService: AliasService,
|
||||||
private val tagsService: TagsService,
|
private val tagsService: TagsService,
|
||||||
private val cryptoService: CryptoService,
|
private val cryptoService: CryptoService,
|
||||||
private val relationService: RelationService,
|
private val relationService: RelationService,
|
||||||
@ -76,6 +78,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
RoomCallService by roomCallService,
|
RoomCallService by roomCallService,
|
||||||
ReadService by readService,
|
ReadService by readService,
|
||||||
TypingService by typingService,
|
TypingService by typingService,
|
||||||
|
AliasService by aliasService,
|
||||||
TagsService by tagsService,
|
TagsService by tagsService,
|
||||||
RelationService by relationService,
|
RelationService by relationService,
|
||||||
MembershipService by roomMembersService,
|
MembershipService by roomMembersService,
|
||||||
|
@ -18,18 +18,24 @@ package org.matrix.android.sdk.internal.session.room
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetThirdPartyProtocolsTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetThirdPartyProtocolsTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
|
internal class DefaultRoomDirectoryService @Inject constructor(
|
||||||
|
private val getPublicRoomTask: GetPublicRoomTask,
|
||||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||||
|
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||||
|
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
|
||||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||||
|
|
||||||
override fun getPublicRooms(server: String?,
|
override fun getPublicRooms(server: String?,
|
||||||
@ -49,4 +55,12 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
|
|||||||
}
|
}
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility {
|
||||||
|
return getRoomDirectoryVisibilityTask.execute(GetRoomDirectoryVisibilityTask.Params(roomId))
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||||
|
setRoomDirectoryVisibilityTask.execute(SetRoomDirectoryVisibilityTask.Params(roomId, roomDirectoryVisibility))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||||
@ -53,6 +54,7 @@ internal class DefaultRoomService @Inject constructor(
|
|||||||
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
||||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||||
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
||||||
|
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
||||||
private val roomGetter: RoomGetter,
|
private val roomGetter: RoomGetter,
|
||||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||||
@ -125,6 +127,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteRoomAlias(roomAlias: String) {
|
||||||
|
deleteRoomAliasTask.execute(DeleteRoomAliasTask.Params(roomAlias))
|
||||||
|
}
|
||||||
|
|
||||||
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
||||||
return roomChangeMembershipStateDataSource.getLiveStates()
|
return roomChangeMembershipStateDataSource.getLiveStates()
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,7 @@ import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsRe
|
|||||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
|
import org.matrix.android.sdk.internal.session.room.alias.GetAliasesResponse
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomBody
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomBody
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomResponse
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomResponse
|
||||||
import org.matrix.android.sdk.internal.session.room.create.JoinRoomResponse
|
import org.matrix.android.sdk.internal.session.room.create.JoinRoomResponse
|
||||||
@ -321,20 +320,11 @@ internal interface RoomAPI {
|
|||||||
@Body body: ReportContentBody): Call<Unit>
|
@Body body: ReportContentBody): Call<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the room ID associated to the room alias.
|
* Get a list of aliases maintained by the local server for the given room.
|
||||||
*
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases
|
||||||
* @param roomAlias the room alias.
|
|
||||||
*/
|
*/
|
||||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2432/rooms/{roomId}/aliases")
|
||||||
fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call<RoomAliasDescription>
|
fun getAliases(@Path("roomId") roomId: String): Call<GetAliasesResponse>
|
||||||
|
|
||||||
/**
|
|
||||||
* Add alias to the room.
|
|
||||||
* @param roomAlias the room alias.
|
|
||||||
*/
|
|
||||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
|
||||||
fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
|
||||||
@Body body: AddRoomAliasBody): Call<Unit>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform that the user is starting to type or has stopped typing
|
* Inform that the user is starting to type or has stopped typing
|
||||||
|
@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room
|
|||||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
|
||||||
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
|
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
|
||||||
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
|
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService
|
import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService
|
||||||
@ -54,6 +55,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
|
|||||||
private val roomCallServiceFactory: DefaultRoomCallService.Factory,
|
private val roomCallServiceFactory: DefaultRoomCallService.Factory,
|
||||||
private val readServiceFactory: DefaultReadService.Factory,
|
private val readServiceFactory: DefaultReadService.Factory,
|
||||||
private val typingServiceFactory: DefaultTypingService.Factory,
|
private val typingServiceFactory: DefaultTypingService.Factory,
|
||||||
|
private val aliasServiceFactory: DefaultAliasService.Factory,
|
||||||
private val tagsServiceFactory: DefaultTagsService.Factory,
|
private val tagsServiceFactory: DefaultTagsService.Factory,
|
||||||
private val relationServiceFactory: DefaultRelationService.Factory,
|
private val relationServiceFactory: DefaultRelationService.Factory,
|
||||||
private val membershipServiceFactory: DefaultMembershipService.Factory,
|
private val membershipServiceFactory: DefaultMembershipService.Factory,
|
||||||
@ -76,6 +78,7 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
|
|||||||
roomCallService = roomCallServiceFactory.create(roomId),
|
roomCallService = roomCallServiceFactory.create(roomId),
|
||||||
readService = readServiceFactory.create(roomId),
|
readService = readServiceFactory.create(roomId),
|
||||||
typingService = typingServiceFactory.create(roomId),
|
typingService = typingServiceFactory.create(roomId),
|
||||||
|
aliasService = aliasServiceFactory.create(roomId),
|
||||||
tagsService = tagsServiceFactory.create(roomId),
|
tagsService = tagsServiceFactory.create(roomId),
|
||||||
cryptoService = cryptoService,
|
cryptoService = cryptoService,
|
||||||
relationService = relationServiceFactory.create(roomId),
|
relationService = relationServiceFactory.create(roomId),
|
||||||
|
@ -26,16 +26,25 @@ import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
|||||||
import org.matrix.android.sdk.api.session.room.RoomService
|
import org.matrix.android.sdk.api.session.room.RoomService
|
||||||
import org.matrix.android.sdk.internal.session.DefaultFileService
|
import org.matrix.android.sdk.internal.session.DefaultFileService
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultAddRoomAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.DefaultAddRoomAliasTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.DefaultDeleteRoomAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomIdByAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomIdByAliasTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAliasesTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask
|
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetThirdPartyProtocolsTask
|
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetThirdPartyProtocolsTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.DefaultSetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.directory.GetThirdPartyProtocolsTask
|
import org.matrix.android.sdk.internal.session.room.directory.GetThirdPartyProtocolsTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.DefaultLoadRoomMembersTask
|
import org.matrix.android.sdk.internal.session.room.membership.DefaultLoadRoomMembersTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.admin.DefaultMembershipAdminTask
|
import org.matrix.android.sdk.internal.session.room.membership.admin.DefaultMembershipAdminTask
|
||||||
@ -90,6 +99,13 @@ internal abstract class RoomModule {
|
|||||||
return retrofit.create(RoomAPI::class.java)
|
return retrofit.create(RoomAPI::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@JvmStatic
|
||||||
|
@SessionScope
|
||||||
|
fun providesDirectoryAPI(retrofit: Retrofit): DirectoryAPI {
|
||||||
|
return retrofit.create(DirectoryAPI::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun providesParser(): Parser {
|
fun providesParser(): Parser {
|
||||||
@ -127,6 +143,12 @@ internal abstract class RoomModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask
|
abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindGetRoomDirectoryVisibilityTask(task: DefaultGetRoomDirectoryVisibilityTask): GetRoomDirectoryVisibilityTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindSetRoomDirectoryVisibilityTask(task: DefaultSetRoomDirectoryVisibilityTask): SetRoomDirectoryVisibilityTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindGetThirdPartyProtocolsTask(task: DefaultGetThirdPartyProtocolsTask): GetThirdPartyProtocolsTask
|
abstract fun bindGetThirdPartyProtocolsTask(task: DefaultGetThirdPartyProtocolsTask): GetThirdPartyProtocolsTask
|
||||||
|
|
||||||
@ -181,9 +203,15 @@ internal abstract class RoomModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract fun bindGetRoomIdByAliasTask(task: DefaultGetRoomIdByAliasTask): GetRoomIdByAliasTask
|
abstract fun bindGetRoomIdByAliasTask(task: DefaultGetRoomIdByAliasTask): GetRoomIdByAliasTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindGetRoomLocalAliasesTask(task: DefaultGetRoomLocalAliasesTask): GetRoomLocalAliasesTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindAddRoomAliasTask(task: DefaultAddRoomAliasTask): AddRoomAliasTask
|
abstract fun bindAddRoomAliasTask(task: DefaultAddRoomAliasTask): AddRoomAliasTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindDeleteRoomAliasTask(task: DefaultDeleteRoomAliasTask): DeleteRoomAliasTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSendTypingTask(task: DefaultSendTypingTask): SendTypingTask
|
abstract fun bindSendTypingTask(task: DefaultSendTypingTask): SendTypingTask
|
||||||
|
|
||||||
|
@ -16,28 +16,38 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.room.alias
|
package org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
import org.matrix.android.sdk.internal.network.executeRequest
|
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker.Companion.toFullLocalAlias
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface AddRoomAliasTask : Task<AddRoomAliasTask.Params, Unit> {
|
internal interface AddRoomAliasTask : Task<AddRoomAliasTask.Params, Unit> {
|
||||||
data class Params(
|
data class Params(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val roomAlias: String
|
/**
|
||||||
|
* the local part of the alias.
|
||||||
|
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||||
|
*/
|
||||||
|
val aliasLocalPart: String
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultAddRoomAliasTask @Inject constructor(
|
internal class DefaultAddRoomAliasTask @Inject constructor(
|
||||||
private val roomAPI: RoomAPI,
|
@UserId private val userId: String,
|
||||||
|
private val directoryAPI: DirectoryAPI,
|
||||||
|
private val aliasAvailabilityChecker: RoomAliasAvailabilityChecker,
|
||||||
private val eventBus: EventBus
|
private val eventBus: EventBus
|
||||||
) : AddRoomAliasTask {
|
) : AddRoomAliasTask {
|
||||||
|
|
||||||
override suspend fun execute(params: AddRoomAliasTask.Params) {
|
override suspend fun execute(params: AddRoomAliasTask.Params) {
|
||||||
|
aliasAvailabilityChecker.check(params.aliasLocalPart)
|
||||||
|
|
||||||
executeRequest<Unit>(eventBus) {
|
executeRequest<Unit>(eventBus) {
|
||||||
apiCall = roomAPI.addRoomAlias(
|
apiCall = directoryAPI.addRoomAlias(
|
||||||
roomAlias = params.roomAlias,
|
roomAlias = params.aliasLocalPart.toFullLocalAlias(userId),
|
||||||
body = AddRoomAliasBody(
|
body = AddRoomAliasBody(
|
||||||
roomId = params.roomId
|
roomId = params.roomId
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
|
import com.squareup.inject.assisted.Assisted
|
||||||
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||||
|
|
||||||
|
internal class DefaultAliasService @AssistedInject constructor(
|
||||||
|
@Assisted private val roomId: String,
|
||||||
|
private val getRoomLocalAliasesTask: GetRoomLocalAliasesTask,
|
||||||
|
private val addRoomAliasTask: AddRoomAliasTask
|
||||||
|
) : AliasService {
|
||||||
|
|
||||||
|
@AssistedInject.Factory
|
||||||
|
interface Factory {
|
||||||
|
fun create(roomId: String): AliasService
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getRoomAliases(): List<String> {
|
||||||
|
return getRoomLocalAliasesTask.execute(GetRoomLocalAliasesTask.Params(roomId))
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun addAlias(aliasLocalPart: String) {
|
||||||
|
addRoomAliasTask.execute(AddRoomAliasTask.Params(roomId, aliasLocalPart))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface DeleteRoomAliasTask : Task<DeleteRoomAliasTask.Params, Unit> {
|
||||||
|
data class Params(
|
||||||
|
val roomAlias: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultDeleteRoomAliasTask @Inject constructor(
|
||||||
|
private val directoryAPI: DirectoryAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) : DeleteRoomAliasTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: DeleteRoomAliasTask.Params) {
|
||||||
|
executeRequest<Unit>(eventBus) {
|
||||||
|
apiCall = directoryAPI.deleteRoomAlias(
|
||||||
|
roomAlias = params.roomAlias
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class GetAliasesResponse(
|
||||||
|
/**
|
||||||
|
* Required. The server's local aliases on the room. Can be empty.
|
||||||
|
*/
|
||||||
|
@Json(name = "aliases") val aliases: List<String> = emptyList()
|
||||||
|
)
|
@ -25,7 +25,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
|||||||
import org.matrix.android.sdk.internal.database.query.findByAlias
|
import org.matrix.android.sdk.internal.database.query.findByAlias
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.network.executeRequest
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ internal interface GetRoomIdByAliasTask : Task<GetRoomIdByAliasTask.Params, Opti
|
|||||||
|
|
||||||
internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val roomAPI: RoomAPI,
|
private val directoryAPI: DirectoryAPI,
|
||||||
private val eventBus: EventBus
|
private val eventBus: EventBus
|
||||||
) : GetRoomIdByAliasTask {
|
) : GetRoomIdByAliasTask {
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
|||||||
} else {
|
} else {
|
||||||
roomId = tryOrNull("## Failed to get roomId from alias") {
|
roomId = tryOrNull("## Failed to get roomId from alias") {
|
||||||
executeRequest<RoomAliasDescription>(eventBus) {
|
executeRequest<RoomAliasDescription>(eventBus) {
|
||||||
apiCall = roomAPI.getRoomIdByAlias(params.roomAlias)
|
apiCall = directoryAPI.getRoomIdByAlias(params.roomAlias)
|
||||||
}
|
}
|
||||||
}?.roomId
|
}?.roomId
|
||||||
Optional.from(roomId)
|
Optional.from(roomId)
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface GetRoomLocalAliasesTask : Task<GetRoomLocalAliasesTask.Params, List<String>> {
|
||||||
|
data class Params(
|
||||||
|
val roomId: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultGetRoomLocalAliasesTask @Inject constructor(
|
||||||
|
private val roomAPI: RoomAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) : GetRoomLocalAliasesTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: GetRoomLocalAliasesTask.Params): List<String> {
|
||||||
|
// We do not check for "org.matrix.msc2432", so the API may be missing
|
||||||
|
val response = executeRequest<GetAliasesResponse>(eventBus) {
|
||||||
|
apiCall = roomAPI.getAliases(roomId = params.roomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.aliases
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.alias
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class RoomAliasAvailabilityChecker @Inject constructor(
|
||||||
|
@UserId private val userId: String,
|
||||||
|
private val directoryAPI: DirectoryAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* @param aliasLocalPart the local part of the alias.
|
||||||
|
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||||
|
*/
|
||||||
|
@Throws(RoomAliasError::class)
|
||||||
|
suspend fun check(aliasLocalPart: String?) {
|
||||||
|
if (aliasLocalPart.isNullOrEmpty()) {
|
||||||
|
throw RoomAliasError.AliasEmpty
|
||||||
|
}
|
||||||
|
// Check alias availability
|
||||||
|
val fullAlias = aliasLocalPart.toFullLocalAlias(userId)
|
||||||
|
try {
|
||||||
|
executeRequest<RoomAliasDescription>(eventBus) {
|
||||||
|
apiCall = directoryAPI.getRoomIdByAlias(fullAlias)
|
||||||
|
}
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
||||||
|
// This is a 404, so the alias is available: nominal case
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
// Other error, propagate it
|
||||||
|
throw throwable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?.let {
|
||||||
|
// Alias already exists: error case
|
||||||
|
throw RoomAliasError.AliasNotAvailable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun String.toFullLocalAlias(userId: String) = "#" + this + ":" + userId.substringAfter(":")
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import kotlinx.coroutines.TimeoutCancellationException
|
|||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.failure.MatrixError
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||||
@ -31,10 +32,9 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
|||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
|
||||||
import org.matrix.android.sdk.internal.network.executeRequest
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasAvailabilityChecker
|
||||||
import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask
|
import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
@ -47,8 +47,8 @@ internal interface CreateRoomTask : Task<CreateRoomParams, String>
|
|||||||
|
|
||||||
internal class DefaultCreateRoomTask @Inject constructor(
|
internal class DefaultCreateRoomTask @Inject constructor(
|
||||||
private val roomAPI: RoomAPI,
|
private val roomAPI: RoomAPI,
|
||||||
@UserId private val userId: String,
|
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
|
private val aliasAvailabilityChecker: RoomAliasAvailabilityChecker,
|
||||||
private val directChatsHelper: DirectChatsHelper,
|
private val directChatsHelper: DirectChatsHelper,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
private val readMarkersTask: SetReadMarkersTask,
|
private val readMarkersTask: SetReadMarkersTask,
|
||||||
@ -65,27 +65,10 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||||||
} else null
|
} else null
|
||||||
|
|
||||||
if (params.preset == CreateRoomPreset.PRESET_PUBLIC_CHAT) {
|
if (params.preset == CreateRoomPreset.PRESET_PUBLIC_CHAT) {
|
||||||
if (params.roomAliasName.isNullOrEmpty()) {
|
|
||||||
throw CreateRoomFailure.RoomAliasError.AliasEmpty
|
|
||||||
}
|
|
||||||
// Check alias availability
|
|
||||||
val fullAlias = "#" + params.roomAliasName + ":" + userId.substringAfter(":")
|
|
||||||
try {
|
try {
|
||||||
executeRequest<RoomAliasDescription>(eventBus) {
|
aliasAvailabilityChecker.check(params.roomAliasName)
|
||||||
apiCall = roomAPI.getRoomIdByAlias(fullAlias)
|
} catch (aliasError: RoomAliasError) {
|
||||||
}
|
throw CreateRoomFailure.AliasError(aliasError)
|
||||||
} catch (throwable: Throwable) {
|
|
||||||
if (throwable is Failure.ServerError && throwable.httpCode == 404) {
|
|
||||||
// This is a 404, so the alias is available: nominal case
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
// Other error, propagate it
|
|
||||||
throw throwable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?.let {
|
|
||||||
// Alias already exists: error case
|
|
||||||
throw CreateRoomFailure.RoomAliasError.AliasNotAvailable
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +87,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||||||
} else if (throwable.httpCode == 400
|
} else if (throwable.httpCode == 400
|
||||||
&& throwable.error.code == MatrixError.M_UNKNOWN
|
&& throwable.error.code == MatrixError.M_UNKNOWN
|
||||||
&& throwable.error.message == "Invalid characters in room alias") {
|
&& throwable.error.message == "Invalid characters in room alias") {
|
||||||
throw CreateRoomFailure.RoomAliasError.AliasInvalid
|
throw CreateRoomFailure.AliasError(RoomAliasError.AliasInvalid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw throwable
|
throw throwable
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.directory
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.RoomDirectoryVisibilityJson
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface GetRoomDirectoryVisibilityTask : Task<GetRoomDirectoryVisibilityTask.Params, RoomDirectoryVisibility> {
|
||||||
|
data class Params(
|
||||||
|
val roomId: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultGetRoomDirectoryVisibilityTask @Inject constructor(
|
||||||
|
private val directoryAPI: DirectoryAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) : GetRoomDirectoryVisibilityTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: GetRoomDirectoryVisibilityTask.Params): RoomDirectoryVisibility {
|
||||||
|
return executeRequest<RoomDirectoryVisibilityJson>(eventBus) {
|
||||||
|
apiCall = directoryAPI.getRoomDirectoryVisibility(params.roomId)
|
||||||
|
}
|
||||||
|
.visibility
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.room.directory
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
|
import org.matrix.android.sdk.internal.session.directory.RoomDirectoryVisibilityJson
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface SetRoomDirectoryVisibilityTask : Task<SetRoomDirectoryVisibilityTask.Params, Unit> {
|
||||||
|
data class Params(
|
||||||
|
val roomId: String,
|
||||||
|
val roomDirectoryVisibility: RoomDirectoryVisibility
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultSetRoomDirectoryVisibilityTask @Inject constructor(
|
||||||
|
private val directoryAPI: DirectoryAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) : SetRoomDirectoryVisibilityTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: SetRoomDirectoryVisibilityTask.Params) {
|
||||||
|
executeRequest<Unit>(eventBus) {
|
||||||
|
apiCall = directoryAPI.setRoomDirectoryVisibility(
|
||||||
|
params.roomId,
|
||||||
|
RoomDirectoryVisibilityJson(visibility = params.roomDirectoryVisibility)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,6 @@ import org.matrix.android.sdk.R
|
|||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomAliasesContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||||
@ -71,12 +70,6 @@ internal class RoomDisplayNameResolver @Inject constructor(
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
val aliases = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ALIASES, stateKey = "")?.root
|
|
||||||
name = ContentMapper.map(aliases?.content).toModel<RoomAliasesContent>()?.aliases?.firstOrNull()
|
|
||||||
if (!name.isNullOrEmpty()) {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||||
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
|
||||||
|
|
||||||
|
@ -24,7 +24,13 @@ import org.matrix.android.sdk.api.MatrixCallback
|
|||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||||
import org.matrix.android.sdk.api.session.room.state.StateService
|
import org.matrix.android.sdk.api.session.room.state.StateService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
@ -104,18 +110,19 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addRoomAlias(roomAlias: String, callback: MatrixCallback<Unit>): Cancelable {
|
override fun updateCanonicalAlias(alias: String?, altAliases: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
return addRoomAliasTask
|
|
||||||
.configureWith(AddRoomAliasTask.Params(roomId, roomAlias)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable {
|
|
||||||
return sendStateEvent(
|
return sendStateEvent(
|
||||||
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
eventType = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||||
body = mapOf("alias" to alias),
|
body = RoomCanonicalAliasContent(
|
||||||
|
canonicalAlias = alias,
|
||||||
|
alternativeAliases = altAliases
|
||||||
|
// Ensure there is no duplicate
|
||||||
|
.distinct()
|
||||||
|
// Ensure the canonical alias is not also included in the alt alias
|
||||||
|
.minus(listOfNotNull(alias))
|
||||||
|
// Sort for the cleanup
|
||||||
|
.sorted()
|
||||||
|
).toContent(),
|
||||||
callback = callback,
|
callback = callback,
|
||||||
stateKey = null
|
stateKey = null
|
||||||
)
|
)
|
||||||
@ -130,6 +137,31 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
|
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||||
|
if (joinRules != null) {
|
||||||
|
awaitCallback<Unit> {
|
||||||
|
sendStateEvent(
|
||||||
|
eventType = EventType.STATE_ROOM_JOIN_RULES,
|
||||||
|
body = RoomJoinRulesContent(joinRules).toContent(),
|
||||||
|
callback = it,
|
||||||
|
stateKey = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (guestAccess != null) {
|
||||||
|
awaitCallback<Unit> {
|
||||||
|
sendStateEvent(
|
||||||
|
eventType = EventType.STATE_ROOM_GUEST_ACCESS,
|
||||||
|
body = RoomGuestAccessContent(guestAccess).toContent(),
|
||||||
|
callback = it,
|
||||||
|
stateKey = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun updateAvatar(avatarUri: Uri, fileName: String, callback: MatrixCallback<Unit>): Cancelable {
|
override fun updateAvatar(avatarUri: Uri, fileName: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||||
val response = fileUploader.uploadFromUri(avatarUri, fileName, "image/jpeg")
|
val response = fileUploader.uploadFromUri(avatarUri, fileName, "image/jpeg")
|
||||||
|
@ -18,17 +18,12 @@ package org.matrix.android.sdk.internal.session.room.uploads
|
|||||||
|
|
||||||
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 org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.uploads.GetUploadsResult
|
import org.matrix.android.sdk.api.session.room.uploads.GetUploadsResult
|
||||||
import org.matrix.android.sdk.api.session.room.uploads.UploadsService
|
import org.matrix.android.sdk.api.session.room.uploads.UploadsService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
|
||||||
|
|
||||||
internal class DefaultUploadsService @AssistedInject constructor(
|
internal class DefaultUploadsService @AssistedInject constructor(
|
||||||
@Assisted private val roomId: String,
|
@Assisted private val roomId: String,
|
||||||
private val taskExecutor: TaskExecutor,
|
|
||||||
private val getUploadsTask: GetUploadsTask,
|
private val getUploadsTask: GetUploadsTask,
|
||||||
private val cryptoService: CryptoService
|
private val cryptoService: CryptoService
|
||||||
) : UploadsService {
|
) : UploadsService {
|
||||||
@ -38,11 +33,7 @@ internal class DefaultUploadsService @AssistedInject constructor(
|
|||||||
fun create(roomId: String): UploadsService
|
fun create(roomId: String): UploadsService
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUploads(numberOfEvents: Int, since: String?, callback: MatrixCallback<GetUploadsResult>): Cancelable {
|
override suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult {
|
||||||
return getUploadsTask
|
return getUploadsTask.execute(GetUploadsTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), numberOfEvents, since))
|
||||||
.configureWith(GetUploadsTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), numberOfEvents, since)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,10 @@
|
|||||||
package org.matrix.android.sdk.internal.session.terms
|
package org.matrix.android.sdk.internal.session.terms
|
||||||
|
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
||||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
|
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
|
||||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||||
import org.matrix.android.sdk.internal.network.RetrofitFactory
|
import org.matrix.android.sdk.internal.network.RetrofitFactory
|
||||||
@ -33,8 +32,6 @@ import org.matrix.android.sdk.internal.session.sync.model.accountdata.AcceptedTe
|
|||||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.AccountDataDataSource
|
import org.matrix.android.sdk.internal.session.user.accountdata.AccountDataDataSource
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
|
||||||
import org.matrix.android.sdk.internal.task.launchToCallback
|
|
||||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.internal.util.ensureTrailingSlash
|
import org.matrix.android.sdk.internal.util.ensureTrailingSlash
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@ -49,13 +46,11 @@ internal class DefaultTermsService @Inject constructor(
|
|||||||
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
||||||
private val identityRegisterTask: IdentityRegisterTask,
|
private val identityRegisterTask: IdentityRegisterTask,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers
|
||||||
private val taskExecutor: TaskExecutor
|
|
||||||
) : TermsService {
|
) : TermsService {
|
||||||
override fun getTerms(serviceType: TermsService.ServiceType,
|
override suspend fun getTerms(serviceType: TermsService.ServiceType,
|
||||||
baseUrl: String,
|
baseUrl: String): GetTermsResponse {
|
||||||
callback: MatrixCallback<GetTermsResponse>): Cancelable {
|
return withContext(coroutineDispatchers.main) {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
|
||||||
val url = buildUrl(baseUrl, serviceType)
|
val url = buildUrl(baseUrl, serviceType)
|
||||||
val termsResponse = executeRequest<TermsResponse>(null) {
|
val termsResponse = executeRequest<TermsResponse>(null) {
|
||||||
apiCall = termsAPI.getTerms("${url}terms")
|
apiCall = termsAPI.getTerms("${url}terms")
|
||||||
@ -64,12 +59,11 @@ internal class DefaultTermsService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun agreeToTerms(serviceType: TermsService.ServiceType,
|
override suspend fun agreeToTerms(serviceType: TermsService.ServiceType,
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
agreedUrls: List<String>,
|
agreedUrls: List<String>,
|
||||||
token: String?,
|
token: String?) {
|
||||||
callback: MatrixCallback<Unit>): Cancelable {
|
withContext(coroutineDispatchers.main) {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
|
||||||
val url = buildUrl(baseUrl, serviceType)
|
val url = buildUrl(baseUrl, serviceType)
|
||||||
val tokenToUse = token?.takeIf { it.isNotEmpty() } ?: getToken(baseUrl)
|
val tokenToUse = token?.takeIf { it.isNotEmpty() } ?: getToken(baseUrl)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.matrix.android.sdk.internal.util
|
package org.matrix.android.sdk.internal.util
|
||||||
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute a Hash of a String, using md5 algorithm
|
* Compute a Hash of a String, using md5 algorithm
|
||||||
@ -26,7 +27,7 @@ fun String.md5() = try {
|
|||||||
digest.update(toByteArray())
|
digest.update(toByteArray())
|
||||||
digest.digest()
|
digest.digest()
|
||||||
.joinToString("") { String.format("%02X", it) }
|
.joinToString("") { String.format("%02X", it) }
|
||||||
.toLowerCase()
|
.toLowerCase(Locale.ROOT)
|
||||||
} catch (exc: Exception) {
|
} catch (exc: Exception) {
|
||||||
// Should not happen, but just in case
|
// Should not happen, but just in case
|
||||||
hashCode().toString()
|
hashCode().toString()
|
||||||
|
@ -246,7 +246,7 @@
|
|||||||
|
|
||||||
<plurals name="notice_room_aliases_removed">
|
<plurals name="notice_room_aliases_removed">
|
||||||
<item quantity="one">%1$s removed %2$s as an address for this room.</item>
|
<item quantity="one">%1$s removed %2$s as an address for this room.</item>
|
||||||
<item quantity="other">%1$s removed %3$s as addresses for this room.</item>
|
<item quantity="other">%1$s removed %2$s as addresses for this room.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<plurals name="notice_room_aliases_removed_by_you">
|
<plurals name="notice_room_aliases_removed_by_you">
|
||||||
@ -262,6 +262,33 @@
|
|||||||
<string name="notice_room_canonical_alias_unset">"%1$s removed the main address for this room."</string>
|
<string name="notice_room_canonical_alias_unset">"%1$s removed the main address for this room."</string>
|
||||||
<string name="notice_room_canonical_alias_unset_by_you">"You removed the main address for this room."</string>
|
<string name="notice_room_canonical_alias_unset_by_you">"You removed the main address for this room."</string>
|
||||||
|
|
||||||
|
<plurals name="notice_room_canonical_alias_alternative_added">
|
||||||
|
<item quantity="one">%1$s added the alternative address %2$s for this room.</item>
|
||||||
|
<item quantity="other">%1$s added the alternative addresses %2$s for this room.</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<plurals name="notice_room_canonical_alias_alternative_added_by_you">
|
||||||
|
<item quantity="one">You added the alternative address %1$s for this room.</item>
|
||||||
|
<item quantity="other">You added the alternative addresses %1$s for this room.</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<plurals name="notice_room_canonical_alias_alternative_removed">
|
||||||
|
<item quantity="one">%1$s removed the alternative address %2$s for this room.</item>
|
||||||
|
<item quantity="other">%1$s removed the alternative addresses %2$s for this room.</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<plurals name="notice_room_canonical_alias_alternative_removed_by_you">
|
||||||
|
<item quantity="one">You removed the alternative address %1$s for this room.</item>
|
||||||
|
<item quantity="other">You removed the alternative addresses %1$s for this room.</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<string name="notice_room_canonical_alias_alternative_changed">%1$s changed the alternative addresses for this room.</string>
|
||||||
|
<string name="notice_room_canonical_alias_alternative_changed_by_you">You changed the alternative addresses for this room.</string>
|
||||||
|
<string name="notice_room_canonical_alias_main_and_alternative_changed">%1$s changed the main and alternative addresses for this room.</string>
|
||||||
|
<string name="notice_room_canonical_alias_main_and_alternative_changed_by_you">You changed the main and alternative addresses for this room.</string>
|
||||||
|
<string name="notice_room_canonical_alias_no_change">%1$s changed the addresses for this room.</string>
|
||||||
|
<string name="notice_room_canonical_alias_no_change_by_you">You changed the addresses for this room.</string>
|
||||||
|
|
||||||
<string name="notice_room_guest_access_can_join">"%1$s has allowed guests to join the room."</string>
|
<string name="notice_room_guest_access_can_join">"%1$s has allowed guests to join the room."</string>
|
||||||
<string name="notice_room_guest_access_can_join_by_you">"You have allowed guests to join the room."</string>
|
<string name="notice_room_guest_access_can_join_by_you">"You have allowed guests to join the room."</string>
|
||||||
<string name="notice_direct_room_guest_access_can_join">"%1$s has allowed guests to join here."</string>
|
<string name="notice_direct_room_guest_access_can_join">"%1$s has allowed guests to join here."</string>
|
||||||
|
@ -43,8 +43,8 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.3.0'
|
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||||
|
|
||||||
// Log
|
// Log
|
||||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||||
|
@ -315,9 +315,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha06"
|
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha06"
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:$fragment_version"
|
|
||||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation "androidx.sharetarget:sharetarget:1.0.0"
|
implementation "androidx.sharetarget:sharetarget:1.0.0"
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
|
|
||||||
@ -362,11 +361,11 @@ dependencies {
|
|||||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||||
|
|
||||||
// Pref
|
// Pref
|
||||||
implementation 'androidx.preference:preference:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||||
implementation 'com.google.android.material:material:1.3.0-alpha02'
|
implementation 'com.google.android.material:material:1.3.0-alpha04'
|
||||||
implementation 'me.gujun.android:span:1.7'
|
implementation 'me.gujun.android:span:1.7'
|
||||||
implementation "io.noties.markwon:core:$markwon_version"
|
implementation "io.noties.markwon:core:$markwon_version"
|
||||||
implementation "io.noties.markwon:html:$markwon_version"
|
implementation "io.noties.markwon:html:$markwon_version"
|
||||||
@ -374,7 +373,7 @@ dependencies {
|
|||||||
implementation 'me.saket:better-link-movement-method:2.2.0'
|
implementation 'me.saket:better-link-movement-method:2.2.0'
|
||||||
implementation 'com.google.android:flexbox:1.1.1'
|
implementation 'com.google.android:flexbox:1.1.1'
|
||||||
implementation "androidx.autofill:autofill:$autofill_version"
|
implementation "androidx.autofill:autofill:$autofill_version"
|
||||||
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta10'
|
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
|
||||||
|
|
||||||
// Custom Tab
|
// Custom Tab
|
||||||
implementation 'androidx.browser:browser:1.2.0'
|
implementation 'androidx.browser:browser:1.2.0'
|
||||||
@ -418,7 +417,7 @@ dependencies {
|
|||||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
||||||
|
|
||||||
// gplay flavor only
|
// gplay flavor only
|
||||||
gplayImplementation('com.google.firebase:firebase-messaging:20.3.0') {
|
gplayImplementation('com.google.firebase:firebase-messaging:21.0.0') {
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<issue id="ObsoleteSdkInt" severity="error" />
|
<issue id="ObsoleteSdkInt" severity="error" />
|
||||||
<issue id="Recycle" severity="error" />
|
<issue id="Recycle" severity="error" />
|
||||||
<issue id="KotlinPropertyAccess" severity="error" />
|
<issue id="KotlinPropertyAccess" severity="error" />
|
||||||
|
<issue id="DefaultLocale" severity="error" />
|
||||||
|
|
||||||
<issue id="InvalidPackage">
|
<issue id="InvalidPackage">
|
||||||
<!-- Ignore error from HtmlCompressor lib -->
|
<!-- Ignore error from HtmlCompressor lib -->
|
||||||
@ -52,6 +53,9 @@
|
|||||||
<!-- Manifest -->
|
<!-- Manifest -->
|
||||||
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="error" />
|
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="error" />
|
||||||
|
|
||||||
|
<!-- Dependencies -->
|
||||||
|
<issue id="KtxExtensionAvailable" severity="error" />
|
||||||
|
|
||||||
<!-- Timber -->
|
<!-- Timber -->
|
||||||
<!-- This rule is failing on CI because it's marked as unknwown rule id :/-->
|
<!-- This rule is failing on CI because it's marked as unknwown rule id :/-->
|
||||||
<!-- <issue id="BinaryOperationInTimber" severity="error" />-->
|
<!-- <issue id="BinaryOperationInTimber" severity="error" />-->
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
android:id="@+id/test_linkify_coordinator"
|
android:id="@+id/test_linkify_coordinator"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/riot_secondary_text_color_status"
|
android:background="#7F70808D"
|
||||||
tools:context=".features.debug.TestLinkifyActivity">
|
tools:context=".features.debug.TestLinkifyActivity">
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
@ -41,14 +41,4 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:theme="@style/AppTheme.Status">
|
|
||||||
|
|
||||||
<include layout="@layout/demo_theme_sample" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -18,7 +18,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.google.firebase.iid.FirebaseInstanceId
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.startAddGoogleAccountIntent
|
import im.vector.app.core.utils.startAddGoogleAccountIntent
|
||||||
@ -36,29 +36,33 @@ class TestFirebaseToken @Inject constructor(private val context: AppCompatActivi
|
|||||||
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||||
status = TestStatus.RUNNING
|
status = TestStatus.RUNNING
|
||||||
try {
|
try {
|
||||||
FirebaseInstanceId.getInstance().instanceId
|
FirebaseMessaging.getInstance().token
|
||||||
.addOnCompleteListener(context) { task ->
|
.addOnCompleteListener(context) { task ->
|
||||||
if (!task.isSuccessful) {
|
if (!task.isSuccessful) {
|
||||||
val errorMsg = if (task.exception == null) "Unknown" else task.exception!!.localizedMessage
|
|
||||||
// Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated)
|
// Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated)
|
||||||
if ("SERVICE_NOT_AVAILABLE".equals(errorMsg)) {
|
description = when (val errorMsg = task.exception?.localizedMessage ?: "Unknown") {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
|
"SERVICE_NOT_AVAILABLE" -> {
|
||||||
} else if ("TOO_MANY_REGISTRATIONS".equals(errorMsg)) {
|
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
|
}
|
||||||
} else if ("ACCOUNT_MISSING".equals(errorMsg)) {
|
"TOO_MANY_REGISTRATIONS" -> {
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
|
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
|
||||||
|
}
|
||||||
|
"ACCOUNT_MISSING" -> {
|
||||||
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
|
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
startAddGoogleAccountIntent(context, activityResultLauncher)
|
startAddGoogleAccountIntent(context, activityResultLauncher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
|
}
|
||||||
|
else -> {
|
||||||
|
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
status = TestStatus.FAILED
|
status = TestStatus.FAILED
|
||||||
} else {
|
} else {
|
||||||
task.result?.token?.let { token ->
|
task.result?.let { token ->
|
||||||
val tok = token.substring(0, Math.min(8, token.length)) + "********************"
|
val tok = token.take(8) + "********************"
|
||||||
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok)
|
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok)
|
||||||
Timber.e("Retrieved FCM token success [$tok].")
|
Timber.e("Retrieved FCM token success [$tok].")
|
||||||
// Ensure it is well store in our local storage
|
// Ensure it is well store in our local storage
|
||||||
|
@ -21,7 +21,7 @@ import android.widget.Toast
|
|||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.google.android.gms.common.ConnectionResult
|
import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
import com.google.firebase.iid.FirebaseInstanceId
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.di.DefaultSharedPreferences
|
import im.vector.app.core.di.DefaultSharedPreferences
|
||||||
@ -71,14 +71,16 @@ object FcmHelper {
|
|||||||
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
|
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
|
||||||
if (checkPlayServices(activity)) {
|
if (checkPlayServices(activity)) {
|
||||||
try {
|
try {
|
||||||
FirebaseInstanceId.getInstance().instanceId
|
FirebaseMessaging.getInstance().token
|
||||||
.addOnSuccessListener(activity) { instanceIdResult ->
|
.addOnSuccessListener { token ->
|
||||||
storeFcmToken(activity, instanceIdResult.token)
|
storeFcmToken(activity, token)
|
||||||
if (registerPusher) {
|
if (registerPusher) {
|
||||||
pushersManager.registerPusherWithFcmKey(instanceIdResult.token)
|
pushersManager.registerPusherWithFcmKey(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.addOnFailureListener(activity) { e -> Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed") }
|
.addOnFailureListener { e ->
|
||||||
|
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
|
||||||
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
|
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import im.vector.app.features.crypto.recover.BootstrapMigrateBackupFragment
|
|||||||
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
|
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
|
||||||
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
|
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
|
||||||
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
|
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
|
||||||
|
import im.vector.app.features.crypto.verification.QuadSLoadingFragment
|
||||||
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
|
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
|
||||||
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
|
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
|
||||||
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
|
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
|
||||||
@ -83,6 +84,7 @@ import im.vector.app.features.roomprofile.RoomProfileFragment
|
|||||||
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
||||||
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
||||||
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
||||||
|
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
|
||||||
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
||||||
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
|
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
|
||||||
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
|
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
|
||||||
@ -363,6 +365,11 @@ interface FragmentModule {
|
|||||||
@FragmentKey(RoomSettingsFragment::class)
|
@FragmentKey(RoomSettingsFragment::class)
|
||||||
fun bindRoomSettingsFragment(fragment: RoomSettingsFragment): Fragment
|
fun bindRoomSettingsFragment(fragment: RoomSettingsFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(RoomAliasFragment::class)
|
||||||
|
fun bindRoomAliasFragment(fragment: RoomAliasFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(RoomMemberProfileFragment::class)
|
@FragmentKey(RoomMemberProfileFragment::class)
|
||||||
@ -418,6 +425,11 @@ interface FragmentModule {
|
|||||||
@FragmentKey(VerificationCancelFragment::class)
|
@FragmentKey(VerificationCancelFragment::class)
|
||||||
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment
|
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(QuadSLoadingFragment::class)
|
||||||
|
fun bindQuadSLoadingFragment(fragment: QuadSLoadingFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(VerificationNotMeFragment::class)
|
@FragmentKey(VerificationNotMeFragment::class)
|
||||||
|
@ -67,6 +67,9 @@ import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
|
|||||||
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
|
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
|
||||||
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
|
import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
|
||||||
import im.vector.app.features.roomprofile.RoomProfileActivity
|
import im.vector.app.features.roomprofile.RoomProfileActivity
|
||||||
|
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
|
||||||
|
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
|
||||||
|
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet
|
||||||
import im.vector.app.features.settings.VectorSettingsActivity
|
import im.vector.app.features.settings.VectorSettingsActivity
|
||||||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
|
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
|
||||||
import im.vector.app.features.share.IncomingShareActivity
|
import im.vector.app.features.share.IncomingShareActivity
|
||||||
@ -153,6 +156,9 @@ interface ScreenComponent {
|
|||||||
fun inject(bottomSheet: ViewEditHistoryBottomSheet)
|
fun inject(bottomSheet: ViewEditHistoryBottomSheet)
|
||||||
fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
|
fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
|
||||||
fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
|
fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
|
||||||
|
fun inject(bottomSheet: RoomAliasBottomSheet)
|
||||||
|
fun inject(bottomSheet: RoomHistoryVisibilityBottomSheet)
|
||||||
|
fun inject(bottomSheet: RoomJoinRuleBottomSheet)
|
||||||
fun inject(bottomSheet: VerificationBottomSheet)
|
fun inject(bottomSheet: VerificationBottomSheet)
|
||||||
fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
|
fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
|
||||||
fun inject(bottomSheet: DeviceListBottomSheet)
|
fun inject(bottomSheet: DeviceListBottomSheet)
|
||||||
|
@ -35,6 +35,9 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
|
|||||||
import im.vector.app.features.reactions.EmojiChooserViewModel
|
import im.vector.app.features.reactions.EmojiChooserViewModel
|
||||||
import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
|
import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
|
||||||
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
||||||
|
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedActionViewModel
|
||||||
|
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilitySharedActionViewModel
|
||||||
|
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel
|
||||||
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
|
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@ -105,6 +108,21 @@ interface ViewModelModule {
|
|||||||
@ViewModelKey(RoomListQuickActionsSharedActionViewModel::class)
|
@ViewModelKey(RoomListQuickActionsSharedActionViewModel::class)
|
||||||
fun bindRoomListQuickActionsSharedActionViewModel(viewModel: RoomListQuickActionsSharedActionViewModel): ViewModel
|
fun bindRoomListQuickActionsSharedActionViewModel(viewModel: RoomListQuickActionsSharedActionViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(RoomAliasBottomSheetSharedActionViewModel::class)
|
||||||
|
fun bindRoomAliasBottomSheetSharedActionViewModel(viewModel: RoomAliasBottomSheetSharedActionViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(RoomHistoryVisibilitySharedActionViewModel::class)
|
||||||
|
fun bindRoomHistoryVisibilitySharedActionViewModel(viewModel: RoomHistoryVisibilitySharedActionViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(RoomJoinRuleSharedActionViewModel::class)
|
||||||
|
fun bindRoomJoinRuleSharedActionViewModel(viewModel: RoomJoinRuleSharedActionViewModel): ViewModel
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(RoomDirectorySharedActionViewModel::class)
|
@ViewModelKey(RoomDirectorySharedActionViewModel::class)
|
||||||
|
@ -21,6 +21,7 @@ import android.view.View
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.core.view.isInvisible
|
import androidx.core.view.isInvisible
|
||||||
@ -43,6 +44,13 @@ abstract class BottomSheetActionItem : VectorEpoxyModel<BottomSheetActionItem.Ho
|
|||||||
@DrawableRes
|
@DrawableRes
|
||||||
var iconRes: Int = 0
|
var iconRes: Int = 0
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var showIcon = true
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var text: String? = null
|
||||||
|
|
||||||
|
@StringRes
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var textRes: Int = 0
|
var textRes: Int = 0
|
||||||
|
|
||||||
@ -75,9 +83,14 @@ abstract class BottomSheetActionItem : VectorEpoxyModel<BottomSheetActionItem.Ho
|
|||||||
} else {
|
} else {
|
||||||
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
|
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
|
||||||
}
|
}
|
||||||
|
holder.icon.isVisible = showIcon
|
||||||
holder.icon.setImageResource(iconRes)
|
holder.icon.setImageResource(iconRes)
|
||||||
ImageViewCompat.setImageTintList(holder.icon, ColorStateList.valueOf(tintColor))
|
ImageViewCompat.setImageTintList(holder.icon, ColorStateList.valueOf(tintColor))
|
||||||
|
if (text != null) {
|
||||||
|
holder.text.text = text
|
||||||
|
} else {
|
||||||
holder.text.setText(textRes)
|
holder.text.setText(textRes)
|
||||||
|
}
|
||||||
holder.text.setTextColor(tintColor)
|
holder.text.setTextColor(tintColor)
|
||||||
holder.selected.isInvisible = !selected
|
holder.selected.isInvisible = !selected
|
||||||
if (showExpand) {
|
if (showExpand) {
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.app.core.epoxy.profiles
|
package im.vector.app.core.epoxy.profiles
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.view.View
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -26,8 +25,10 @@ import androidx.core.widget.ImageViewCompat
|
|||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.ClickListener
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.epoxy.onClick
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.themes.ThemeUtils
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
@ -67,11 +68,11 @@ abstract class ProfileActionItem : VectorEpoxyModel<ProfileActionItem.Holder>()
|
|||||||
var destructive: Boolean = false
|
var destructive: Boolean = false
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var listener: View.OnClickListener? = null
|
var listener: ClickListener? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.view.setOnClickListener(listener)
|
holder.view.onClick(listener)
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
holder.view.isClickable = false
|
holder.view.isClickable = false
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,7 @@ fun EpoxyController.buildProfileAction(
|
|||||||
accessoryRes(accessory)
|
accessoryRes(accessory)
|
||||||
accessoryMatrixItem(accessoryMatrixItem)
|
accessoryMatrixItem(accessoryMatrixItem)
|
||||||
avatarRenderer(avatarRenderer)
|
avatarRenderer(avatarRenderer)
|
||||||
listener { _ ->
|
listener(action)
|
||||||
action?.invoke()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (divider) {
|
if (divider) {
|
||||||
|
@ -57,3 +57,15 @@ fun EditText.setupAsSearch(@DrawableRes searchIconRes: Int = R.drawable.ic_searc
|
|||||||
return@OnTouchListener false
|
return@OnTouchListener false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the edit text value, only if necessary and move the cursor to the end of the text
|
||||||
|
*/
|
||||||
|
fun EditText.setTextSafe(value: String?) {
|
||||||
|
if (value != null && text.toString() != value) {
|
||||||
|
setText(value)
|
||||||
|
// To fix jumping cursor to the start https://github.com/airbnb/epoxy/issues/426
|
||||||
|
// Note: there is still a known bug if deleting char in the middle of the text, by long pressing on the backspace button.
|
||||||
|
setSelection(value.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ import android.net.Uri
|
|||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import im.vector.app.core.utils.getFileExtension
|
import im.vector.app.core.utils.getFileExtension
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mimetype from a uri.
|
* Returns the mimetype from a uri.
|
||||||
@ -44,7 +45,7 @@ fun getMimeTypeFromUri(context: Context, uri: Uri): String? {
|
|||||||
|
|
||||||
if (null != mimeType) {
|
if (null != mimeType) {
|
||||||
// the mimetype is sometimes in uppercase.
|
// the mimetype is sometimes in uppercase.
|
||||||
mimeType = mimeType.toLowerCase()
|
mimeType = mimeType.toLowerCase(Locale.ROOT)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "Failed to open resource input stream")
|
Timber.e(e, "Failed to open resource input stream")
|
||||||
|
@ -43,7 +43,7 @@ abstract class VectorViewModel<S : MvRxState, VA : VectorViewModelAction, VE : V
|
|||||||
* so you can use this in a switchMap or a flatMap
|
* so you can use this in a switchMap or a flatMap
|
||||||
*/
|
*/
|
||||||
// False positive
|
// False positive
|
||||||
@Suppress("USELESS_CAST")
|
@Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
|
||||||
fun <T> Single<T>.toAsync(stateReducer: S.(Async<T>) -> S): Single<Async<T>> {
|
fun <T> Single<T>.toAsync(stateReducer: S.(Async<T>) -> S): Single<Async<T>> {
|
||||||
setState { stateReducer(Loading()) }
|
setState { stateReducer(Loading()) }
|
||||||
return map { Success(it) as Async<T> }
|
return map { Success(it) as Async<T> }
|
||||||
@ -56,7 +56,7 @@ abstract class VectorViewModel<S : MvRxState, VA : VectorViewModelAction, VE : V
|
|||||||
* so you can use this in a switchMap or a flatMap
|
* so you can use this in a switchMap or a flatMap
|
||||||
*/
|
*/
|
||||||
// False positive
|
// False positive
|
||||||
@Suppress("USELESS_CAST")
|
@Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
|
||||||
fun <T> Observable<T>.toAsync(stateReducer: S.(Async<T>) -> S): Observable<Async<T>> {
|
fun <T> Observable<T>.toAsync(stateReducer: S.(Async<T>) -> S): Observable<Async<T>> {
|
||||||
setState { stateReducer(Loading()) }
|
setState { stateReducer(Loading()) }
|
||||||
return map { Success(it) as Async<T> }
|
return map { Success(it) as Async<T> }
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.annotation.CallSuper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import butterknife.BindView
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.cleanup
|
||||||
|
import im.vector.app.core.extensions.configureWith
|
||||||
|
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic Bottom sheet with actions
|
||||||
|
*/
|
||||||
|
abstract class BottomSheetGeneric<STATE : BottomSheetGenericState, ACTION : BottomSheetGenericAction> :
|
||||||
|
VectorBaseBottomSheetDialogFragment(),
|
||||||
|
BottomSheetGenericController.Listener<ACTION> {
|
||||||
|
|
||||||
|
@Inject lateinit var sharedViewPool: RecyclerView.RecycledViewPool
|
||||||
|
|
||||||
|
@BindView(R.id.bottomSheetRecyclerView)
|
||||||
|
lateinit var recyclerView: RecyclerView
|
||||||
|
|
||||||
|
final override val showExpanded = true
|
||||||
|
|
||||||
|
final override fun getLayoutResId() = R.layout.bottom_sheet_generic_list
|
||||||
|
|
||||||
|
abstract fun getController(): BottomSheetGenericController<STATE, ACTION>
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
recyclerView.configureWith(getController(), viewPool = sharedViewPool, hasFixedSize = false, disableItemAnimation = true)
|
||||||
|
getController().listener = this
|
||||||
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
override fun onDestroyView() {
|
||||||
|
recyclerView.cleanup()
|
||||||
|
getController().listener = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import im.vector.app.core.epoxy.bottomsheet.BottomSheetActionItem_
|
||||||
|
import im.vector.app.core.platform.VectorSharedAction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent class for a bottom sheet action
|
||||||
|
*/
|
||||||
|
open class BottomSheetGenericAction(
|
||||||
|
open val title: String,
|
||||||
|
@DrawableRes open val iconResId: Int,
|
||||||
|
open val isSelected: Boolean,
|
||||||
|
open val destructive: Boolean
|
||||||
|
) : VectorSharedAction {
|
||||||
|
|
||||||
|
fun toBottomSheetItem(): BottomSheetActionItem_ {
|
||||||
|
return BottomSheetActionItem_().apply {
|
||||||
|
id("action_$title")
|
||||||
|
iconRes(iconResId)
|
||||||
|
text(title)
|
||||||
|
selected(isSelected)
|
||||||
|
destructive(destructive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import im.vector.app.core.epoxy.dividerItem
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Epoxy controller for generic bottom sheet actions
|
||||||
|
*/
|
||||||
|
abstract class BottomSheetGenericController<State : BottomSheetGenericState, Action : BottomSheetGenericAction>
|
||||||
|
: TypedEpoxyController<State>() {
|
||||||
|
|
||||||
|
var listener: Listener<Action>? = null
|
||||||
|
|
||||||
|
abstract fun getTitle(): String?
|
||||||
|
|
||||||
|
open fun getSubTitle(): String? = null
|
||||||
|
|
||||||
|
abstract fun getActions(state: State): List<Action>
|
||||||
|
|
||||||
|
override fun buildModels(state: State?) {
|
||||||
|
state ?: return
|
||||||
|
// Title
|
||||||
|
getTitle()?.let { title ->
|
||||||
|
bottomSheetTitleItem {
|
||||||
|
id("title")
|
||||||
|
title(title)
|
||||||
|
subTitle(getSubTitle())
|
||||||
|
}
|
||||||
|
|
||||||
|
dividerItem {
|
||||||
|
id("title_separator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Actions
|
||||||
|
val actions = getActions(state)
|
||||||
|
val showIcons = actions.any { it.iconResId > 0 }
|
||||||
|
actions.forEach { action ->
|
||||||
|
action.toBottomSheetItem()
|
||||||
|
.showIcon(showIcons)
|
||||||
|
.listener(View.OnClickListener { listener?.didSelectAction(action) })
|
||||||
|
.addTo(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener<Action> {
|
||||||
|
fun didSelectAction(action: Action)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorSharedAction
|
||||||
|
import im.vector.app.core.platform.VectorSharedActionViewModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity shared view model to handle bottom sheet quick actions
|
||||||
|
*/
|
||||||
|
abstract class BottomSheetGenericSharedActionViewModel<Action : VectorSharedAction> : VectorSharedActionViewModel<Action>()
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
|
||||||
|
abstract class BottomSheetGenericState : MvRxState
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import im.vector.app.core.platform.EmptyAction
|
||||||
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
|
|
||||||
|
abstract class BottomSheetGenericViewModel<State : MvRxState>(initialState: State) :
|
||||||
|
VectorViewModel<State, EmptyAction, EmptyViewEvents>(initialState) {
|
||||||
|
|
||||||
|
override fun handle(action: EmptyAction) {
|
||||||
|
// No op
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package im.vector.app.core.ui.bottomsheet
|
||||||
|
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A title for bottom sheet, with an optional subtitle. It does not include the bottom separator.
|
||||||
|
*/
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_bottom_sheet_title)
|
||||||
|
abstract class BottomSheetTitleItem : VectorEpoxyModel<BottomSheetTitleItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var title: String
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var subTitle: String? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.title.text = title
|
||||||
|
holder.subtitle.setTextOrHide(subTitle)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val title by bind<TextView>(R.id.itemBottomSheetTitleTitle)
|
||||||
|
val subtitle by bind<TextView>(R.id.itemBottomSheetTitleSubtitle)
|
||||||
|
}
|
||||||
|
}
|
@ -44,7 +44,7 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun post(value: T) {
|
override fun post(value: T) {
|
||||||
behaviorRelay.accept(value)
|
behaviorRelay.accept(value!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createRelay(): BehaviorRelay<T> {
|
private fun createRelay(): BehaviorRelay<T> {
|
||||||
@ -68,6 +68,6 @@ open class PublishDataSource<T> : MutableDataSource<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun post(value: T) {
|
override fun post(value: T) {
|
||||||
publishRelay.accept(value)
|
publishRelay.accept(value!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package im.vector.app.core.utils
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
// Implementation should return true in case of success
|
// Implementation should return true in case of success
|
||||||
typealias ActionOnFile = (file: File) -> Boolean
|
typealias ActionOnFile = (file: File) -> Boolean
|
||||||
@ -113,7 +114,7 @@ fun getFileExtension(fileUri: String): String? {
|
|||||||
val ext = filename.substring(dotPos + 1)
|
val ext = filename.substring(dotPos + 1)
|
||||||
|
|
||||||
if (ext.isNotBlank()) {
|
if (ext.isNotBlank()) {
|
||||||
return ext.toLowerCase()
|
return ext.toLowerCase(Locale.ROOT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ data class AttachmentsPreviewArgs(
|
|||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
class AttachmentsPreviewFragment @Inject constructor(
|
class AttachmentsPreviewFragment @Inject constructor(
|
||||||
val viewModelFactory: AttachmentsPreviewViewModel.Factory,
|
|
||||||
private val attachmentMiniaturePreviewController: AttachmentMiniaturePreviewController,
|
private val attachmentMiniaturePreviewController: AttachmentMiniaturePreviewController,
|
||||||
private val attachmentBigPreviewController: AttachmentBigPreviewController,
|
private val attachmentBigPreviewController: AttachmentBigPreviewController,
|
||||||
private val colorProvider: ColorProvider
|
private val colorProvider: ColorProvider
|
||||||
|
@ -17,31 +17,12 @@
|
|||||||
|
|
||||||
package im.vector.app.features.attachments.preview
|
package im.vector.app.features.attachments.preview
|
||||||
|
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
|
||||||
import com.squareup.inject.assisted.Assisted
|
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
|
|
||||||
class AttachmentsPreviewViewModel @AssistedInject constructor(@Assisted initialState: AttachmentsPreviewViewState)
|
class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState)
|
||||||
: VectorViewModel<AttachmentsPreviewViewState, AttachmentsPreviewAction, AttachmentsPreviewViewEvents>(initialState) {
|
: VectorViewModel<AttachmentsPreviewViewState, AttachmentsPreviewAction, AttachmentsPreviewViewEvents>(initialState) {
|
||||||
|
|
||||||
@AssistedInject.Factory
|
|
||||||
interface Factory {
|
|
||||||
fun create(initialState: AttachmentsPreviewViewState): AttachmentsPreviewViewModel
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : MvRxViewModelFactory<AttachmentsPreviewViewModel, AttachmentsPreviewViewState> {
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
override fun create(viewModelContext: ViewModelContext, state: AttachmentsPreviewViewState): AttachmentsPreviewViewModel? {
|
|
||||||
val fragment: AttachmentsPreviewFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
|
||||||
return fragment.viewModelFactory.create(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handle(action: AttachmentsPreviewAction) {
|
override fun handle(action: AttachmentsPreviewAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action)
|
is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action)
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.crypto.verification
|
||||||
|
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class QuadSLoadingFragment @Inject constructor() : VectorBaseFragment() {
|
||||||
|
override fun getLayoutResId() = R.layout.fragment_progress
|
||||||
|
}
|
@ -31,5 +31,6 @@ sealed class VerificationAction : VectorViewModelAction {
|
|||||||
object SkipVerification : VerificationAction()
|
object SkipVerification : VerificationAction()
|
||||||
object VerifyFromPassphrase : VerificationAction()
|
object VerifyFromPassphrase : VerificationAction()
|
||||||
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
|
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
|
||||||
|
object CancelledFromSsss : VerificationAction()
|
||||||
object SecuredStorageHasBeenReset : VerificationAction()
|
object SecuredStorageHasBeenReset : VerificationAction()
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,8 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||||||
// all have been reset, so we are verified?
|
// all have been reset, so we are verified?
|
||||||
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
|
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
viewModel.handle(VerificationAction.CancelledFromSsss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +211,10 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||||||
return@withState
|
return@withState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.selfVerificationMode && state.verifyingFrom4S) {
|
||||||
|
showFragment(QuadSLoadingFragment::class, Bundle())
|
||||||
|
return@withState
|
||||||
|
}
|
||||||
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
|
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
|
||||||
showFragment(VerificationConclusionFragment::class, Bundle().apply {
|
showFragment(VerificationConclusionFragment::class, Bundle().apply {
|
||||||
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
|
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
|
||||||
|
@ -32,6 +32,7 @@ import im.vector.app.core.extensions.exhaustive
|
|||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
@ -70,6 +71,7 @@ data class VerificationBottomSheetViewState(
|
|||||||
// true when we display the loading and we wait for the other (incoming request)
|
// true when we display the loading and we wait for the other (incoming request)
|
||||||
val selfVerificationMode: Boolean = false,
|
val selfVerificationMode: Boolean = false,
|
||||||
val verifiedFromPrivateKeys: Boolean = false,
|
val verifiedFromPrivateKeys: Boolean = false,
|
||||||
|
val verifyingFrom4S: Boolean = false,
|
||||||
val isMe: Boolean = false,
|
val isMe: Boolean = false,
|
||||||
val currentDeviceCanCrossSign: Boolean = false,
|
val currentDeviceCanCrossSign: Boolean = false,
|
||||||
val userWantsToCancel: Boolean = false,
|
val userWantsToCancel: Boolean = false,
|
||||||
@ -170,7 +172,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if the verification is already done you can't cancel anymore
|
// if the verification is already done you can't cancel anymore
|
||||||
if (state.pendingRequest.invoke()?.cancelConclusion != null || state.sasTransactionState is VerificationTxState.TerminalTxState) {
|
if (state.pendingRequest.invoke()?.cancelConclusion != null
|
||||||
|
|| state.sasTransactionState is VerificationTxState.TerminalTxState
|
||||||
|
|| state.verifyingFrom4S) {
|
||||||
// you cannot cancel anymore
|
// you cannot cancel anymore
|
||||||
} else {
|
} else {
|
||||||
setState {
|
setState {
|
||||||
@ -346,6 +350,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||||||
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
||||||
}
|
}
|
||||||
is VerificationAction.VerifyFromPassphrase -> {
|
is VerificationAction.VerifyFromPassphrase -> {
|
||||||
|
setState { copy(verifyingFrom4S = true) }
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
||||||
}
|
}
|
||||||
is VerificationAction.GotResultFromSsss -> {
|
is VerificationAction.GotResultFromSsss -> {
|
||||||
@ -354,15 +359,21 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||||||
VerificationAction.SecuredStorageHasBeenReset -> {
|
VerificationAction.SecuredStorageHasBeenReset -> {
|
||||||
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
|
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
|
||||||
setState {
|
setState {
|
||||||
copy(quadSHasBeenReset = true)
|
copy(quadSHasBeenReset = true, verifyingFrom4S = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
VerificationAction.CancelledFromSsss -> {
|
||||||
|
setState {
|
||||||
|
copy(verifyingFrom4S = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||||
@ -383,27 +394,38 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
copy(verifiedFromPrivateKeys = true)
|
copy(
|
||||||
}
|
verifyingFrom4S = false,
|
||||||
|
verifiedFromPrivateKeys = true
|
||||||
// try to get keybackup key
|
)
|
||||||
} else {
|
|
||||||
// POP UP something
|
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// try the keybackup
|
// try the keybackup
|
||||||
tentativeRestoreBackup(res)
|
tentativeRestoreBackup(res)
|
||||||
Unit
|
} else {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
verifyingFrom4S = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// POP UP something
|
||||||
|
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
verifyingFrom4S = false
|
||||||
|
)
|
||||||
|
}
|
||||||
_viewEvents.post(
|
_viewEvents.post(
|
||||||
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
||||||
Timber.v("## Keybackup secret not restored from SSSS")
|
Timber.v("## Keybackup secret not restored from SSSS")
|
||||||
|
@ -27,6 +27,9 @@ import im.vector.app.core.epoxy.onClick
|
|||||||
@EpoxyModelClass(layout = R.layout.item_settings_continue_cancel)
|
@EpoxyModelClass(layout = R.layout.item_settings_continue_cancel)
|
||||||
abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinueCancelItem.Holder>() {
|
abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinueCancelItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var continueText: String? = null
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var continueOnClick: ClickListener? = null
|
var continueOnClick: ClickListener? = null
|
||||||
|
|
||||||
@ -37,6 +40,8 @@ abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinu
|
|||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
|
|
||||||
holder.cancelButton.onClick(cancelOnClick)
|
holder.cancelButton.onClick(cancelOnClick)
|
||||||
|
|
||||||
|
continueText?.let { holder.continueButton.text = it }
|
||||||
holder.continueButton.onClick(continueOnClick)
|
holder.continueButton.onClick(continueOnClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ import kotlinx.coroutines.launch
|
|||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
|
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
|
||||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
|
||||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
@ -117,9 +116,7 @@ class SetIdentityServerViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
private suspend fun checkTerms(baseUrl: String) {
|
private suspend fun checkTerms(baseUrl: String) {
|
||||||
try {
|
try {
|
||||||
val data = awaitCallback<GetTermsResponse> {
|
val data = mxSession.getTerms(TermsService.ServiceType.IdentityService, baseUrl)
|
||||||
mxSession.getTerms(TermsService.ServiceType.IdentityService, baseUrl, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
// has all been accepted?
|
// has all been accepted?
|
||||||
val resp = data.serverResponse
|
val resp = data.serverResponse
|
||||||
|
@ -26,6 +26,7 @@ import com.google.android.material.textfield.TextInputLayout
|
|||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.extensions.setTextSafe
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
import im.vector.app.core.platform.SimpleTextWatcher
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_form_text_input)
|
@EpoxyModelClass(layout = R.layout.item_form_text_input)
|
||||||
@ -65,9 +66,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||||||
holder.textInputLayout.error = errorMessage
|
holder.textInputLayout.error = errorMessage
|
||||||
|
|
||||||
// Update only if text is different and value is not null
|
// Update only if text is different and value is not null
|
||||||
if (value != null && holder.textInputEditText.text.toString() != value) {
|
holder.textInputEditText.setTextSafe(value)
|
||||||
holder.textInputEditText.setText(value)
|
|
||||||
}
|
|
||||||
holder.textInputEditText.isEnabled = enabled
|
holder.textInputEditText.isEnabled = enabled
|
||||||
inputType?.let { holder.textInputEditText.inputType = it }
|
inputType?.let { holder.textInputEditText.inputType = it }
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.google.android.material.textfield.TextInputLayout
|
|||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.extensions.setTextSafe
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
import im.vector.app.core.platform.SimpleTextWatcher
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_form_text_input_with_button)
|
@EpoxyModelClass(layout = R.layout.item_form_text_input_with_button)
|
||||||
@ -61,9 +62,7 @@ abstract class FormEditTextWithButtonItem : VectorEpoxyModel<FormEditTextWithBut
|
|||||||
holder.textInputLayout.hint = hint
|
holder.textInputLayout.hint = hint
|
||||||
|
|
||||||
// Update only if text is different
|
// Update only if text is different
|
||||||
if (holder.textInputEditText.text.toString() != value) {
|
holder.textInputEditText.setTextSafe(value)
|
||||||
holder.textInputEditText.setText(value)
|
|
||||||
}
|
|
||||||
holder.textInputEditText.isEnabled = enabled
|
holder.textInputEditText.isEnabled = enabled
|
||||||
|
|
||||||
holder.textInputEditText.addTextChangedListener(onTextChangeListener)
|
holder.textInputEditText.addTextChangedListener(onTextChangeListener)
|
||||||
|
@ -61,8 +61,8 @@ abstract class FormSwitchItem : VectorEpoxyModel<FormSwitchItem.Holder>() {
|
|||||||
|
|
||||||
holder.switchView.isEnabled = enabled
|
holder.switchView.isEnabled = enabled
|
||||||
|
|
||||||
|
holder.switchView.setOnCheckedChangeListener(null)
|
||||||
holder.switchView.isChecked = switchChecked
|
holder.switchView.isChecked = switchChecked
|
||||||
|
|
||||||
holder.switchView.setOnCheckedChangeListener { _, isChecked ->
|
holder.switchView.setOnCheckedChangeListener { _, isChecked ->
|
||||||
listener?.invoke(isChecked)
|
listener?.invoke(isChecked)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
EventType.STATE_ROOM_AVATAR,
|
EventType.STATE_ROOM_AVATAR,
|
||||||
EventType.STATE_ROOM_MEMBER,
|
EventType.STATE_ROOM_MEMBER,
|
||||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||||
EventType.STATE_ROOM_ALIASES,
|
|
||||||
EventType.STATE_ROOM_CANONICAL_ALIAS,
|
EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||||
EventType.STATE_ROOM_JOIN_RULES,
|
EventType.STATE_ROOM_JOIN_RULES,
|
||||||
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||||
@ -79,6 +78,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
encryptedItemFactory.create(event, nextEvent, highlight, callback)
|
encryptedItemFactory.create(event, nextEvent, highlight, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EventType.STATE_ROOM_ALIASES,
|
||||||
EventType.KEY_VERIFICATION_ACCEPT,
|
EventType.KEY_VERIFICATION_ACCEPT,
|
||||||
EventType.KEY_VERIFICATION_START,
|
EventType.KEY_VERIFICATION_START,
|
||||||
EventType.KEY_VERIFICATION_KEY,
|
EventType.KEY_VERIFICATION_KEY,
|
||||||
|
@ -260,13 +260,13 @@ class NoticeEventFormatter @Inject constructor(
|
|||||||
private fun formatRoomHistoryVisibilityEvent(event: Event, senderName: String?, rs: RoomSummary?): CharSequence? {
|
private fun formatRoomHistoryVisibilityEvent(event: Event, senderName: String?, rs: RoomSummary?): CharSequence? {
|
||||||
val historyVisibility = event.getClearContent().toModel<RoomHistoryVisibilityContent>()?.historyVisibility ?: return null
|
val historyVisibility = event.getClearContent().toModel<RoomHistoryVisibilityContent>()?.historyVisibility ?: return null
|
||||||
|
|
||||||
val formattedVisibility = roomHistoryVisibilityFormatter.format(historyVisibility)
|
val historyVisibilitySuffix = roomHistoryVisibilityFormatter.getNoticeSuffix(historyVisibility)
|
||||||
return if (event.isSentByCurrentUser()) {
|
return if (event.isSentByCurrentUser()) {
|
||||||
sp.getString(if (rs.isDm()) R.string.notice_made_future_direct_room_visibility_by_you else R.string.notice_made_future_room_visibility_by_you,
|
sp.getString(if (rs.isDm()) R.string.notice_made_future_direct_room_visibility_by_you else R.string.notice_made_future_room_visibility_by_you,
|
||||||
formattedVisibility)
|
historyVisibilitySuffix)
|
||||||
} else {
|
} else {
|
||||||
sp.getString(if (rs.isDm()) R.string.notice_made_future_direct_room_visibility else R.string.notice_made_future_room_visibility,
|
sp.getString(if (rs.isDm()) R.string.notice_made_future_direct_room_visibility else R.string.notice_made_future_room_visibility,
|
||||||
senderName, formattedVisibility)
|
senderName, historyVisibilitySuffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,22 +465,73 @@ class NoticeEventFormatter @Inject constructor(
|
|||||||
|
|
||||||
private fun formatRoomCanonicalAliasEvent(event: Event, senderName: String?): String? {
|
private fun formatRoomCanonicalAliasEvent(event: Event, senderName: String?): String? {
|
||||||
val eventContent: RoomCanonicalAliasContent? = event.getClearContent().toModel()
|
val eventContent: RoomCanonicalAliasContent? = event.getClearContent().toModel()
|
||||||
val canonicalAlias = eventContent?.canonicalAlias
|
val prevContent: RoomCanonicalAliasContent? = event.resolvedPrevContent().toModel()
|
||||||
return canonicalAlias
|
val canonicalAlias = eventContent?.canonicalAlias?.takeIf { it.isNotEmpty() }
|
||||||
?.takeIf { it.isNotBlank() }
|
val prevCanonicalAlias = prevContent?.canonicalAlias?.takeIf { it.isNotEmpty() }
|
||||||
?.let {
|
val altAliases = eventContent?.alternativeAliases.orEmpty()
|
||||||
|
val prevAltAliases = prevContent?.alternativeAliases.orEmpty()
|
||||||
|
val added = altAliases - prevAltAliases
|
||||||
|
val removed = prevAltAliases - altAliases
|
||||||
|
|
||||||
|
return when {
|
||||||
|
added.isEmpty() && removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||||
|
// No difference between the two events say something as we can't simply hide the event from here
|
||||||
if (event.isSentByCurrentUser()) {
|
if (event.isSentByCurrentUser()) {
|
||||||
sp.getString(R.string.notice_room_canonical_alias_set_by_you, it)
|
sp.getString(R.string.notice_room_canonical_alias_no_change_by_you)
|
||||||
} else {
|
} else {
|
||||||
sp.getString(R.string.notice_room_canonical_alias_set, senderName, it)
|
sp.getString(R.string.notice_room_canonical_alias_no_change, senderName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?: if (event.isSentByCurrentUser()) {
|
added.isEmpty() && removed.isEmpty() -> {
|
||||||
|
// Canonical has changed
|
||||||
|
if (canonicalAlias != null) {
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_set_by_you, canonicalAlias)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_set, senderName, canonicalAlias)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
sp.getString(R.string.notice_room_canonical_alias_unset_by_you)
|
sp.getString(R.string.notice_room_canonical_alias_unset_by_you)
|
||||||
} else {
|
} else {
|
||||||
sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
added.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||||
|
// Some alternative has been removed
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
|
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed_by_you, removed.size, removed.joinToString())
|
||||||
|
} else {
|
||||||
|
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_removed, removed.size, senderName, removed.joinToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removed.isEmpty() && canonicalAlias == prevCanonicalAlias -> {
|
||||||
|
// Some alternative has been added
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
|
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added_by_you, added.size, added.joinToString())
|
||||||
|
} else {
|
||||||
|
sp.getQuantityString(R.plurals.notice_room_canonical_alias_alternative_added, added.size, senderName, added.joinToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canonicalAlias == prevCanonicalAlias -> {
|
||||||
|
// Alternative added and removed
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_alternative_changed_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_alternative_changed, senderName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// Main and removed, or main and added, or main and added and removed
|
||||||
|
if (event.isSentByCurrentUser()) {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.notice_room_canonical_alias_main_and_alternative_changed, senderName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun formatRoomGuestAccessEvent(event: Event, senderName: String?, rs: RoomSummary?): String? {
|
private fun formatRoomGuestAccessEvent(event: Event, senderName: String?, rs: RoomSummary?): String? {
|
||||||
val eventContent: RoomGuestAccessContent? = event.getClearContent().toModel()
|
val eventContent: RoomGuestAccessContent? = event.getClearContent().toModel()
|
||||||
|
@ -24,13 +24,21 @@ import javax.inject.Inject
|
|||||||
class RoomHistoryVisibilityFormatter @Inject constructor(
|
class RoomHistoryVisibilityFormatter @Inject constructor(
|
||||||
private val stringProvider: StringProvider
|
private val stringProvider: StringProvider
|
||||||
) {
|
) {
|
||||||
|
fun getNoticeSuffix(roomHistoryVisibility: RoomHistoryVisibility): String {
|
||||||
fun format(roomHistoryVisibility: RoomHistoryVisibility): String {
|
return stringProvider.getString(when (roomHistoryVisibility) {
|
||||||
return when (roomHistoryVisibility) {
|
RoomHistoryVisibility.WORLD_READABLE -> R.string.notice_room_visibility_world_readable
|
||||||
RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared)
|
RoomHistoryVisibility.SHARED -> R.string.notice_room_visibility_shared
|
||||||
RoomHistoryVisibility.INVITED -> stringProvider.getString(R.string.notice_room_visibility_invited)
|
RoomHistoryVisibility.INVITED -> R.string.notice_room_visibility_invited
|
||||||
RoomHistoryVisibility.JOINED -> stringProvider.getString(R.string.notice_room_visibility_joined)
|
RoomHistoryVisibility.JOINED -> R.string.notice_room_visibility_joined
|
||||||
RoomHistoryVisibility.WORLD_READABLE -> stringProvider.getString(R.string.notice_room_visibility_world_readable)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSetting(roomHistoryVisibility: RoomHistoryVisibility): String {
|
||||||
|
return stringProvider.getString(when (roomHistoryVisibility) {
|
||||||
|
RoomHistoryVisibility.WORLD_READABLE -> R.string.room_settings_read_history_entry_anyone
|
||||||
|
RoomHistoryVisibility.SHARED -> R.string.room_settings_read_history_entry_members_only_option_time_shared
|
||||||
|
RoomHistoryVisibility.INVITED -> R.string.room_settings_read_history_entry_members_only_invited
|
||||||
|
RoomHistoryVisibility.JOINED -> R.string.room_settings_read_history_entry_members_only_joined
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R
|
|||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
recyclerView.cleanup()
|
recyclerView.cleanup()
|
||||||
|
roomListActionsEpoxyController.listener = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ class PinFragment @Inject constructor(
|
|||||||
when (fragmentArgs.pinMode) {
|
when (fragmentArgs.pinMode) {
|
||||||
PinMode.CREATE -> showCreateFragment()
|
PinMode.CREATE -> showCreateFragment()
|
||||||
PinMode.AUTH -> showAuthFragment()
|
PinMode.AUTH -> showAuthFragment()
|
||||||
|
PinMode.MODIFY -> showCreateFragment() // No need to create another function for now because texts are generic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +74,10 @@ class PinFragment @Inject constructor(
|
|||||||
Toast.makeText(requireContext(), getString(R.string.create_pin_confirm_failure), Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), getString(R.string.create_pin_confirm_failure), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPinCodeEnteredFirst(pinCode: String?): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCodeCreated(encodedCode: String) {
|
override fun onCodeCreated(encodedCode: String) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
pinCodeStore.storeEncodedPin(encodedCode)
|
pinCodeStore.storeEncodedPin(encodedCode)
|
||||||
|
@ -18,5 +18,6 @@ package im.vector.app.features.pin
|
|||||||
|
|
||||||
enum class PinMode {
|
enum class PinMode {
|
||||||
CREATE,
|
CREATE,
|
||||||
AUTH
|
AUTH,
|
||||||
|
MODIFY
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import com.airbnb.epoxy.TypedEpoxyController
|
|||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.error.ErrorFormatter
|
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.discovery.settingsSectionTitleItem
|
import im.vector.app.features.discovery.settingsSectionTitleItem
|
||||||
import im.vector.app.features.form.formAdvancedToggleItem
|
import im.vector.app.features.form.formAdvancedToggleItem
|
||||||
@ -31,8 +30,9 @@ import im.vector.app.features.form.formSwitchItem
|
|||||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CreateRoomController @Inject constructor(private val stringProvider: StringProvider,
|
class CreateRoomController @Inject constructor(
|
||||||
private val errorFormatter: ErrorFormatter
|
private val stringProvider: StringProvider,
|
||||||
|
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
||||||
) : TypedEpoxyController<CreateRoomViewState>() {
|
) : TypedEpoxyController<CreateRoomViewState>() {
|
||||||
|
|
||||||
var listener: Listener? = null
|
var listener: Listener? = null
|
||||||
@ -104,13 +104,8 @@ class CreateRoomController @Inject constructor(private val stringProvider: Strin
|
|||||||
value(viewState.roomType.aliasLocalPart)
|
value(viewState.roomType.aliasLocalPart)
|
||||||
homeServer(":" + viewState.homeServerName)
|
homeServer(":" + viewState.homeServerName)
|
||||||
errorMessage(
|
errorMessage(
|
||||||
when ((viewState.asyncCreateRoomRequest as? Fail)?.error) {
|
roomAliasErrorFormatter.format(
|
||||||
is CreateRoomFailure.RoomAliasError.AliasEmpty -> R.string.create_room_alias_empty
|
(((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
|
||||||
is CreateRoomFailure.RoomAliasError.AliasNotAvailable -> R.string.create_room_alias_already_in_use
|
|
||||||
is CreateRoomFailure.RoomAliasError.AliasInvalid -> R.string.create_room_alias_invalid
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
?.let { stringProvider.getString(it) }
|
|
||||||
)
|
)
|
||||||
onTextChange { value ->
|
onTextChange { value ->
|
||||||
listener?.setAliasLocalPart(value)
|
listener?.setAliasLocalPart(value)
|
||||||
|
@ -84,7 +84,7 @@ class CreateRoomFragment @Inject constructor(
|
|||||||
|
|
||||||
override fun showFailure(throwable: Throwable) {
|
override fun showFailure(throwable: Throwable) {
|
||||||
// Note: RoomAliasError are displayed directly in the form
|
// Note: RoomAliasError are displayed directly in the form
|
||||||
if (throwable !is CreateRoomFailure.RoomAliasError) {
|
if (throwable !is CreateRoomFailure.AliasError) {
|
||||||
super.showFailure(throwable)
|
super.showFailure(throwable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import com.google.android.material.textfield.TextInputLayout
|
|||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.extensions.setTextSafe
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
import im.vector.app.core.platform.SimpleTextWatcher
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_room_alias_text_input)
|
@EpoxyModelClass(layout = R.layout.item_room_alias_text_input)
|
||||||
@ -62,9 +63,7 @@ abstract class RoomAliasEditItem : VectorEpoxyModel<RoomAliasEditItem.Holder>()
|
|||||||
holder.textInputLayout.error = errorMessage
|
holder.textInputLayout.error = errorMessage
|
||||||
|
|
||||||
// Update only if text is different and value is not null
|
// Update only if text is different and value is not null
|
||||||
if (value != null && holder.textInputEditText.text.toString() != value) {
|
holder.textInputEditText.setTextSafe(value)
|
||||||
holder.textInputEditText.setText(value)
|
|
||||||
}
|
|
||||||
holder.textInputEditText.isEnabled = enabled
|
holder.textInputEditText.isEnabled = enabled
|
||||||
holder.textInputEditText.addTextChangedListener(onTextChangeListener)
|
holder.textInputEditText.addTextChangedListener(onTextChangeListener)
|
||||||
holder.homeServerText.text = homeServer
|
holder.homeServerText.text = homeServer
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.roomdirectory.createroom
|
||||||
|
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RoomAliasErrorFormatter @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider
|
||||||
|
) {
|
||||||
|
fun format(roomAliasError: RoomAliasError?): String? {
|
||||||
|
return when (roomAliasError) {
|
||||||
|
is RoomAliasError.AliasEmpty -> R.string.create_room_alias_empty
|
||||||
|
is RoomAliasError.AliasNotAvailable -> R.string.create_room_alias_already_in_use
|
||||||
|
is RoomAliasError.AliasInvalid -> R.string.create_room_alias_invalid
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
?.let { stringProvider.getString(it) }
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,7 @@ import im.vector.app.features.room.RequireActiveMembershipViewState
|
|||||||
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
|
||||||
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
|
||||||
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
|
||||||
|
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
|
||||||
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ class RoomProfileActivity :
|
|||||||
when (sharedAction) {
|
when (sharedAction) {
|
||||||
is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
|
is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
|
||||||
is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
|
is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
|
||||||
|
is RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias()
|
||||||
is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
|
is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
|
||||||
is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
|
is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
|
||||||
}
|
}
|
||||||
@ -135,6 +137,10 @@ class RoomProfileActivity :
|
|||||||
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomSettingsFragment::class.java, roomProfileArgs)
|
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomSettingsFragment::class.java, roomProfileArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openRoomAlias() {
|
||||||
|
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomAliasFragment::class.java, roomProfileArgs)
|
||||||
|
}
|
||||||
|
|
||||||
private fun openRoomMembers() {
|
private fun openRoomMembers() {
|
||||||
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs)
|
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import im.vector.app.core.platform.VectorSharedAction
|
|||||||
*/
|
*/
|
||||||
sealed class RoomProfileSharedAction : VectorSharedAction {
|
sealed class RoomProfileSharedAction : VectorSharedAction {
|
||||||
object OpenRoomSettings : RoomProfileSharedAction()
|
object OpenRoomSettings : RoomProfileSharedAction()
|
||||||
|
object OpenRoomAliasesSettings : RoomProfileSharedAction()
|
||||||
object OpenRoomUploads : RoomProfileSharedAction()
|
object OpenRoomUploads : RoomProfileSharedAction()
|
||||||
object OpenRoomMembers : RoomProfileSharedAction()
|
object OpenRoomMembers : RoomProfileSharedAction()
|
||||||
object OpenBannedRoomMembers : RoomProfileSharedAction()
|
object OpenBannedRoomMembers : RoomProfileSharedAction()
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.features.roomprofile.alias
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
|
||||||
|
sealed class RoomAliasAction : VectorViewModelAction {
|
||||||
|
// Canonical
|
||||||
|
object ToggleManualPublishForm : RoomAliasAction()
|
||||||
|
data class SetNewAlias(val alias: String) : RoomAliasAction()
|
||||||
|
object ManualPublishAlias : RoomAliasAction()
|
||||||
|
data class PublishAlias(val alias: String) : RoomAliasAction()
|
||||||
|
data class UnpublishAlias(val alias: String) : RoomAliasAction()
|
||||||
|
data class SetCanonicalAlias(val canonicalAlias: String?) : RoomAliasAction()
|
||||||
|
|
||||||
|
// Room directory
|
||||||
|
data class SetRoomDirectoryVisibility(val roomDirectoryVisibility: RoomDirectoryVisibility) : RoomAliasAction()
|
||||||
|
|
||||||
|
// Local
|
||||||
|
data class RemoveLocalAlias(val alias: String) : RoomAliasAction()
|
||||||
|
object ToggleAddLocalAliasForm : RoomAliasAction()
|
||||||
|
data class SetNewLocalAliasLocalPart(val aliasLocalPart: String) : RoomAliasAction()
|
||||||
|
object AddLocalAlias : RoomAliasAction()
|
||||||
|
}
|
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.features.roomprofile.alias
|
||||||
|
|
||||||
|
import android.text.InputType
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.errorWithRetryItem
|
||||||
|
import im.vector.app.core.epoxy.loadingItem
|
||||||
|
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
||||||
|
import im.vector.app.core.epoxy.profiles.profileActionItem
|
||||||
|
import im.vector.app.core.error.ErrorFormatter
|
||||||
|
import im.vector.app.core.resources.ColorProvider
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.features.discovery.settingsButtonItem
|
||||||
|
import im.vector.app.features.discovery.settingsContinueCancelItem
|
||||||
|
import im.vector.app.features.discovery.settingsInfoItem
|
||||||
|
import im.vector.app.features.form.formEditTextItem
|
||||||
|
import im.vector.app.features.form.formSwitchItem
|
||||||
|
import im.vector.app.features.roomdirectory.createroom.RoomAliasErrorFormatter
|
||||||
|
import im.vector.app.features.roomdirectory.createroom.roomAliasEditItem
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RoomAliasController @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val errorFormatter: ErrorFormatter,
|
||||||
|
private val colorProvider: ColorProvider,
|
||||||
|
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
||||||
|
) : TypedEpoxyController<RoomAliasViewState>() {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun toggleManualPublishForm()
|
||||||
|
fun setNewAlias(alias: String)
|
||||||
|
fun addAlias()
|
||||||
|
fun setRoomDirectoryVisibility(roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||||
|
fun toggleLocalAliasForm()
|
||||||
|
fun setNewLocalAliasLocalPart(aliasLocalPart: String)
|
||||||
|
fun addLocalAlias()
|
||||||
|
fun openAliasDetail(alias: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
var callback: Callback? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
setData(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildModels(data: RoomAliasViewState?) {
|
||||||
|
data ?: return
|
||||||
|
|
||||||
|
// Published alias
|
||||||
|
buildPublishInfo(data)
|
||||||
|
// Room directory visibility
|
||||||
|
buildRoomDirectoryVisibility(data)
|
||||||
|
// Local alias
|
||||||
|
buildLocalInfo(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildRoomDirectoryVisibility(data: RoomAliasViewState) {
|
||||||
|
when (data.roomDirectoryVisibility) {
|
||||||
|
Uninitialized -> Unit
|
||||||
|
is Loading -> Unit
|
||||||
|
is Success -> {
|
||||||
|
formSwitchItem {
|
||||||
|
id("roomVisibility")
|
||||||
|
title(stringProvider.getString(R.string.room_alias_publish_to_directory, data.homeServerName))
|
||||||
|
showDivider(false)
|
||||||
|
switchChecked(data.roomDirectoryVisibility() == RoomDirectoryVisibility.PUBLIC)
|
||||||
|
listener {
|
||||||
|
if (it) {
|
||||||
|
callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PUBLIC)
|
||||||
|
} else {
|
||||||
|
callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PRIVATE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Fail -> {
|
||||||
|
errorWithRetryItem {
|
||||||
|
text(stringProvider.getString(R.string.room_alias_publish_to_directory_error,
|
||||||
|
errorFormatter.toHumanReadable(data.roomDirectoryVisibility.error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPublishInfo(data: RoomAliasViewState) {
|
||||||
|
buildProfileSection(
|
||||||
|
stringProvider.getString(R.string.room_alias_published_alias_title)
|
||||||
|
)
|
||||||
|
settingsInfoItem {
|
||||||
|
id("publishedInfo")
|
||||||
|
helperTextResId(R.string.room_alias_published_alias_subtitle)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.canonicalAlias
|
||||||
|
?.takeIf { it.isNotEmpty() }
|
||||||
|
?.let { canonicalAlias ->
|
||||||
|
|
||||||
|
profileActionItem {
|
||||||
|
id("canonical")
|
||||||
|
title(data.canonicalAlias)
|
||||||
|
subtitle(stringProvider.getString(R.string.room_alias_published_alias_main))
|
||||||
|
listener { callback?.openAliasDetail(canonicalAlias) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.alternativeAliases.isEmpty()) {
|
||||||
|
settingsInfoItem {
|
||||||
|
id("otherPublishedEmpty")
|
||||||
|
if (data.actionPermissions.canChangeCanonicalAlias) {
|
||||||
|
helperTextResId(R.string.room_alias_address_empty_can_add)
|
||||||
|
} else {
|
||||||
|
helperTextResId(R.string.room_alias_address_empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
settingsInfoItem {
|
||||||
|
id("otherPublished")
|
||||||
|
helperTextResId(R.string.room_alias_published_other)
|
||||||
|
}
|
||||||
|
data.alternativeAliases.forEachIndexed { idx, altAlias ->
|
||||||
|
profileActionItem {
|
||||||
|
id("alt_$idx")
|
||||||
|
title(altAlias)
|
||||||
|
listener { callback?.openAliasDetail(altAlias) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.actionPermissions.canChangeCanonicalAlias) {
|
||||||
|
buildPublishManuallyForm(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPublishManuallyForm(data: RoomAliasViewState) {
|
||||||
|
when (data.publishManuallyState) {
|
||||||
|
RoomAliasViewState.AddAliasState.Hidden -> Unit
|
||||||
|
RoomAliasViewState.AddAliasState.Closed -> {
|
||||||
|
settingsButtonItem {
|
||||||
|
id("publishManually")
|
||||||
|
colorProvider(colorProvider)
|
||||||
|
buttonTitleId(R.string.room_alias_published_alias_add_manually)
|
||||||
|
buttonClickListener { callback?.toggleManualPublishForm() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is RoomAliasViewState.AddAliasState.Editing -> {
|
||||||
|
formEditTextItem {
|
||||||
|
id("publishManuallyEdit")
|
||||||
|
value(data.publishManuallyState.value)
|
||||||
|
showBottomSeparator(false)
|
||||||
|
hint(stringProvider.getString(R.string.room_alias_address_hint))
|
||||||
|
inputType(InputType.TYPE_CLASS_TEXT)
|
||||||
|
onTextChange { text ->
|
||||||
|
callback?.setNewAlias(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settingsContinueCancelItem {
|
||||||
|
id("publishManuallySubmit")
|
||||||
|
continueText(stringProvider.getString(R.string.room_alias_published_alias_add_manually_submit))
|
||||||
|
continueOnClick { callback?.addAlias() }
|
||||||
|
cancelOnClick { callback?.toggleManualPublishForm() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildLocalInfo(data: RoomAliasViewState) {
|
||||||
|
buildProfileSection(
|
||||||
|
stringProvider.getString(R.string.room_alias_local_address_title)
|
||||||
|
)
|
||||||
|
settingsInfoItem {
|
||||||
|
id("localInfo")
|
||||||
|
helperText(stringProvider.getString(R.string.room_alias_local_address_subtitle, data.homeServerName))
|
||||||
|
}
|
||||||
|
|
||||||
|
when (val localAliases = data.localAliases) {
|
||||||
|
is Uninitialized -> {
|
||||||
|
loadingItem {
|
||||||
|
id("loadingAliases")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Success -> {
|
||||||
|
if (localAliases().isEmpty()) {
|
||||||
|
settingsInfoItem {
|
||||||
|
id("locEmpty")
|
||||||
|
helperTextResId(R.string.room_alias_local_address_empty)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
localAliases().forEachIndexed { idx, localAlias ->
|
||||||
|
profileActionItem {
|
||||||
|
id("loc_$idx")
|
||||||
|
title(localAlias)
|
||||||
|
listener { callback?.openAliasDetail(localAlias) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is Fail -> {
|
||||||
|
errorWithRetryItem {
|
||||||
|
id("alt_error")
|
||||||
|
text(errorFormatter.toHumanReadable(localAliases.error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add local
|
||||||
|
buildAddLocalAlias(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildAddLocalAlias(data: RoomAliasViewState) {
|
||||||
|
when (data.newLocalAliasState) {
|
||||||
|
RoomAliasViewState.AddAliasState.Hidden -> Unit
|
||||||
|
RoomAliasViewState.AddAliasState.Closed -> {
|
||||||
|
settingsButtonItem {
|
||||||
|
id("newLocalAliasButton")
|
||||||
|
colorProvider(colorProvider)
|
||||||
|
buttonTitleId(R.string.room_alias_local_address_add)
|
||||||
|
buttonClickListener { callback?.toggleLocalAliasForm() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is RoomAliasViewState.AddAliasState.Editing -> {
|
||||||
|
roomAliasEditItem {
|
||||||
|
id("newLocalAlias")
|
||||||
|
value(data.newLocalAliasState.value)
|
||||||
|
homeServer(":" + data.homeServerName)
|
||||||
|
showBottomSeparator(false)
|
||||||
|
errorMessage(roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
|
||||||
|
onTextChange { value ->
|
||||||
|
callback?.setNewLocalAliasLocalPart(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settingsContinueCancelItem {
|
||||||
|
id("newLocalAliasSubmit")
|
||||||
|
continueText(stringProvider.getString(R.string.action_add))
|
||||||
|
continueOnClick { callback?.addLocalAlias() }
|
||||||
|
cancelOnClick { callback?.toggleLocalAliasForm() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.features.roomprofile.alias
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.mvrx.args
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.dialogs.withColoredButton
|
||||||
|
import im.vector.app.core.extensions.cleanup
|
||||||
|
import im.vector.app.core.extensions.configureWith
|
||||||
|
import im.vector.app.core.extensions.exhaustive
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.core.utils.shareText
|
||||||
|
import im.vector.app.core.utils.toast
|
||||||
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
|
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
|
||||||
|
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedAction
|
||||||
|
import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetSharedActionViewModel
|
||||||
|
import kotlinx.android.synthetic.main.fragment_room_setting_generic.*
|
||||||
|
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RoomAliasFragment @Inject constructor(
|
||||||
|
val viewModelFactory: RoomAliasViewModel.Factory,
|
||||||
|
private val controller: RoomAliasController,
|
||||||
|
private val avatarRenderer: AvatarRenderer
|
||||||
|
) :
|
||||||
|
VectorBaseFragment(),
|
||||||
|
RoomAliasController.Callback {
|
||||||
|
|
||||||
|
private val viewModel: RoomAliasViewModel by fragmentViewModel()
|
||||||
|
private lateinit var sharedActionViewModel: RoomAliasBottomSheetSharedActionViewModel
|
||||||
|
|
||||||
|
private val roomProfileArgs: RoomProfileArgs by args()
|
||||||
|
|
||||||
|
override fun getLayoutResId() = R.layout.fragment_room_setting_generic
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
sharedActionViewModel = activityViewModelProvider.get(RoomAliasBottomSheetSharedActionViewModel::class.java)
|
||||||
|
|
||||||
|
controller.callback = this
|
||||||
|
setupToolbar(roomSettingsToolbar)
|
||||||
|
roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true)
|
||||||
|
waiting_view_status_text.setText(R.string.please_wait)
|
||||||
|
waiting_view_status_text.isVisible = true
|
||||||
|
|
||||||
|
viewModel.observeViewEvents {
|
||||||
|
when (it) {
|
||||||
|
is RoomAliasViewEvents.Failure -> showFailure(it.throwable)
|
||||||
|
RoomAliasViewEvents.Success -> showSuccess()
|
||||||
|
}.exhaustive
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedActionViewModel
|
||||||
|
.observe()
|
||||||
|
.subscribe { handleAliasAction(it) }
|
||||||
|
.disposeOnDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAliasAction(action: RoomAliasBottomSheetSharedAction?) {
|
||||||
|
when (action) {
|
||||||
|
is RoomAliasBottomSheetSharedAction.ShareAlias -> shareAlias(action.matrixTo)
|
||||||
|
is RoomAliasBottomSheetSharedAction.PublishAlias -> viewModel.handle(RoomAliasAction.PublishAlias(action.alias))
|
||||||
|
is RoomAliasBottomSheetSharedAction.UnPublishAlias -> unpublishAlias(action.alias)
|
||||||
|
is RoomAliasBottomSheetSharedAction.DeleteAlias -> removeLocalAlias(action.alias)
|
||||||
|
is RoomAliasBottomSheetSharedAction.SetMainAlias -> viewModel.handle(RoomAliasAction.SetCanonicalAlias(action.alias))
|
||||||
|
RoomAliasBottomSheetSharedAction.UnsetMainAlias -> viewModel.handle(RoomAliasAction.SetCanonicalAlias(canonicalAlias = null))
|
||||||
|
null -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shareAlias(matrixTo: String) {
|
||||||
|
shareText(requireContext(), matrixTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showFailure(throwable: Throwable) {
|
||||||
|
if (throwable !is RoomAliasError) {
|
||||||
|
super.showFailure(throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showSuccess() {
|
||||||
|
activity?.toast(R.string.room_settings_save_success)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
controller.callback = null
|
||||||
|
roomSettingsRecyclerView.cleanup()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
|
waiting_view.isVisible = state.isLoading
|
||||||
|
controller.setData(state)
|
||||||
|
renderRoomSummary(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderRoomSummary(state: RoomAliasViewState) {
|
||||||
|
state.roomSummary()?.let {
|
||||||
|
roomSettingsToolbarTitleView.text = it.displayName
|
||||||
|
avatarRenderer.render(it.toMatrixItem(), roomSettingsToolbarAvatarImageView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unpublishAlias(alias: String) {
|
||||||
|
AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(R.string.dialog_title_confirmation)
|
||||||
|
.setMessage(getString(R.string.room_alias_unpublish_confirmation, alias))
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.setPositiveButton(R.string.action_unpublish) { _, _ ->
|
||||||
|
viewModel.handle(RoomAliasAction.UnpublishAlias(alias))
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
.withColoredButton(DialogInterface.BUTTON_POSITIVE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toggleManualPublishForm() {
|
||||||
|
viewModel.handle(RoomAliasAction.ToggleManualPublishForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setNewAlias(alias: String) {
|
||||||
|
viewModel.handle(RoomAliasAction.SetNewAlias(alias))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addAlias() {
|
||||||
|
viewModel.handle(RoomAliasAction.ManualPublishAlias)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setRoomDirectoryVisibility(roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||||
|
viewModel.handle(RoomAliasAction.SetRoomDirectoryVisibility(roomDirectoryVisibility))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toggleLocalAliasForm() {
|
||||||
|
viewModel.handle(RoomAliasAction.ToggleAddLocalAliasForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setNewLocalAliasLocalPart(aliasLocalPart: String) {
|
||||||
|
viewModel.handle(RoomAliasAction.SetNewLocalAliasLocalPart(aliasLocalPart))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addLocalAlias() {
|
||||||
|
viewModel.handle(RoomAliasAction.AddLocalAlias)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openAliasDetail(alias: String) = withState(viewModel) { state ->
|
||||||
|
RoomAliasBottomSheet
|
||||||
|
.newInstance(
|
||||||
|
alias = alias,
|
||||||
|
isPublished = alias in state.allPublishedAliases,
|
||||||
|
isMainAlias = alias == state.canonicalAlias,
|
||||||
|
isLocal = alias in state.localAliases().orEmpty(),
|
||||||
|
canEditCanonicalAlias = state.actionPermissions.canChangeCanonicalAlias
|
||||||
|
)
|
||||||
|
.show(childFragmentManager, "ROOM_ALIAS_ACTIONS")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeLocalAlias(alias: String) {
|
||||||
|
AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(R.string.dialog_title_confirmation)
|
||||||
|
.setMessage(getString(R.string.room_alias_delete_confirmation, alias))
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.setPositiveButton(R.string.delete) { _, _ ->
|
||||||
|
viewModel.handle(RoomAliasAction.RemoveLocalAlias(alias))
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
.withColoredButton(DialogInterface.BUTTON_POSITIVE)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.features.roomprofile.alias
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient events for room settings screen
|
||||||
|
*/
|
||||||
|
sealed class RoomAliasViewEvents : VectorViewEvents {
|
||||||
|
data class Failure(val throwable: Throwable) : RoomAliasViewEvents()
|
||||||
|
object Success : RoomAliasViewEvents()
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user