diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 15dd579386..892c31ecf8 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3247,5 +3247,6 @@
Current Session
Session
+ Last activity %1$s
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 f7f6ca6db4..2262f083da 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
@@ -31,6 +31,7 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
+import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.dialogs.ManuallyVerifyDialog
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSettingsDevicesBinding
@@ -55,6 +56,8 @@ class VectorSettingsDevicesFragment :
@Inject lateinit var viewNavigator: VectorSettingsDevicesViewNavigator
+ @Inject lateinit var dateFormatter: VectorDateFormatter
+
private val viewModel: DevicesViewModel by fragmentViewModel()
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsDevicesBinding {
@@ -214,7 +217,7 @@ class VectorSettingsDevicesFragment :
isCurrentSession = true,
deviceFullInfo = it
)
- views.deviceListCurrentSession.render(viewState)
+ views.deviceListCurrentSession.render(viewState, dateFormatter)
views.deviceListCurrentSession.debouncedClicks {
currentDeviceInfo.deviceInfo.deviceId?.let { deviceId -> navigateToSessionOverview(deviceId) }
}
@@ -226,10 +229,10 @@ class VectorSettingsDevicesFragment :
}
}
- private fun navigateToSessionOverview(sessionId: String) {
+ private fun navigateToSessionOverview(deviceId: String) {
viewNavigator.navigateToSessionOverview(
context = requireActivity(),
- sessionId = sessionId
+ deviceId = deviceId
)
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt
index 25c971aacb..54eed3bc14 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt
@@ -22,7 +22,7 @@ import javax.inject.Inject
class VectorSettingsDevicesViewNavigator @Inject constructor() {
- fun navigateToSessionOverview(context: Context, sessionId: String) {
- context.startActivity(SessionOverviewActivity.newIntent(context, sessionId))
+ fun navigateToSessionOverview(context: Context, deviceId: String) {
+ context.startActivity(SessionOverviewActivity.newIntent(context, deviceId))
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt
index 536184faec..df50666b3b 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt
@@ -19,11 +19,15 @@ package im.vector.app.features.settings.devices.v2.list
import android.content.Context
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.isGone
import androidx.core.view.isVisible
import im.vector.app.R
+import im.vector.app.core.date.DateFormatKind
+import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.extensions.setTextWithColoredPart
import im.vector.app.databinding.ViewSessionInfoBinding
import im.vector.app.features.themes.ThemeUtils
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
class SessionInfoView @JvmOverloads constructor(
@@ -43,13 +47,14 @@ class SessionInfoView @JvmOverloads constructor(
val viewDetailsButton = views.sessionInfoViewDetailsButton
- fun render(sessionInfoViewState: SessionInfoViewState) {
+ fun render(sessionInfoViewState: SessionInfoViewState, dateFormatter: VectorDateFormatter) {
renderDeviceInfo(sessionInfoViewState.deviceFullInfo.deviceInfo.displayName.orEmpty())
renderVerificationStatus(
sessionInfoViewState.deviceFullInfo.trustLevelForShield,
sessionInfoViewState.isCurrentSession,
- sessionInfoViewState.hasLearnMoreLink
+ sessionInfoViewState.isLearnMoreLinkVisible
)
+ renderDeviceLastSeenDetails(sessionInfoViewState.deviceFullInfo.deviceInfo, dateFormatter, sessionInfoViewState.isLastSeenDetailsVisible)
renderDetailsButton(sessionInfoViewState.isDetailsButtonVisible)
}
@@ -117,6 +122,33 @@ class SessionInfoView @JvmOverloads constructor(
views.sessionInfoNameTextView.text = sessionName
}
+ private fun renderDeviceLastSeenDetails(
+ deviceInfo: DeviceInfo,
+ dateFormatter: VectorDateFormatter,
+ isLastSeenDetailsVisible: Boolean,
+ ) {
+ deviceInfo.lastSeenTs
+ ?.takeIf { isLastSeenDetailsVisible }
+ ?.let { timestamp ->
+ views.sessionInfoLastActivityTextView.isVisible = true
+ val formattedTs = dateFormatter.format(timestamp, DateFormatKind.DEFAULT_DATE_AND_TIME)
+ views.sessionInfoLastActivityTextView.text = context.getString(R.string.device_manager_session_last_activity, formattedTs)
+ }
+ ?: run {
+ views.sessionInfoLastActivityTextView.isGone = true
+ }
+
+ deviceInfo.lastSeenIp
+ ?.takeIf { isLastSeenDetailsVisible }
+ ?.let { ipAddress ->
+ views.sessionInfoLastIPAddressTextView.isVisible = true
+ views.sessionInfoLastIPAddressTextView.text = ipAddress
+ }
+ ?: run {
+ views.sessionInfoLastIPAddressTextView.isGone = true
+ }
+ }
+
private fun renderDetailsButton(isDetailsButtonVisible: Boolean) {
views.sessionInfoViewDetailsButton.isVisible = isDetailsButtonVisible
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoViewState.kt
index cf7c6f0ae8..22ad710676 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoViewState.kt
@@ -22,5 +22,6 @@ data class SessionInfoViewState(
val isCurrentSession: Boolean,
val deviceFullInfo: DeviceFullInfo,
val isDetailsButtonVisible: Boolean = true,
- val hasLearnMoreLink: Boolean = false
+ val isLearnMoreLinkVisible: Boolean = false,
+ val isLastSeenDetailsVisible: Boolean = false,
)
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt
index a663c0ff2a..015fcccf51 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt
@@ -43,9 +43,9 @@ class SessionOverviewActivity : SimpleFragmentActivity() {
}
companion object {
- fun newIntent(context: Context, sessionId: String): Intent {
+ fun newIntent(context: Context, deviceId: String): Intent {
return Intent(context, SessionOverviewActivity::class.java).apply {
- putExtra(Mavericks.KEY_ARG, SessionOverviewArgs(sessionId))
+ putExtra(Mavericks.KEY_ARG, SessionOverviewArgs(deviceId))
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt
index 87ea883362..27c8d6fb2e 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt
@@ -21,5 +21,5 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class SessionOverviewArgs(
- val sessionId: String
+ val deviceId: String
) : Parcelable
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt
index eb2a3aa93f..dbe75c94cc 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt
@@ -29,10 +29,12 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
+import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSessionOverviewBinding
import im.vector.app.features.settings.devices.DeviceFullInfo
import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
+import javax.inject.Inject
/**
* Display the overview info about a Session.
@@ -41,6 +43,8 @@ import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
class SessionOverviewFragment :
VectorBaseFragment() {
+ @Inject lateinit var dateFormatter: VectorDateFormatter
+
private val viewModel: SessionOverviewViewModel by fragmentViewModel()
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionOverviewBinding {
@@ -89,9 +93,10 @@ class SessionOverviewFragment :
isCurrentSession = isCurrentSession,
deviceFullInfo = deviceFullInfo,
isDetailsButtonVisible = false,
- hasLearnMoreLink = true
+ isLearnMoreLinkVisible = true,
+ isLastSeenDetailsVisible = true,
)
- views.sessionOverviewInfo.render(viewState)
+ views.sessionOverviewInfo.render(viewState, dateFormatter)
}
private fun hideSessionInfo() {
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt
index 9c40480270..1a1d3640a2 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt
@@ -46,10 +46,10 @@ class SessionOverviewViewModel @AssistedInject constructor(
init {
val currentDeviceId = session.sessionParams.deviceId.orEmpty()
setState {
- copy(isCurrentSession = sessionId.isNotEmpty() && sessionId == currentDeviceId)
+ copy(isCurrentSession = deviceId.isNotEmpty() && deviceId == currentDeviceId)
}
- observeSessionInfo(currentDeviceId)
+ observeSessionInfo(initialState.deviceId)
}
private fun observeSessionInfo(deviceId: String) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt
index 8fa19a6eee..c9f5635cbd 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt
@@ -22,11 +22,11 @@ import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.settings.devices.DeviceFullInfo
data class SessionOverviewViewState(
- val sessionId: String,
+ val deviceId: String,
val isCurrentSession: Boolean = false,
val deviceInfo: Async = Uninitialized,
) : MavericksState {
constructor(args: SessionOverviewArgs) : this(
- sessionId = args.sessionId
+ deviceId = args.deviceId
)
}
diff --git a/vector/src/main/res/layout/view_session_info.xml b/vector/src/main/res/layout/view_session_info.xml
index 02aad7b19d..49e1ebbb77 100644
--- a/vector/src/main/res/layout/view_session_info.xml
+++ b/vector/src/main/res/layout/view_session_info.xml
@@ -72,6 +72,35 @@
app:layout_constraintTop_toBottomOf="@id/sessionInfoVerificationStatusContainer"
tools:text="@string/device_manager_verification_status_detail_current_session_verified" />
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/sessionInfoLastIPAddressTextView" />