Skip to content

Commit 80c210e

Browse files
authored
Merge pull request #7292 from vector-im/feature/mna/device-manager-type-icons
[Device Management] Show correct device type icons (PSG-775)
2 parents 6d2caf6 + f02b689 commit 80c210e

File tree

15 files changed

+235
-40
lines changed

15 files changed

+235
-40
lines changed

changelog.d/7277.wip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Device Management] Show correct device type icons

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -657,14 +657,7 @@ internal class RealmCryptoStore @Inject constructor(
657657
}
658658

659659
override fun saveMyDevicesInfo(info: List<DeviceInfo>) {
660-
val entities = info.map {
661-
MyDeviceLastSeenInfoEntity(
662-
lastSeenTs = it.lastSeenTs,
663-
lastSeenIp = it.lastSeenIp,
664-
displayName = it.displayName,
665-
deviceId = it.deviceId
666-
)
667-
}
660+
val entities = info.map { myDeviceLastSeenInfoEntityMapper.map(it) }
668661
doRealmTransactionAsync(realmConfiguration) { realm ->
669662
realm.where<MyDeviceLastSeenInfoEntity>().findAll().deleteAllFromRealm()
670663
entities.forEach {

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStoreMigration.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo
3636
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo017
3737
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo018
3838
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo019
39+
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo020
3940
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
4041
import org.matrix.android.sdk.internal.util.time.Clock
4142
import javax.inject.Inject
@@ -50,7 +51,7 @@ internal class RealmCryptoStoreMigration @Inject constructor(
5051
private val clock: Clock,
5152
) : MatrixRealmMigration(
5253
dbName = "Crypto",
53-
schemaVersion = 19L,
54+
schemaVersion = 20L,
5455
) {
5556
/**
5657
* Forces all RealmCryptoStoreMigration instances to be equal.
@@ -79,5 +80,6 @@ internal class RealmCryptoStoreMigration @Inject constructor(
7980
if (oldVersion < 17) MigrateCryptoTo017(realm).perform()
8081
if (oldVersion < 18) MigrateCryptoTo018(realm).perform()
8182
if (oldVersion < 19) MigrateCryptoTo019(realm).perform()
83+
if (oldVersion < 20) MigrateCryptoTo020(realm).perform()
8284
}
8385
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapper.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,18 @@ internal class MyDeviceLastSeenInfoEntityMapper @Inject constructor() {
2727
deviceId = entity.deviceId,
2828
lastSeenIp = entity.lastSeenIp,
2929
lastSeenTs = entity.lastSeenTs,
30-
displayName = entity.displayName
30+
displayName = entity.displayName,
31+
unstableLastSeenUserAgent = entity.lastSeenUserAgent,
32+
)
33+
}
34+
35+
fun map(deviceInfo: DeviceInfo): MyDeviceLastSeenInfoEntity {
36+
return MyDeviceLastSeenInfoEntity(
37+
deviceId = deviceInfo.deviceId,
38+
lastSeenIp = deviceInfo.lastSeenIp,
39+
lastSeenTs = deviceInfo.lastSeenTs,
40+
displayName = deviceInfo.displayName,
41+
lastSeenUserAgent = deviceInfo.getBestLastSeenUserAgent(),
3142
)
3243
}
3344
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo019.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator
3030
* mark existing keys as safe.
3131
* This migration can take long depending on the account
3232
*/
33-
internal class MigrateCryptoTo019(realm: DynamicRealm) : RealmMigrator(realm, 18) {
33+
internal class MigrateCryptoTo019(realm: DynamicRealm) : RealmMigrator(realm, 19) {
3434

3535
override fun doMigrate(realm: DynamicRealm) {
3636
realm.schema.get("CrossSigningInfoEntity")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.matrix.android.sdk.internal.crypto.store.db.migration
18+
19+
import io.realm.DynamicRealm
20+
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields
21+
import org.matrix.android.sdk.internal.util.database.RealmMigrator
22+
23+
/**
24+
* This migration adds a new field into MyDeviceLastSeenInfoEntity corresponding to the last seen user agent.
25+
*/
26+
internal class MigrateCryptoTo020(realm: DynamicRealm) : RealmMigrator(realm, 20) {
27+
28+
override fun doMigrate(realm: DynamicRealm) {
29+
realm.schema.get("MyDeviceLastSeenInfoEntity")
30+
?.addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_USER_AGENT, String::class.java)
31+
}
32+
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/MyDeviceLastSeenInfoEntity.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ internal open class MyDeviceLastSeenInfoEntity(
2727
/** The last time this device has been seen. */
2828
var lastSeenTs: Long? = null,
2929
/** The last ip address. */
30-
var lastSeenIp: String? = null
30+
var lastSeenIp: String? = null,
31+
/** The last user agent. */
32+
var lastSeenUserAgent: String? = null,
3133
) : RealmObject() {
3234

3335
companion object

matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/MyDeviceLastSeenInfoEntityMapperTest.kt

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,63 @@ private const val A_DEVICE_ID = "device-id"
2525
private const val AN_IP_ADDRESS = "ip-address"
2626
private const val A_TIMESTAMP = 123L
2727
private const val A_DISPLAY_NAME = "display-name"
28+
private const val A_USER_AGENT = "user-agent"
2829

2930
class MyDeviceLastSeenInfoEntityMapperTest {
3031

3132
private val myDeviceLastSeenInfoEntityMapper = MyDeviceLastSeenInfoEntityMapper()
3233

3334
@Test
3435
fun `given an entity when mapping to model then all fields are correctly mapped`() {
36+
// Given
3537
val entity = MyDeviceLastSeenInfoEntity(
3638
deviceId = A_DEVICE_ID,
3739
lastSeenIp = AN_IP_ADDRESS,
3840
lastSeenTs = A_TIMESTAMP,
39-
displayName = A_DISPLAY_NAME
41+
displayName = A_DISPLAY_NAME,
42+
lastSeenUserAgent = A_USER_AGENT,
4043
)
4144
val expectedDeviceInfo = DeviceInfo(
4245
deviceId = A_DEVICE_ID,
4346
lastSeenIp = AN_IP_ADDRESS,
4447
lastSeenTs = A_TIMESTAMP,
45-
displayName = A_DISPLAY_NAME
48+
displayName = A_DISPLAY_NAME,
49+
unstableLastSeenUserAgent = A_USER_AGENT,
4650
)
4751

52+
// When
4853
val deviceInfo = myDeviceLastSeenInfoEntityMapper.map(entity)
4954

55+
// Then
5056
deviceInfo shouldBeEqualTo expectedDeviceInfo
5157
}
58+
59+
@Test
60+
fun `given a device info when mapping to entity then all fields are correctly mapped`() {
61+
// Given
62+
val deviceInfo = DeviceInfo(
63+
deviceId = A_DEVICE_ID,
64+
lastSeenIp = AN_IP_ADDRESS,
65+
lastSeenTs = A_TIMESTAMP,
66+
displayName = A_DISPLAY_NAME,
67+
unstableLastSeenUserAgent = A_USER_AGENT,
68+
)
69+
val expectedEntity = MyDeviceLastSeenInfoEntity(
70+
deviceId = A_DEVICE_ID,
71+
lastSeenIp = AN_IP_ADDRESS,
72+
lastSeenTs = A_TIMESTAMP,
73+
displayName = A_DISPLAY_NAME,
74+
lastSeenUserAgent = A_USER_AGENT
75+
)
76+
77+
// When
78+
val entity = myDeviceLastSeenInfoEntityMapper.map(deviceInfo)
79+
80+
// Then
81+
entity.deviceId shouldBeEqualTo expectedEntity.deviceId
82+
entity.lastSeenIp shouldBeEqualTo expectedEntity.lastSeenIp
83+
entity.lastSeenTs shouldBeEqualTo expectedEntity.lastSeenTs
84+
entity.displayName shouldBeEqualTo expectedEntity.displayName
85+
entity.lastSeenUserAgent shouldBeEqualTo expectedEntity.lastSeenUserAgent
86+
}
5287
}

vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import im.vector.app.core.dialogs.ManuallyVerifyDialog
3333
import im.vector.app.core.platform.VectorBaseFragment
3434
import im.vector.app.core.resources.ColorProvider
3535
import im.vector.app.core.resources.DrawableProvider
36+
import im.vector.app.core.resources.StringProvider
3637
import im.vector.app.databinding.FragmentSettingsDevicesBinding
3738
import im.vector.app.features.crypto.recover.SetupMode
3839
import im.vector.app.features.crypto.verification.VerificationBottomSheet
@@ -61,6 +62,8 @@ class VectorSettingsDevicesFragment :
6162

6263
@Inject lateinit var colorProvider: ColorProvider
6364

65+
@Inject lateinit var stringProvider: StringProvider
66+
6467
private val viewModel: DevicesViewModel by fragmentViewModel()
6568

6669
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsDevicesBinding {
@@ -237,7 +240,7 @@ class VectorSettingsDevicesFragment :
237240
isCurrentSession = true,
238241
deviceFullInfo = it
239242
)
240-
views.deviceListCurrentSession.render(viewState, dateFormatter, drawableProvider, colorProvider)
243+
views.deviceListCurrentSession.render(viewState, dateFormatter, drawableProvider, colorProvider, stringProvider)
241244
views.deviceListCurrentSession.debouncedClicks {
242245
currentDeviceInfo.deviceInfo.deviceId?.let { deviceId -> navigateToSessionOverview(deviceId) }
243246
}

vector/src/main/java/im/vector/app/features/settings/devices/v2/list/OtherSessionItem.kt

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,16 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
5959
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
6060
var clickListener: ClickListener? = null
6161

62+
private val setDeviceTypeIconUseCase = SetDeviceTypeIconUseCase()
63+
6264
override fun bind(holder: Holder) {
6365
super.bind(holder)
6466
holder.view.onClick(clickListener)
6567
if (clickListener == null) {
6668
holder.view.isClickable = false
6769
}
6870

69-
when (deviceType) {
70-
DeviceType.MOBILE -> {
71-
holder.otherSessionDeviceTypeImageView.setImageResource(R.drawable.ic_device_type_mobile)
72-
holder.otherSessionDeviceTypeImageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_mobile)
73-
}
74-
DeviceType.WEB -> {
75-
holder.otherSessionDeviceTypeImageView.setImageResource(R.drawable.ic_device_type_web)
76-
holder.otherSessionDeviceTypeImageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_web)
77-
}
78-
DeviceType.DESKTOP -> {
79-
holder.otherSessionDeviceTypeImageView.setImageResource(R.drawable.ic_device_type_desktop)
80-
holder.otherSessionDeviceTypeImageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_desktop)
81-
}
82-
DeviceType.UNKNOWN -> {
83-
holder.otherSessionDeviceTypeImageView.setImageResource(R.drawable.ic_device_type_unknown)
84-
holder.otherSessionDeviceTypeImageView.contentDescription = stringProvider.getString(R.string.a11y_device_manager_device_type_unknown)
85-
}
86-
}
71+
setDeviceTypeIconUseCase.execute(deviceType, holder.otherSessionDeviceTypeImageView, stringProvider)
8772
holder.otherSessionVerificationStatusImageView.render(roomEncryptionTrustLevel)
8873
holder.otherSessionNameTextView.text = sessionName
8974
holder.otherSessionDescriptionTextView.text = sessionDescription

0 commit comments

Comments
 (0)