diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index ed21c2de8a..8cf89196e1 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3231,6 +3231,6 @@
Unverified sessions
Verify or sign out from unverified sessions.
Inactive sessions
- Consider signing out from old sessions (90 days or older) you don’t use anymore.
+ Consider signing out from old sessions (%1$d days or more) that you don’t use anymore.
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
index 245cfe9809..9d1f446b33 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
@@ -40,6 +40,7 @@ import im.vector.app.features.settings.devices.DeviceFullInfo
import im.vector.app.features.settings.devices.DevicesAction
import im.vector.app.features.settings.devices.DevicesViewEvents
import im.vector.app.features.settings.devices.DevicesViewModel
+import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS
/**
* Display the list of the user's devices and sessions.
@@ -153,6 +154,9 @@ class VectorSettingsDevicesFragment :
views.deviceListInactiveSessionsRecommendation.isVisible = inactiveSessionsCount > 0
views.deviceListUnverifiedSessionsRecommendation.setCount(unverifiedSessionsCount)
views.deviceListInactiveSessionsRecommendation.setCount(inactiveSessionsCount)
+ views.deviceListInactiveSessionsRecommendation.setDescription(
+ getString(R.string.device_manager_inactive_sessions_description, SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS)
+ )
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCase.kt
index c5d5f804a6..8991ad1e3d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCase.kt
@@ -16,18 +16,19 @@
package im.vector.app.features.settings.devices.v2.list
-import im.vector.app.core.resources.DateProvider
-import im.vector.app.core.resources.toTimestamp
+import im.vector.app.core.time.Clock
import java.util.concurrent.TimeUnit
import javax.inject.Inject
-class CheckIfSessionIsInactiveUseCase @Inject constructor() {
+class CheckIfSessionIsInactiveUseCase @Inject constructor(
+ private val clock: Clock,
+) {
fun execute(lastSeenTs: Long): Boolean {
- val lastSeenDate = DateProvider.toLocalDateTime(lastSeenTs)
- val currentDate = DateProvider.currentLocalDateTime()
- val diffMilliseconds = currentDate.toTimestamp() - lastSeenDate.toTimestamp()
- val diffDays = TimeUnit.MILLISECONDS.toDays(diffMilliseconds)
- return diffDays >= SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS
+ // In case of the server doesn't send the last seen date.
+ if (lastSeenTs == 0L) return true
+
+ val diffMilliseconds = clock.epochMillis() - lastSeenTs
+ return diffMilliseconds >= TimeUnit.DAYS.toMillis(SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS.toLong())
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt
index 73d8d74bfd..c715704444 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SecurityRecommendationView.kt
@@ -66,6 +66,14 @@ class SecurityRecommendationView @JvmOverloads constructor(
views.recommendationShieldImageView.backgroundTintList = ColorStateList.valueOf(backgroundTint)
}
+ fun setTitle(title: String) {
+ views.recommendationTitleTextView.text = title
+ }
+
+ fun setDescription(description: String) {
+ views.recommendationDescriptionTextView.text = description
+ }
+
fun setCount(sessionsCount: Int) {
views.recommendationViewAllButton.text = context.getString(R.string.device_manager_other_sessions_view_all, sessionsCount)
}
diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCaseTest.kt
index 32f809057b..b7d56a88bf 100644
--- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/list/CheckIfSessionIsInactiveUseCaseTest.kt
@@ -16,62 +16,44 @@
package im.vector.app.features.settings.devices.v2.list
-import im.vector.app.core.resources.DateProvider
-import im.vector.app.core.resources.toTimestamp
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.mockkStatic
+import im.vector.app.test.fakes.FakeClock
import org.amshove.kluent.shouldBeEqualTo
-import org.junit.Before
import org.junit.Test
-import org.threeten.bp.Instant
-import org.threeten.bp.LocalDateTime
-import org.threeten.bp.ZoneId
-import org.threeten.bp.ZoneId.systemDefault
-import org.threeten.bp.ZoneOffset
-import org.threeten.bp.zone.ZoneRules
+import java.util.concurrent.TimeUnit
+
+private const val A_TIMESTAMP = 1654689143L
class CheckIfSessionIsInactiveUseCaseTest {
- private val checkIfSessionIsInactiveUseCase = CheckIfSessionIsInactiveUseCase()
- private val zoneId = mockk()
- private val zoneRules = mockk()
-
- @Before
- fun setup() {
- mockkStatic(ZoneId::class)
- every { systemDefault() } returns zoneId
- every { zoneId.rules } returns zoneRules
- every { zoneRules.getOffset(any()) } returns ZoneOffset.UTC
- every { zoneRules.getOffset(any()) } returns ZoneOffset.UTC
- }
+ private val clock = FakeClock().apply { givenEpoch(A_TIMESTAMP) }
+ private val checkIfSessionIsInactiveUseCase = CheckIfSessionIsInactiveUseCase(clock)
@Test
fun `given an old last seen date then session is inactive`() {
- val lastSeenDate = DateProvider.currentLocalDateTime().minusDays((SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS + 1).toLong())
+ val lastSeenDate = A_TIMESTAMP - TimeUnit.DAYS.toMillis(SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS.toLong()) - 1
- checkIfSessionIsInactiveUseCase.execute(lastSeenDate.toTimestamp()) shouldBeEqualTo true
+ checkIfSessionIsInactiveUseCase.execute(lastSeenDate) shouldBeEqualTo true
}
@Test
fun `given a last seen date equal to the threshold then session is inactive`() {
- val lastSeenDate = DateProvider.currentLocalDateTime().minusDays((SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS).toLong())
+ val lastSeenDate = A_TIMESTAMP - TimeUnit.DAYS.toMillis(SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS.toLong())
- checkIfSessionIsInactiveUseCase.execute(lastSeenDate.toTimestamp()) shouldBeEqualTo true
+ checkIfSessionIsInactiveUseCase.execute(lastSeenDate) shouldBeEqualTo true
}
@Test
fun `given a recent last seen date then session is active`() {
- val lastSeenDate = DateProvider.currentLocalDateTime().minusDays((SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS - 1).toLong())
+ val lastSeenDate = A_TIMESTAMP - TimeUnit.DAYS.toMillis(SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS.toLong()) + 1
- checkIfSessionIsInactiveUseCase.execute(lastSeenDate.toTimestamp()) shouldBeEqualTo false
+ checkIfSessionIsInactiveUseCase.execute(lastSeenDate) shouldBeEqualTo false
}
@Test
fun `given a last seen date as zero then session is inactive`() {
// In case of the server doesn't send the last seen date.
- val lastSeenDate = DateProvider.toLocalDateTime(0)
+ val lastSeenDate = 0L
- checkIfSessionIsInactiveUseCase.execute(lastSeenDate.toTimestamp()) shouldBeEqualTo true
+ checkIfSessionIsInactiveUseCase.execute(lastSeenDate) shouldBeEqualTo true
}
}