You've already forked element-android
mirror of
https://github.com/vector-im/element-android.git
synced 2025-08-07 14:42:55 +03:00
Merge pull request #7217 from vector-im/feature/eric/msc3881
Implements MSC3881 (enabled and device_id fields for Pusher API)
This commit is contained in:
1
changelog.d/7217.wip
Normal file
1
changelog.d/7217.wip
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Implements MSC3881: Parses `enabled` and `device_id` fields from updated Pusher API
|
@@ -1702,13 +1702,15 @@
|
|||||||
<string name="settings_push_rules_no_rules">No push rules defined</string>
|
<string name="settings_push_rules_no_rules">No push rules defined</string>
|
||||||
<string name="settings_push_gateway_no_pushers">No registered push gateways</string>
|
<string name="settings_push_gateway_no_pushers">No registered push gateways</string>
|
||||||
|
|
||||||
<string name="push_gateway_item_app_id">app_id:</string>
|
<string name="push_gateway_item_app_id">App ID:</string>
|
||||||
<string name="push_gateway_item_push_key">push_key:</string>
|
<string name="push_gateway_item_push_key">Push Key:</string>
|
||||||
<string name="push_gateway_item_app_display_name">app_display_name:</string>
|
<string name="push_gateway_item_app_display_name">App Display Name:</string>
|
||||||
<string name="push_gateway_item_device_name">session_name:</string>
|
<string name="push_gateway_item_device_name">Session Display Name:</string>
|
||||||
|
<string name="push_gateway_item_device_id">Session ID:</string>
|
||||||
<string name="push_gateway_item_url">Url:</string>
|
<string name="push_gateway_item_url">Url:</string>
|
||||||
<string name="push_gateway_item_format">Format:</string>
|
<string name="push_gateway_item_format">Format:</string>
|
||||||
<string name="push_gateway_item_profile_tag">Profile tag:</string>
|
<string name="push_gateway_item_profile_tag">Profile tag:</string>
|
||||||
|
<string name="push_gateway_item_enabled">Enabled:</string>
|
||||||
|
|
||||||
<string name="preference_voice_and_video">Voice & Video</string>
|
<string name="preference_voice_and_video">Voice & Video</string>
|
||||||
<string name="preference_root_help_about">Help & About</string>
|
<string name="preference_root_help_about">Help & About</string>
|
||||||
|
@@ -58,6 +58,16 @@ data class HttpPusher(
|
|||||||
*/
|
*/
|
||||||
val url: String,
|
val url: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the pusher should actively create push notifications.
|
||||||
|
*/
|
||||||
|
val enabled: Boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device ID of the session that registered the pusher.
|
||||||
|
*/
|
||||||
|
val deviceId: String,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
* If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
||||||
* to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
|
* to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
|
||||||
|
@@ -24,8 +24,9 @@ data class Pusher(
|
|||||||
val profileTag: String? = null,
|
val profileTag: String? = null,
|
||||||
val lang: String?,
|
val lang: String?,
|
||||||
val data: PusherData,
|
val data: PusherData,
|
||||||
|
val enabled: Boolean,
|
||||||
val state: PusherState
|
val deviceId: String?,
|
||||||
|
val state: PusherState,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@@ -33,7 +33,9 @@ internal object PushersMapper {
|
|||||||
profileTag = pushEntity.profileTag,
|
profileTag = pushEntity.profileTag,
|
||||||
lang = pushEntity.lang,
|
lang = pushEntity.lang,
|
||||||
data = PusherData(pushEntity.data?.url, pushEntity.data?.format),
|
data = PusherData(pushEntity.data?.url, pushEntity.data?.format),
|
||||||
state = pushEntity.state
|
enabled = pushEntity.enabled,
|
||||||
|
deviceId = pushEntity.deviceId,
|
||||||
|
state = pushEntity.state,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +48,9 @@ internal object PushersMapper {
|
|||||||
deviceDisplayName = pusher.deviceDisplayName,
|
deviceDisplayName = pusher.deviceDisplayName,
|
||||||
profileTag = pusher.profileTag,
|
profileTag = pusher.profileTag,
|
||||||
lang = pusher.lang,
|
lang = pusher.lang,
|
||||||
data = PusherDataEntity(pusher.data?.url, pusher.data?.format)
|
data = PusherDataEntity(pusher.data?.url, pusher.data?.format),
|
||||||
|
enabled = pusher.enabled,
|
||||||
|
deviceId = pusher.deviceId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,15 +18,6 @@ package org.matrix.android.sdk.internal.database.model
|
|||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import org.matrix.android.sdk.api.session.pushers.PusherState
|
import org.matrix.android.sdk.api.session.pushers.PusherState
|
||||||
|
|
||||||
// TODO
|
|
||||||
// at java.lang.Thread.run(Thread.java:764)
|
|
||||||
// Caused by: java.lang.IllegalArgumentException: 'value' is not a valid managed object.
|
|
||||||
// at io.realm.ProxyState.checkValidObject(ProxyState.java:213)
|
|
||||||
// at io.realm.im_vector_matrix_android_internal_database_model_PusherEntityRealmProxy
|
|
||||||
// .realmSet$data(im_vector_matrix_android_internal_database_model_PusherEntityRealmProxy.java:413)
|
|
||||||
// at org.matrix.android.sdk.internal.database.model.PusherEntity.setData(PusherEntity.kt:16)
|
|
||||||
// at org.matrix.android.sdk.internal.session.pushers.AddHttpPusherWorker$doWork$$inlined$fold$lambda$2.execute(AddHttpPusherWorker.kt:70)
|
|
||||||
// at io.realm.Realm.executeTransaction(Realm.java:1493)
|
|
||||||
internal open class PusherEntity(
|
internal open class PusherEntity(
|
||||||
var pushKey: String = "",
|
var pushKey: String = "",
|
||||||
var kind: String? = null,
|
var kind: String? = null,
|
||||||
@@ -35,7 +26,9 @@ internal open class PusherEntity(
|
|||||||
var deviceDisplayName: String? = null,
|
var deviceDisplayName: String? = null,
|
||||||
var profileTag: String? = null,
|
var profileTag: String? = null,
|
||||||
var lang: String? = null,
|
var lang: String? = null,
|
||||||
var data: PusherDataEntity? = null
|
var data: PusherDataEntity? = null,
|
||||||
|
var enabled: Boolean = true,
|
||||||
|
var deviceId: String? = null,
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
private var stateStr: String = PusherState.UNREGISTERED.name
|
private var stateStr: String = PusherState.UNREGISTERED.name
|
||||||
|
|
||||||
|
@@ -38,6 +38,7 @@ internal class DefaultAddPusherTask @Inject constructor(
|
|||||||
private val requestExecutor: RequestExecutor,
|
private val requestExecutor: RequestExecutor,
|
||||||
private val globalErrorReceiver: GlobalErrorReceiver
|
private val globalErrorReceiver: GlobalErrorReceiver
|
||||||
) : AddPusherTask {
|
) : AddPusherTask {
|
||||||
|
|
||||||
override suspend fun execute(params: AddPusherTask.Params) {
|
override suspend fun execute(params: AddPusherTask.Params) {
|
||||||
val pusher = params.pusher
|
val pusher = params.pusher
|
||||||
try {
|
try {
|
||||||
@@ -71,6 +72,8 @@ internal class DefaultAddPusherTask @Inject constructor(
|
|||||||
echo.profileTag = pusher.profileTag
|
echo.profileTag = pusher.profileTag
|
||||||
echo.data?.format = pusher.data?.format
|
echo.data?.format = pusher.data?.format
|
||||||
echo.data?.url = pusher.data?.url
|
echo.data?.url = pusher.data?.url
|
||||||
|
echo.enabled = pusher.enabled
|
||||||
|
echo.deviceId = pusher.deviceId
|
||||||
echo.state = PusherState.REGISTERED
|
echo.state = PusherState.REGISTERED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -78,7 +78,9 @@ internal class DefaultPushersService @Inject constructor(
|
|||||||
appDisplayName = appDisplayName,
|
appDisplayName = appDisplayName,
|
||||||
deviceDisplayName = deviceDisplayName,
|
deviceDisplayName = deviceDisplayName,
|
||||||
data = JsonPusherData(url, EVENT_ID_ONLY.takeIf { withEventIdOnly }),
|
data = JsonPusherData(url, EVENT_ID_ONLY.takeIf { withEventIdOnly }),
|
||||||
append = append
|
append = append,
|
||||||
|
enabled = enabled,
|
||||||
|
deviceId = deviceId,
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun addEmailPusher(
|
override suspend fun addEmailPusher(
|
||||||
|
@@ -33,6 +33,8 @@ import java.security.InvalidParameterException
|
|||||||
* "device_display_name": "Alice's Phone",
|
* "device_display_name": "Alice's Phone",
|
||||||
* "profile_tag": "xyz",
|
* "profile_tag": "xyz",
|
||||||
* "lang": "en-US",
|
* "lang": "en-US",
|
||||||
|
* "enabled": true,
|
||||||
|
* "device_id": "abc123",
|
||||||
* "data": {
|
* "data": {
|
||||||
* "url": "https://example.com/_matrix/push/v1/notify"
|
* "url": "https://example.com/_matrix/push/v1/notify"
|
||||||
* }
|
* }
|
||||||
@@ -112,7 +114,19 @@ internal data class JsonPusher(
|
|||||||
* The default is false.
|
* The default is false.
|
||||||
*/
|
*/
|
||||||
@Json(name = "append")
|
@Json(name = "append")
|
||||||
val append: Boolean? = false
|
val append: Boolean? = false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the pusher should actively create push notifications.
|
||||||
|
*/
|
||||||
|
@Json(name = "org.matrix.msc3881.enabled")
|
||||||
|
val enabled: Boolean = true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device_id of the session that registered the pusher.
|
||||||
|
*/
|
||||||
|
@Json(name = "org.matrix.msc3881.device_id")
|
||||||
|
val deviceId: String? = null,
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
// Do some parameter checks. It's ok to throw Exception, to inform developer of the problem
|
// Do some parameter checks. It's ok to throw Exception, to inform developer of the problem
|
||||||
|
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.database.mapper
|
||||||
|
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.test.fixtures.JsonPusherFixture.aJsonPusher
|
||||||
|
import org.matrix.android.sdk.test.fixtures.PusherEntityFixture.aPusherEntity
|
||||||
|
|
||||||
|
class PushersMapperTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when mapping PusherEntity, then it is mapped into Pusher successfully`() {
|
||||||
|
val pusherEntity = aPusherEntity()
|
||||||
|
|
||||||
|
val mappedPusher = PushersMapper.map(pusherEntity)
|
||||||
|
|
||||||
|
mappedPusher.pushKey shouldBeEqualTo pusherEntity.pushKey
|
||||||
|
mappedPusher.kind shouldBeEqualTo pusherEntity.kind.orEmpty()
|
||||||
|
mappedPusher.appId shouldBeEqualTo pusherEntity.appId
|
||||||
|
mappedPusher.appDisplayName shouldBeEqualTo pusherEntity.appDisplayName
|
||||||
|
mappedPusher.deviceDisplayName shouldBeEqualTo pusherEntity.deviceDisplayName
|
||||||
|
mappedPusher.profileTag shouldBeEqualTo pusherEntity.profileTag
|
||||||
|
mappedPusher.lang shouldBeEqualTo pusherEntity.lang
|
||||||
|
mappedPusher.data.url shouldBeEqualTo pusherEntity.data?.url
|
||||||
|
mappedPusher.data.format shouldBeEqualTo pusherEntity.data?.format
|
||||||
|
mappedPusher.enabled shouldBeEqualTo pusherEntity.enabled
|
||||||
|
mappedPusher.deviceId shouldBeEqualTo pusherEntity.deviceId
|
||||||
|
mappedPusher.state shouldBeEqualTo pusherEntity.state
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when mapping JsonPusher, then it is mapped into Pusher successfully`() {
|
||||||
|
val jsonPusher = aJsonPusher()
|
||||||
|
|
||||||
|
val mappedPusherEntity = PushersMapper.map(jsonPusher)
|
||||||
|
|
||||||
|
mappedPusherEntity.pushKey shouldBeEqualTo jsonPusher.pushKey
|
||||||
|
mappedPusherEntity.kind shouldBeEqualTo jsonPusher.kind
|
||||||
|
mappedPusherEntity.appId shouldBeEqualTo jsonPusher.appId
|
||||||
|
mappedPusherEntity.appDisplayName shouldBeEqualTo jsonPusher.appDisplayName
|
||||||
|
mappedPusherEntity.deviceDisplayName shouldBeEqualTo jsonPusher.deviceDisplayName
|
||||||
|
mappedPusherEntity.profileTag shouldBeEqualTo jsonPusher.profileTag
|
||||||
|
mappedPusherEntity.lang shouldBeEqualTo jsonPusher.lang
|
||||||
|
mappedPusherEntity.data?.url shouldBeEqualTo jsonPusher.data?.url
|
||||||
|
mappedPusherEntity.data?.format shouldBeEqualTo jsonPusher.data?.format
|
||||||
|
mappedPusherEntity.enabled shouldBeEqualTo jsonPusher.enabled
|
||||||
|
mappedPusherEntity.deviceId shouldBeEqualTo jsonPusher.deviceId
|
||||||
|
}
|
||||||
|
}
|
@@ -71,7 +71,7 @@ class DefaultAddPusherTaskTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given a persisted pusher when adding Pusher then updates api and mutates persisted result with Registered state`() {
|
fun `given a persisted pusher, when adding Pusher, then updates api and mutates persisted result with Registered state`() {
|
||||||
val realmResult = PusherEntity(appDisplayName = null)
|
val realmResult = PusherEntity(appDisplayName = null)
|
||||||
monarchy.givenWhereReturns(result = realmResult)
|
monarchy.givenWhereReturns(result = realmResult)
|
||||||
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
||||||
@@ -85,7 +85,7 @@ class DefaultAddPusherTaskTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given a persisted push entity and SetPush API fails when adding Pusher then mutates persisted result with Failed registration state and rethrows`() {
|
fun `given a persisted push entity and SetPush API fails, when adding Pusher, then mutates persisted result with Failed registration state and rethrows`() {
|
||||||
val realmResult = PusherEntity()
|
val realmResult = PusherEntity()
|
||||||
monarchy.givenWhereReturns(result = realmResult)
|
monarchy.givenWhereReturns(result = realmResult)
|
||||||
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
||||||
@@ -99,7 +99,7 @@ class DefaultAddPusherTaskTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given no persisted push entity and SetPush API fails when adding Pusher then rethrows error`() {
|
fun `given no persisted push entity and SetPush API fails, when adding Pusher, then rethrows error`() {
|
||||||
monarchy.givenWhereReturns<PusherEntity>(result = null)
|
monarchy.givenWhereReturns<PusherEntity>(result = null)
|
||||||
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
.givenEqualTo(PusherEntityFields.PUSH_KEY, A_JSON_PUSHER.pushKey)
|
||||||
pushersAPI.givenSetPusherErrors(SocketException())
|
pushersAPI.givenSetPusherErrors(SocketException())
|
||||||
|
49
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/JsonPusherFixture.kt
vendored
Normal file
49
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/JsonPusherFixture.kt
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.internal.session.pushers.JsonPusher
|
||||||
|
import org.matrix.android.sdk.internal.session.pushers.JsonPusherData
|
||||||
|
|
||||||
|
internal object JsonPusherFixture {
|
||||||
|
|
||||||
|
fun aJsonPusher(
|
||||||
|
pushKey: String = "",
|
||||||
|
kind: String? = null,
|
||||||
|
appId: String = "",
|
||||||
|
appDisplayName: String? = null,
|
||||||
|
deviceDisplayName: String? = null,
|
||||||
|
profileTag: String? = null,
|
||||||
|
lang: String? = null,
|
||||||
|
data: JsonPusherData? = null,
|
||||||
|
append: Boolean? = false,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
deviceId: String? = null,
|
||||||
|
) = JsonPusher(
|
||||||
|
pushKey,
|
||||||
|
kind,
|
||||||
|
appId,
|
||||||
|
appDisplayName,
|
||||||
|
deviceDisplayName,
|
||||||
|
profileTag,
|
||||||
|
lang,
|
||||||
|
data,
|
||||||
|
append,
|
||||||
|
enabled,
|
||||||
|
deviceId,
|
||||||
|
)
|
||||||
|
}
|
47
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/PusherEntityFixture.kt
vendored
Normal file
47
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/PusherEntityFixture.kt
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.internal.database.model.PusherDataEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.PusherEntity
|
||||||
|
|
||||||
|
internal object PusherEntityFixture {
|
||||||
|
|
||||||
|
fun aPusherEntity(
|
||||||
|
pushKey: String = "",
|
||||||
|
kind: String? = null,
|
||||||
|
appId: String = "",
|
||||||
|
appDisplayName: String? = null,
|
||||||
|
deviceDisplayName: String? = null,
|
||||||
|
profileTag: String? = null,
|
||||||
|
lang: String? = null,
|
||||||
|
data: PusherDataEntity? = null,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
deviceId: String? = null,
|
||||||
|
) = PusherEntity(
|
||||||
|
pushKey,
|
||||||
|
kind,
|
||||||
|
appId,
|
||||||
|
appDisplayName,
|
||||||
|
deviceDisplayName,
|
||||||
|
profileTag,
|
||||||
|
lang,
|
||||||
|
data,
|
||||||
|
enabled,
|
||||||
|
deviceId,
|
||||||
|
)
|
||||||
|
}
|
@@ -23,6 +23,10 @@ import dagger.Provides
|
|||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import im.vector.app.core.pushers.FcmHelper
|
import im.vector.app.core.pushers.FcmHelper
|
||||||
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
|
import im.vector.app.core.resources.DefaultAppNameProvider
|
||||||
|
import im.vector.app.core.resources.DefaultLocaleProvider
|
||||||
|
import im.vector.app.core.resources.LocaleProvider
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
import im.vector.app.fdroid.service.FDroidGuardServiceStarter
|
import im.vector.app.fdroid.service.FDroidGuardServiceStarter
|
||||||
import im.vector.app.features.home.NightlyProxy
|
import im.vector.app.features.home.NightlyProxy
|
||||||
@@ -59,4 +63,10 @@ abstract class FlavorModule {
|
|||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindsFcmHelper(fcmHelper: FdroidFcmHelper): FcmHelper
|
abstract fun bindsFcmHelper(fcmHelper: FdroidFcmHelper): FcmHelper
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsLocaleProvider(localeProvider: DefaultLocaleProvider): LocaleProvider
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsAppNameProvider(appNameProvider: DefaultAppNameProvider): AppNameProvider
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,10 @@ import dagger.hilt.InstallIn
|
|||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import im.vector.app.GoogleFlavorLegals
|
import im.vector.app.GoogleFlavorLegals
|
||||||
import im.vector.app.core.pushers.FcmHelper
|
import im.vector.app.core.pushers.FcmHelper
|
||||||
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
|
import im.vector.app.core.resources.DefaultAppNameProvider
|
||||||
|
import im.vector.app.core.resources.DefaultLocaleProvider
|
||||||
|
import im.vector.app.core.resources.LocaleProvider
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
import im.vector.app.features.home.NightlyProxy
|
import im.vector.app.features.home.NightlyProxy
|
||||||
import im.vector.app.features.settings.legals.FlavorLegals
|
import im.vector.app.features.settings.legals.FlavorLegals
|
||||||
@@ -46,6 +50,12 @@ abstract class FlavorModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract fun bindsFcmHelper(fcmHelper: GoogleFcmHelper): FcmHelper
|
abstract fun bindsFcmHelper(fcmHelper: GoogleFcmHelper): FcmHelper
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsLocaleProvider(localeProvider: DefaultLocaleProvider): LocaleProvider
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindsAppNameProvider(appNameProvider: DefaultAppNameProvider): AppNameProvider
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindsFlavorLegals(legals: GoogleFlavorLegals): FlavorLegals
|
abstract fun bindsFlavorLegals(legals: GoogleFlavorLegals): FlavorLegals
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,8 @@ import im.vector.app.SpaceStateHandler
|
|||||||
import im.vector.app.SpaceStateHandlerImpl
|
import im.vector.app.SpaceStateHandlerImpl
|
||||||
import im.vector.app.config.Config
|
import im.vector.app.config.Config
|
||||||
import im.vector.app.core.debug.FlipperProxy
|
import im.vector.app.core.debug.FlipperProxy
|
||||||
|
import im.vector.app.core.device.DefaultGetDeviceInfoUseCase
|
||||||
|
import im.vector.app.core.device.GetDeviceInfoUseCase
|
||||||
import im.vector.app.core.dispatchers.CoroutineDispatchers
|
import im.vector.app.core.dispatchers.CoroutineDispatchers
|
||||||
import im.vector.app.core.error.DefaultErrorFormatter
|
import im.vector.app.core.error.DefaultErrorFormatter
|
||||||
import im.vector.app.core.error.ErrorFormatter
|
import im.vector.app.core.error.ErrorFormatter
|
||||||
@@ -112,6 +114,9 @@ abstract class VectorBindModule {
|
|||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSpaceStateHandler(spaceStateHandlerImpl: SpaceStateHandlerImpl): SpaceStateHandler
|
abstract fun bindSpaceStateHandler(spaceStateHandlerImpl: SpaceStateHandlerImpl): SpaceStateHandler
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindGetDeviceInfoUseCase(getDeviceInfoUseCase: DefaultGetDeviceInfoUseCase): GetDeviceInfoUseCase
|
||||||
}
|
}
|
||||||
|
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.device
|
||||||
|
|
||||||
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface GetDeviceInfoUseCase {
|
||||||
|
|
||||||
|
fun execute(): CryptoDeviceInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultGetDeviceInfoUseCase @Inject constructor(
|
||||||
|
private val activeSessionHolder: ActiveSessionHolder
|
||||||
|
) : GetDeviceInfoUseCase {
|
||||||
|
|
||||||
|
override fun execute(): CryptoDeviceInfo {
|
||||||
|
return activeSessionHolder.getActiveSession().cryptoService().getMyDevice()
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.core.pushers
|
package im.vector.app.core.pushers
|
||||||
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.device.GetDeviceInfoUseCase
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.resources.AppNameProvider
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
import im.vector.app.core.resources.LocaleProvider
|
import im.vector.app.core.resources.LocaleProvider
|
||||||
@@ -26,7 +27,7 @@ import java.util.UUID
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
private const val DEFAULT_PUSHER_FILE_TAG = "mobile"
|
internal const val DEFAULT_PUSHER_FILE_TAG = "mobile"
|
||||||
|
|
||||||
class PushersManager @Inject constructor(
|
class PushersManager @Inject constructor(
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
@@ -34,6 +35,7 @@ class PushersManager @Inject constructor(
|
|||||||
private val localeProvider: LocaleProvider,
|
private val localeProvider: LocaleProvider,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val appNameProvider: AppNameProvider,
|
private val appNameProvider: AppNameProvider,
|
||||||
|
private val getDeviceInfoUseCase: GetDeviceInfoUseCase,
|
||||||
) {
|
) {
|
||||||
suspend fun testPush() {
|
suspend fun testPush() {
|
||||||
val currentSession = activeSessionHolder.getActiveSession()
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
@@ -63,15 +65,17 @@ class PushersManager @Inject constructor(
|
|||||||
pushKey: String,
|
pushKey: String,
|
||||||
gateway: String
|
gateway: String
|
||||||
) = HttpPusher(
|
) = HttpPusher(
|
||||||
pushKey,
|
pushkey = pushKey,
|
||||||
stringProvider.getString(R.string.pusher_app_id),
|
appId = stringProvider.getString(R.string.pusher_app_id),
|
||||||
profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()),
|
profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()),
|
||||||
localeProvider.current().language,
|
lang = localeProvider.current().language,
|
||||||
appNameProvider.getAppName(),
|
appDisplayName = appNameProvider.getAppName(),
|
||||||
activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE",
|
deviceDisplayName = getDeviceInfoUseCase.execute().displayName().orEmpty(),
|
||||||
gateway,
|
url = gateway,
|
||||||
|
enabled = true,
|
||||||
|
deviceId = activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE",
|
||||||
append = false,
|
append = false,
|
||||||
withEventIdOnly = true
|
withEventIdOnly = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun registerEmailForPush(email: String) {
|
suspend fun registerEmailForPush(email: String) {
|
||||||
|
@@ -21,9 +21,14 @@ import im.vector.app.core.utils.getApplicationLabel
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AppNameProvider @Inject constructor(private val context: Context) {
|
interface AppNameProvider {
|
||||||
|
|
||||||
fun getAppName(): String {
|
fun getAppName(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultAppNameProvider @Inject constructor(private val context: Context) : AppNameProvider {
|
||||||
|
|
||||||
|
override fun getAppName(): String {
|
||||||
return try {
|
return try {
|
||||||
val appPackageName = context.applicationContext.packageName
|
val appPackageName = context.applicationContext.packageName
|
||||||
var appName = context.getApplicationLabel(appPackageName)
|
var appName = context.getApplicationLabel(appPackageName)
|
||||||
|
@@ -23,9 +23,14 @@ import androidx.core.os.ConfigurationCompat
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LocaleProvider @Inject constructor(private val resources: Resources) {
|
interface LocaleProvider {
|
||||||
|
|
||||||
fun current(): Locale {
|
fun current(): Locale
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultLocaleProvider @Inject constructor(private val resources: Resources) : LocaleProvider {
|
||||||
|
|
||||||
|
override fun current(): Locale {
|
||||||
return ConfigurationCompat.getLocales(resources.configuration).get(0) ?: Locale.getDefault()
|
return ConfigurationCompat.getLocales(resources.configuration).get(0) ?: Locale.getDefault()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,7 @@ import androidx.core.view.marginEnd
|
|||||||
import androidx.core.view.marginStart
|
import androidx.core.view.marginStart
|
||||||
import androidx.core.view.marginTop
|
import androidx.core.view.marginTop
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.LocaleProvider
|
import im.vector.app.core.resources.DefaultLocaleProvider
|
||||||
import im.vector.app.core.resources.getLayoutDirectionFromCurrentLocale
|
import im.vector.app.core.resources.getLayoutDirectionFromCurrentLocale
|
||||||
|
|
||||||
class MessageBubbleContentLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
class MessageBubbleContentLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||||
@@ -53,7 +53,7 @@ class MessageBubbleContentLayout @JvmOverloads constructor(context: Context, att
|
|||||||
textViewStub.setOnInflateListener(null)
|
textViewStub.setOnInflateListener(null)
|
||||||
messageTextView = inflated.findViewById(R.id.messageTextView)
|
messageTextView = inflated.findViewById(R.id.messageTextView)
|
||||||
}
|
}
|
||||||
localeLayoutDirection = LocaleProvider(resources).getLayoutDirectionFromCurrentLocale()
|
localeLayoutDirection = DefaultLocaleProvider(resources).getLayoutDirectionFromCurrentLocale()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
@@ -33,7 +33,7 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.LocaleProvider
|
import im.vector.app.core.resources.DefaultLocaleProvider
|
||||||
import im.vector.app.core.resources.getLayoutDirectionFromCurrentLocale
|
import im.vector.app.core.resources.getLayoutDirectionFromCurrentLocale
|
||||||
import im.vector.app.core.utils.DimensionConverter
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
import im.vector.app.databinding.ViewMessageBubbleBinding
|
import im.vector.app.databinding.ViewMessageBubbleBinding
|
||||||
@@ -67,7 +67,7 @@ class MessageBubbleView @JvmOverloads constructor(
|
|||||||
override fun onFinishInflate() {
|
override fun onFinishInflate() {
|
||||||
super.onFinishInflate()
|
super.onFinishInflate()
|
||||||
views = ViewMessageBubbleBinding.bind(this)
|
views = ViewMessageBubbleBinding.bind(this)
|
||||||
val currentLayoutDirection = LocaleProvider(resources).getLayoutDirectionFromCurrentLocale()
|
val currentLayoutDirection = DefaultLocaleProvider(resources).getLayoutDirectionFromCurrentLocale()
|
||||||
val layoutDirectionToSet = if (isIncoming) {
|
val layoutDirectionToSet = if (isIncoming) {
|
||||||
currentLayoutDirection
|
currentLayoutDirection
|
||||||
} else {
|
} else {
|
||||||
|
@@ -50,6 +50,8 @@ abstract class PushGatewayItem : VectorEpoxyModel<PushGatewayItem.Holder>(R.layo
|
|||||||
holder.format.setTextOrHide(pusher.data.format, hideWhenBlank = true, holder.formatTitle)
|
holder.format.setTextOrHide(pusher.data.format, hideWhenBlank = true, holder.formatTitle)
|
||||||
holder.profileTag.setTextOrHide(pusher.profileTag, hideWhenBlank = true, holder.profileTagTitle)
|
holder.profileTag.setTextOrHide(pusher.profileTag, hideWhenBlank = true, holder.profileTagTitle)
|
||||||
holder.deviceName.text = pusher.deviceDisplayName
|
holder.deviceName.text = pusher.deviceDisplayName
|
||||||
|
holder.deviceId.text = pusher.deviceId ?: "null"
|
||||||
|
holder.enabled.text = pusher.enabled.toString()
|
||||||
holder.removeButton.setOnClickListener {
|
holder.removeButton.setOnClickListener {
|
||||||
interactions.onRemovePushTapped(pusher)
|
interactions.onRemovePushTapped(pusher)
|
||||||
}
|
}
|
||||||
@@ -59,10 +61,12 @@ abstract class PushGatewayItem : VectorEpoxyModel<PushGatewayItem.Holder>(R.layo
|
|||||||
val kind by bind<TextView>(R.id.pushGatewayKind)
|
val kind by bind<TextView>(R.id.pushGatewayKind)
|
||||||
val pushKey by bind<TextView>(R.id.pushGatewayKeyValue)
|
val pushKey by bind<TextView>(R.id.pushGatewayKeyValue)
|
||||||
val deviceName by bind<TextView>(R.id.pushGatewayDeviceNameValue)
|
val deviceName by bind<TextView>(R.id.pushGatewayDeviceNameValue)
|
||||||
|
val deviceId by bind<TextView>(R.id.pushGatewayDeviceIdValue)
|
||||||
val formatTitle by bind<View>(R.id.pushGatewayFormat)
|
val formatTitle by bind<View>(R.id.pushGatewayFormat)
|
||||||
val format by bind<TextView>(R.id.pushGatewayFormatValue)
|
val format by bind<TextView>(R.id.pushGatewayFormatValue)
|
||||||
val profileTagTitle by bind<TextView>(R.id.pushGatewayProfileTag)
|
val profileTagTitle by bind<TextView>(R.id.pushGatewayProfileTag)
|
||||||
val profileTag by bind<TextView>(R.id.pushGatewayProfileTagValue)
|
val profileTag by bind<TextView>(R.id.pushGatewayProfileTagValue)
|
||||||
|
val enabled by bind<TextView>(R.id.pushGatewayEnabledValue)
|
||||||
val urlTitle by bind<View>(R.id.pushGatewayURL)
|
val urlTitle by bind<View>(R.id.pushGatewayURL)
|
||||||
val url by bind<TextView>(R.id.pushGatewayURLValue)
|
val url by bind<TextView>(R.id.pushGatewayURLValue)
|
||||||
val appName by bind<TextView>(R.id.pushGatewayAppNameValue)
|
val appName by bind<TextView>(R.id.pushGatewayAppNameValue)
|
||||||
|
@@ -83,6 +83,23 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
|
tools:text="Pixel 6" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pushGatewayDeviceId"
|
||||||
|
style="@style/Widget.Vector.TextView.Body"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:text="@string/push_gateway_item_device_id"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pushGatewayDeviceIdValue"
|
||||||
|
style="@style/Widget.Vector.TextView.Body"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
tools:text="EBMDOLFJD" />
|
tools:text="EBMDOLFJD" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -135,6 +152,23 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp" />
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pushGatewayEnabled"
|
||||||
|
style="@style/Widget.Vector.TextView.Body"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:text="@string/push_gateway_item_enabled"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pushGatewayEnabledValue"
|
||||||
|
style="@style/Widget.Vector.TextView.Body"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
tools:text="true" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/pushGatewayDeleteButton"
|
android:id="@+id/pushGatewayDeleteButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.device
|
||||||
|
|
||||||
|
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||||
|
import im.vector.app.test.fakes.FakeCryptoService
|
||||||
|
import im.vector.app.test.fakes.FakeSession
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class DefaultGetDeviceInfoUseCaseTest {
|
||||||
|
|
||||||
|
private val cryptoService = FakeCryptoService()
|
||||||
|
private val session = FakeSession(fakeCryptoService = cryptoService)
|
||||||
|
private val activeSessionHolder = FakeActiveSessionHolder(session)
|
||||||
|
|
||||||
|
private val getDeviceInfoUseCase = DefaultGetDeviceInfoUseCase(activeSessionHolder.instance)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when execute, then get crypto device info`() {
|
||||||
|
val result = getDeviceInfoUseCase.execute()
|
||||||
|
|
||||||
|
result shouldBeEqualTo cryptoService.cryptoDeviceInfo
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.pushers
|
||||||
|
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||||
|
import im.vector.app.test.fakes.FakeAppNameProvider
|
||||||
|
import im.vector.app.test.fakes.FakeGetDeviceInfoUseCase
|
||||||
|
import im.vector.app.test.fakes.FakeLocaleProvider
|
||||||
|
import im.vector.app.test.fakes.FakePushersService
|
||||||
|
import im.vector.app.test.fakes.FakeSession
|
||||||
|
import im.vector.app.test.fakes.FakeStringProvider
|
||||||
|
import im.vector.app.test.fixtures.CryptoDeviceInfoFixture.aCryptoDeviceInfo
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||||
|
import org.matrix.android.sdk.api.session.pushers.HttpPusher
|
||||||
|
import java.util.Locale
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
class PushersManagerTest {
|
||||||
|
|
||||||
|
private val pushersService = FakePushersService()
|
||||||
|
private val session = FakeSession(fakePushersService = pushersService)
|
||||||
|
private val activeSessionHolder = FakeActiveSessionHolder(session)
|
||||||
|
private val stringProvider = FakeStringProvider()
|
||||||
|
private val localeProvider = FakeLocaleProvider()
|
||||||
|
private val appNameProvider = FakeAppNameProvider()
|
||||||
|
private val getDeviceInfoUseCase = FakeGetDeviceInfoUseCase()
|
||||||
|
|
||||||
|
private val pushersManager = PushersManager(
|
||||||
|
mockk(),
|
||||||
|
activeSessionHolder.instance,
|
||||||
|
localeProvider,
|
||||||
|
stringProvider.instance,
|
||||||
|
appNameProvider,
|
||||||
|
getDeviceInfoUseCase,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when enqueueRegisterPusher, then HttpPusher created and enqueued`() {
|
||||||
|
val pushKey = "abc"
|
||||||
|
val gateway = "123"
|
||||||
|
val pusherAppId = "app-id"
|
||||||
|
val appName = "element"
|
||||||
|
val deviceDisplayName = "iPhone Lollipop"
|
||||||
|
stringProvider.given(R.string.pusher_app_id, pusherAppId)
|
||||||
|
localeProvider.givenCurrent(Locale.UK)
|
||||||
|
appNameProvider.givenAppName(appName)
|
||||||
|
getDeviceInfoUseCase.givenDeviceInfo(aCryptoDeviceInfo(unsigned = UnsignedDeviceInfo(deviceDisplayName)))
|
||||||
|
val expectedHttpPusher = HttpPusher(
|
||||||
|
pushkey = pushKey,
|
||||||
|
appId = pusherAppId,
|
||||||
|
profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(session.myUserId.hashCode()),
|
||||||
|
lang = Locale.UK.language,
|
||||||
|
appDisplayName = appName,
|
||||||
|
deviceDisplayName = deviceDisplayName,
|
||||||
|
url = gateway,
|
||||||
|
enabled = true,
|
||||||
|
deviceId = session.sessionParams.deviceId!!,
|
||||||
|
append = false,
|
||||||
|
withEventIdOnly = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
pushersManager.enqueueRegisterPusher(pushKey, gateway)
|
||||||
|
|
||||||
|
val httpPusher = pushersService.verifyEnqueueAddHttpPusher()
|
||||||
|
httpPusher shouldBeEqualTo expectedHttpPusher
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes
|
||||||
|
|
||||||
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
|
||||||
|
class FakeAppNameProvider : AppNameProvider by mockk() {
|
||||||
|
|
||||||
|
fun givenAppName(appName: String) {
|
||||||
|
every { getAppName() } returns appName
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.test.fakes
|
package im.vector.app.test.fakes
|
||||||
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import im.vector.app.test.fixtures.CryptoDeviceInfoFixture.aCryptoDeviceInfo
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.slot
|
import io.mockk.slot
|
||||||
@@ -35,6 +36,7 @@ class FakeCryptoService(
|
|||||||
var cryptoDeviceInfos = mutableMapOf<String, CryptoDeviceInfo>()
|
var cryptoDeviceInfos = mutableMapOf<String, CryptoDeviceInfo>()
|
||||||
var cryptoDeviceInfoWithIdLiveData: MutableLiveData<Optional<CryptoDeviceInfo>> = MutableLiveData()
|
var cryptoDeviceInfoWithIdLiveData: MutableLiveData<Optional<CryptoDeviceInfo>> = MutableLiveData()
|
||||||
var myDevicesInfoWithIdLiveData: MutableLiveData<Optional<DeviceInfo>> = MutableLiveData()
|
var myDevicesInfoWithIdLiveData: MutableLiveData<Optional<DeviceInfo>> = MutableLiveData()
|
||||||
|
var cryptoDeviceInfo = aCryptoDeviceInfo()
|
||||||
|
|
||||||
override fun crossSigningService() = fakeCrossSigningService
|
override fun crossSigningService() = fakeCrossSigningService
|
||||||
|
|
||||||
@@ -81,4 +83,6 @@ class FakeCryptoService(
|
|||||||
thirdArg<MatrixCallback<Unit>>().onFailure(error)
|
thirdArg<MatrixCallback<Unit>>().onFailure(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getMyDevice() = cryptoDeviceInfo
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes
|
||||||
|
|
||||||
|
import im.vector.app.core.device.GetDeviceInfoUseCase
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
|
|
||||||
|
class FakeGetDeviceInfoUseCase : GetDeviceInfoUseCase by mockk() {
|
||||||
|
|
||||||
|
fun givenDeviceInfo(cryptoDeviceInfo: CryptoDeviceInfo) {
|
||||||
|
every { execute() } returns cryptoDeviceInfo
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes
|
||||||
|
|
||||||
|
import im.vector.app.core.resources.LocaleProvider
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
class FakeLocaleProvider : LocaleProvider by mockk() {
|
||||||
|
|
||||||
|
fun givenCurrent(locale: Locale) {
|
||||||
|
every { current() } returns locale
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes
|
||||||
|
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.slot
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.matrix.android.sdk.api.session.pushers.HttpPusher
|
||||||
|
import org.matrix.android.sdk.api.session.pushers.PushersService
|
||||||
|
|
||||||
|
class FakePushersService : PushersService by mockk(relaxed = true) {
|
||||||
|
|
||||||
|
fun verifyEnqueueAddHttpPusher(): HttpPusher {
|
||||||
|
val httpPusherSlot = slot<HttpPusher>()
|
||||||
|
verify { enqueueAddHttpPusher(capture(httpPusherSlot)) }
|
||||||
|
return httpPusherSlot.captured
|
||||||
|
}
|
||||||
|
}
|
@@ -41,6 +41,7 @@ class FakeSession(
|
|||||||
val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(),
|
val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(),
|
||||||
val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(),
|
val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(),
|
||||||
val fakeRoomService: FakeRoomService = FakeRoomService(),
|
val fakeRoomService: FakeRoomService = FakeRoomService(),
|
||||||
|
val fakePushersService: FakePushersService = FakePushersService(),
|
||||||
private val fakeEventService: FakeEventService = FakeEventService(),
|
private val fakeEventService: FakeEventService = FakeEventService(),
|
||||||
) : Session by mockk(relaxed = true) {
|
) : Session by mockk(relaxed = true) {
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ class FakeSession(
|
|||||||
override fun sharedSecretStorageService() = fakeSharedSecretStorageService
|
override fun sharedSecretStorageService() = fakeSharedSecretStorageService
|
||||||
override fun roomService() = fakeRoomService
|
override fun roomService() = fakeRoomService
|
||||||
override fun eventService() = fakeEventService
|
override fun eventService() = fakeEventService
|
||||||
|
override fun pushersService() = fakePushersService
|
||||||
|
|
||||||
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
|
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
|
||||||
coEvery {
|
coEvery {
|
||||||
|
46
vector/src/test/java/im/vector/app/test/fixtures/CryptoDeviceInfoFixture.kt
vendored
Normal file
46
vector/src/test/java/im/vector/app/test/fixtures/CryptoDeviceInfoFixture.kt
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||||
|
|
||||||
|
object CryptoDeviceInfoFixture {
|
||||||
|
|
||||||
|
fun aCryptoDeviceInfo(
|
||||||
|
deviceId: String = "",
|
||||||
|
userId: String = "",
|
||||||
|
algorithms: List<String>? = null,
|
||||||
|
keys: Map<String, String>? = null,
|
||||||
|
signatures: Map<String, Map<String, String>>? = null,
|
||||||
|
unsigned: UnsignedDeviceInfo? = null,
|
||||||
|
trustLevel: DeviceTrustLevel? = null,
|
||||||
|
isBlocked: Boolean = false,
|
||||||
|
firstTimeSeenLocalTs: Long? = null,
|
||||||
|
) = CryptoDeviceInfo(
|
||||||
|
deviceId,
|
||||||
|
userId,
|
||||||
|
algorithms,
|
||||||
|
keys,
|
||||||
|
signatures,
|
||||||
|
unsigned,
|
||||||
|
trustLevel,
|
||||||
|
isBlocked,
|
||||||
|
firstTimeSeenLocalTs,
|
||||||
|
)
|
||||||
|
}
|
Reference in New Issue
Block a user