diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 0b17b64c4a..61043a80e3 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3313,6 +3313,9 @@
Name
Version
URL
+ Browser
+ Model
+ Operating system
IP address
Rename session
Session name
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCase.kt
index 25b5ddb0e8..471ef05c8d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCase.kt
@@ -16,13 +16,36 @@
package im.vector.app.features.settings.devices.v2.details
+import im.vector.app.features.settings.devices.v2.DeviceFullInfo
+import im.vector.app.features.settings.devices.v2.details.extended.DeviceExtendedInfo
+import im.vector.app.features.settings.devices.v2.list.DeviceType
import org.matrix.android.sdk.api.extensions.orFalse
-import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import javax.inject.Inject
class CheckIfSectionDeviceIsVisibleUseCase @Inject constructor() {
- fun execute(deviceInfo: DeviceInfo): Boolean {
- return deviceInfo.lastSeenIp?.isNotEmpty().orFalse()
+ fun execute(deviceFullInfo: DeviceFullInfo): Boolean {
+ val hasExtendedInfo = when (deviceFullInfo.deviceExtendedInfo.deviceType) {
+ DeviceType.MOBILE -> hasAnyDeviceExtendedInfoMobile(deviceFullInfo.deviceExtendedInfo)
+ DeviceType.WEB -> hasAnyDeviceExtendedInfoWeb(deviceFullInfo.deviceExtendedInfo)
+ DeviceType.DESKTOP -> hasAnyDeviceExtendedInfoDesktop(deviceFullInfo.deviceExtendedInfo)
+ DeviceType.UNKNOWN -> false
+ }
+
+ return hasExtendedInfo || deviceFullInfo.deviceInfo.lastSeenIp?.isNotEmpty().orFalse()
+ }
+
+ private fun hasAnyDeviceExtendedInfoMobile(deviceExtendedInfo: DeviceExtendedInfo): Boolean {
+ return deviceExtendedInfo.deviceModel?.isNotEmpty().orFalse() ||
+ deviceExtendedInfo.deviceOperatingSystem?.isNotEmpty().orFalse()
+ }
+
+ private fun hasAnyDeviceExtendedInfoWeb(deviceExtendedInfo: DeviceExtendedInfo): Boolean {
+ return deviceExtendedInfo.clientName?.isNotEmpty().orFalse() ||
+ deviceExtendedInfo.deviceOperatingSystem?.isNotEmpty().orFalse()
+ }
+
+ private fun hasAnyDeviceExtendedInfoDesktop(deviceExtendedInfo: DeviceExtendedInfo): Boolean {
+ return deviceExtendedInfo.deviceOperatingSystem?.isNotEmpty().orFalse()
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt
index eb4f823889..8d780925df 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/details/SessionDetailsController.kt
@@ -26,6 +26,7 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.core.session.clientinfo.MatrixClientInfoContent
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
+import im.vector.app.features.settings.devices.v2.list.DeviceType
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import javax.inject.Inject
@@ -58,8 +59,8 @@ class SessionDetailsController @Inject constructor(
buildSectionApplication(matrixClientInfo, addExtraTopMargin = hasSectionSession)
}
- if (hasSectionDevice(deviceInfo)) {
- buildSectionDevice(deviceInfo, addExtraTopMargin = hasSectionSession || hasApplicationSection)
+ if (hasSectionDevice(fullInfo)) {
+ buildSectionDevice(fullInfo, addExtraTopMargin = hasSectionSession || hasApplicationSection)
}
}
}
@@ -139,15 +140,77 @@ class SessionDetailsController @Inject constructor(
}
}
- private fun hasSectionDevice(data: DeviceInfo): Boolean {
+ private fun hasSectionDevice(data: DeviceFullInfo): Boolean {
return checkIfSectionDeviceIsVisibleUseCase.execute(data)
}
- private fun buildSectionDevice(data: DeviceInfo, addExtraTopMargin: Boolean) {
- val lastSeenIp = data.lastSeenIp.orEmpty()
-
+ private fun buildSectionDevice(data: DeviceFullInfo, addExtraTopMargin: Boolean) {
buildHeaderItem(R.string.device_manager_device_title, addExtraTopMargin)
+ when (data.deviceExtendedInfo.deviceType) {
+ DeviceType.MOBILE -> buildSectionDeviceMobile(data)
+ DeviceType.WEB -> buildSectionDeviceWeb(data)
+ DeviceType.DESKTOP -> buildSectionDeviceDesktop(data)
+ DeviceType.UNKNOWN -> buildSectionDeviceUnknown(data)
+ }
+ }
+
+ private fun buildSectionDeviceWeb(data: DeviceFullInfo) {
+ val browserName = data.deviceExtendedInfo.clientName.orEmpty()
+ val browserVersion = data.deviceExtendedInfo.clientVersion.orEmpty()
+ val browser = "$browserName $browserVersion"
+ val operatingSystem = data.deviceExtendedInfo.deviceOperatingSystem.orEmpty()
+ val lastSeenIp = data.deviceInfo.lastSeenIp.orEmpty()
+
+ if (browser.isNotEmpty()) {
+ val hasDivider = operatingSystem.isNotEmpty() || lastSeenIp.isNotEmpty()
+ buildContentItem(R.string.device_manager_session_details_device_browser, browser, hasDivider)
+ }
+
+ if (operatingSystem.isNotEmpty()) {
+ val hasDivider = lastSeenIp.isNotEmpty()
+ buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider)
+ }
+
+ buildIpAddressContentItem(lastSeenIp)
+ }
+
+ private fun buildSectionDeviceDesktop(data: DeviceFullInfo) {
+ val operatingSystem = data.deviceExtendedInfo.deviceOperatingSystem.orEmpty()
+ val lastSeenIp = data.deviceInfo.lastSeenIp.orEmpty()
+
+ if (operatingSystem.isNotEmpty()) {
+ val hasDivider = lastSeenIp.isNotEmpty()
+ buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider)
+ }
+
+ buildIpAddressContentItem(lastSeenIp)
+ }
+
+ private fun buildSectionDeviceMobile(data: DeviceFullInfo) {
+ val model = data.deviceExtendedInfo.deviceModel.orEmpty()
+ val operatingSystem = data.deviceExtendedInfo.deviceOperatingSystem.orEmpty()
+ val lastSeenIp = data.deviceInfo.lastSeenIp.orEmpty()
+
+ if (model.isNotEmpty()) {
+ val hasDivider = operatingSystem.isNotEmpty() || lastSeenIp.isNotEmpty()
+ buildContentItem(R.string.device_manager_session_details_device_model, model, hasDivider)
+ }
+
+ if (operatingSystem.isNotEmpty()) {
+ val hasDivider = lastSeenIp.isNotEmpty()
+ buildContentItem(R.string.device_manager_session_details_device_operating_system, operatingSystem, hasDivider)
+ }
+
+ buildIpAddressContentItem(lastSeenIp)
+ }
+
+ private fun buildSectionDeviceUnknown(data: DeviceFullInfo) {
+ val lastSeenIp = data.deviceInfo.lastSeenIp.orEmpty()
+ buildIpAddressContentItem(lastSeenIp)
+ }
+
+ private fun buildIpAddressContentItem(lastSeenIp: String) {
if (lastSeenIp.isNotEmpty()) {
val hasDivider = false
buildContentItem(R.string.device_manager_session_details_device_ip_address, lastSeenIp, hasDivider)
diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCaseTest.kt
index e5cd5f1647..d124f68b1b 100644
--- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/details/CheckIfSectionDeviceIsVisibleUseCaseTest.kt
@@ -16,6 +16,9 @@
package im.vector.app.features.settings.devices.v2.details
+import im.vector.app.features.settings.devices.v2.DeviceFullInfo
+import im.vector.app.features.settings.devices.v2.details.extended.DeviceExtendedInfo
+import im.vector.app.features.settings.devices.v2.list.DeviceType
import io.mockk.every
import io.mockk.mockk
import org.amshove.kluent.shouldBeEqualTo
@@ -23,36 +26,106 @@ import org.junit.Test
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
private const val AN_IP_ADDRESS = "ip-address"
+private const val A_DEVICE_MODEL = "device-model"
+private const val A_DEVICE_OPERATING_SYSTEM = "device-operating-system"
+private const val A_CLIENT_NAME = "client-name"
class CheckIfSectionDeviceIsVisibleUseCaseTest {
private val checkIfSectionDeviceIsVisibleUseCase = CheckIfSectionDeviceIsVisibleUseCase()
@Test
- fun `given device info with Ip address when checking is device section is visible then it returns true`() {
- // Given
- val deviceInfo = givenADeviceInfo(AN_IP_ADDRESS)
+ fun `given device of any type with Ip address when checking if device section is visible then it returns true`() {
+ DeviceType.values().forEach { deviceType ->
+ // Given
+ val deviceExtendedInfo = givenAnExtendedDeviceInfo(deviceType)
+ val deviceFullInfo = givenADeviceFullInfo(deviceExtendedInfo)
+ val deviceInfo = givenADeviceInfo(ipAddress = AN_IP_ADDRESS)
+ every { deviceFullInfo.deviceInfo } returns deviceInfo
- // When
- val result = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo)
+ // When
+ val result = checkIfSectionDeviceIsVisibleUseCase.execute(deviceFullInfo)
- // Then
- result shouldBeEqualTo true
+ // Then
+ result shouldBeEqualTo true
+ }
}
@Test
- fun `given device info with empty or null Ip address when checking is device section is visible then it returns false`() {
+ fun `given device of any type with empty or null Ip address and no extended info when checking if device section is visible then it returns false`() {
+ DeviceType.values().forEach { deviceType ->
+ // Given
+ val deviceExtendedInfo = givenAnExtendedDeviceInfo(deviceType)
+ val deviceFullInfo1 = givenADeviceFullInfo(deviceExtendedInfo)
+ val deviceFullInfo2 = givenADeviceFullInfo(deviceExtendedInfo)
+ val deviceInfo1 = givenADeviceInfo(ipAddress = "")
+ val deviceInfo2 = givenADeviceInfo(ipAddress = null)
+ every { deviceFullInfo1.deviceInfo } returns deviceInfo1
+ every { deviceFullInfo2.deviceInfo } returns deviceInfo2
+
+ // When
+ val result1 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceFullInfo1)
+ val result2 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceFullInfo2)
+
+ // Then
+ result1 shouldBeEqualTo false
+ result2 shouldBeEqualTo false
+ }
+ }
+
+ @Test
+ fun `given device of any type with extended info when checking if device section is visible then it returns true`() {
// Given
- val deviceInfo1 = givenADeviceInfo("")
- val deviceInfo2 = givenADeviceInfo(null)
+ val deviceExtendedInfoList = listOf(
+ givenAnExtendedDeviceInfo(
+ DeviceType.MOBILE,
+ deviceModel = A_DEVICE_MODEL,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.MOBILE,
+ deviceOperatingSystem = A_DEVICE_OPERATING_SYSTEM,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.MOBILE,
+ deviceModel = A_DEVICE_MODEL,
+ deviceOperatingSystem = A_DEVICE_OPERATING_SYSTEM,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.DESKTOP,
+ deviceOperatingSystem = A_DEVICE_OPERATING_SYSTEM,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.WEB,
+ clientName = A_CLIENT_NAME,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.WEB,
+ deviceOperatingSystem = A_DEVICE_OPERATING_SYSTEM,
+ ),
+ givenAnExtendedDeviceInfo(
+ DeviceType.WEB,
+ clientName = A_CLIENT_NAME,
+ deviceOperatingSystem = A_DEVICE_OPERATING_SYSTEM,
+ ),
+ )
- // When
- val result1 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo1)
- val result2 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo2)
+ deviceExtendedInfoList.forEach { deviceExtendedInfo ->
+ val deviceFullInfo = givenADeviceFullInfo(deviceExtendedInfo)
+ val deviceInfo = givenADeviceInfo(ipAddress = null)
+ every { deviceFullInfo.deviceInfo } returns deviceInfo
- // Then
- result1 shouldBeEqualTo false
- result2 shouldBeEqualTo false
+ // When
+ val result = checkIfSectionDeviceIsVisibleUseCase.execute(deviceFullInfo)
+
+ // Then
+ result shouldBeEqualTo true
+ }
+ }
+
+ private fun givenADeviceFullInfo(deviceExtendedInfo: DeviceExtendedInfo): DeviceFullInfo {
+ val deviceFullInfo = mockk()
+ every { deviceFullInfo.deviceExtendedInfo } returns deviceExtendedInfo
+ return deviceFullInfo
}
private fun givenADeviceInfo(ipAddress: String?): DeviceInfo {
@@ -60,4 +133,20 @@ class CheckIfSectionDeviceIsVisibleUseCaseTest {
every { info.lastSeenIp } returns ipAddress
return info
}
+
+ private fun givenAnExtendedDeviceInfo(
+ deviceType: DeviceType,
+ clientName: String? = null,
+ clientVersion: String? = null,
+ deviceOperatingSystem: String? = null,
+ deviceModel: String? = null,
+ ): DeviceExtendedInfo {
+ return DeviceExtendedInfo(
+ deviceType = deviceType,
+ clientName = clientName,
+ clientVersion = clientVersion,
+ deviceOperatingSystem = deviceOperatingSystem,
+ deviceModel = deviceModel,
+ )
+ }
}