Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toggle IP address visibility (PSG-860) #7546

Merged
merged 17 commits into from
Nov 22, 2022

Conversation

onurays
Copy link
Contributor

@onurays onurays commented Nov 8, 2022

Type of change

  • Feature
  • Bugfix
  • Technical
  • Other :

Content

In new Session Management screens we should hide the IP addresses of devices by default for the sake of privacy (in case users may demo these screens to someone else etc.). In this PR, we will provide a menu item to be able to toggle the visibility of IP addresses. Once a user selects to show or hide the IP addresses then this option is saved to the shared preferences and will be reflected to the screens on next app launches.

Motivation and context

Screenshots / GIFs

toggle_ip_address.mp4

Tests

  • Enable new session management screen from Labs settings
  • Navigate to Settings > Security & Privacy > Show All sessions
  • Scroll down to Other Sessions section, click to the menu
  • Toggle Show/Hide IP address menu item and see the IP addresses visibility changes
  • Click View All button at the bottom of the Other Sessions section
  • Toggle Show/Hide IP address menu item and see the changes on UI
  • Select a session to navigate to the session overview screen
  • Toggle Show/Hide IP address menu item in session overview screen

Tested devices

  • Physical
  • Emulator
  • OS version(s):

Checklist

@onurays onurays requested review from a team and jonnyandrew and removed request for a team November 8, 2022 16:27
@onurays onurays requested review from a team, fedrunov, jonnyandrew and mnaturel and removed request for jonnyandrew, a team and fedrunov November 9, 2022 10:55
Onuray Sahin added 4 commits November 9, 2022 16:57
# Conflicts:
#	vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt
# Conflicts:
#	vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt
@onurays onurays requested review from a team and bmarty and removed request for jonnyandrew, mnaturel and a team November 14, 2022 07:26
@mnaturel mnaturel self-requested a review November 16, 2022 10:12
}

private fun refreshIpAddressVisibility() {
val shouldShowIpAddress = sharedPreferences.getBoolean(VectorPreferences.SETTINGS_SESSION_MANAGER_SHOW_IP_ADDRESS, false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should either define the default value for this preference somewhere in VectorPreferences or create a method to retrieve this setting so that it can be reused accross the screens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done.

setState {
copy(isShowingIpAddress = !isShowingIpAddress)
}
sharedPreferences.edit {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to encapsulate the domain layer code inside a UseCase. I would see 2 options in prefered order:

  • if we have a way to observe settings in the app, we should have a usecase to observe the ip address visiblity setting and another one to toggle the setting.
  • if we don't have a way to observe settings, we should have a usecase to set the setting to a certain value.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a use case to set the value.

@@ -72,6 +73,7 @@ class DevicesViewModelTest {
private val fakeInterceptSignoutFlowResponseUseCase = mockk<InterceptSignoutFlowResponseUseCase>()
private val fakePendingAuthHandler = FakePendingAuthHandler()
private val fakeRefreshDevicesUseCase = mockk<RefreshDevicesUseCase>(relaxUnitFun = true)
private val fakeSharedPreferences = FakeSharedPreferences()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New tests should be added:

  • to cover the new toggle visibility action
  • to cover the update of viewState at the initialization

@@ -187,6 +189,7 @@ class SessionInfoView @JvmOverloads constructor(
views.sessionInfoLastActivityTextView.isGone = true
}
views.sessionInfoLastIPAddressTextView.setTextOrHide(deviceInfo.lastSeenIp?.takeIf { isLastSeenDetailsVisible })
Copy link
Contributor

@mnaturel mnaturel Nov 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could write instead:
views.sessionInfoLastIPAddressTextView.setTextOrHide(deviceInfo.lastSeenIp?.takeIf { isLastSeenDetailsVisible && isShowingIpAddress })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done.

}

private fun handleToggleIpAddressVisibility() = withState { state ->
val isShowingIpAddress = state.isShowingIpAddress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark for adding a reusable usecase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored.

@@ -66,6 +67,7 @@ class OtherSessionsViewModelTest {
private val fakeRefreshDevicesUseCase = mockk<RefreshDevicesUseCase>(relaxed = true)
private val fakeSignoutSessionsUseCase = FakeSignoutSessionsUseCase()
private val fakePendingAuthHandler = FakePendingAuthHandler()
private val fakeSharedPreferences = FakeSharedPreferences()

private fun createViewModel(viewState: OtherSessionsViewState = OtherSessionsViewState(defaultArgs)) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add units tests to cover the new action and the change of the viewState in the initialization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tests have not been added for this ViewModel.

}

private fun handleToggleIpAddressVisibility() = withState { state ->
val isShowingIpAddress = state.isShowingIpAddress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark for the need of a usecase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored.

@@ -103,6 +106,7 @@ class SessionOverviewViewModelTest {
A_SESSION_ID_1,
notificationsStatus
)
fakeSharedPreferences.givenSessionManagerShowIpAddress(false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark for the missing new unit tests.

app:layout_constraintEnd_toEndOf="@id/otherSessionNameTextView"
app:layout_constraintStart_toStartOf="@id/otherSessionNameTextView"
app:layout_constraintTop_toBottomOf="@id/otherSessionNameTextView"
tools:text="@string/device_manager_verification_status_verified" />

<TextView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should update some constraints on this layout:

  • For the view with id otherSessionItemBackground we should replace app:layout_constraintBottom_toBottomOf="@id/otherSessionVerificationStatusImageView" by app:layout_constraintBottom_toBottomOf="@id/otherSessionIpAddressTextView"
  • For the view with id otherSessionNameTextView we should replace app:layout_constraintTop_toTopOf="@id/otherSessionDeviceTypeImageView" by app:layout_constraintTop_toTopOf="@id/otherSessionItemBackground"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without these changes, you can see in the below screen there is an issue with the background for selected items when in select mode:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, done.

Copy link
Contributor

@mnaturel mnaturel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When testing it, I have found a small bug which could be fixed by observing the setting as I suggested instead of getting the setting value when ViewModel is initialized. To reproduce the bug:

  • Make sure the IP address is not visible
  • Go to the other sessions list
  • Go to a session overview screen
  • From this screen, show the IP address
  • Press back
  • We can see IP address are not displayed since the ViewModel is using the setting value when the ViewModel was created.

@@ -51,6 +51,7 @@
<bool name="settings_labs_rich_text_editor_default">false</bool>
<bool name="settings_labs_enable_voice_broadcast_visible">true</bool>
<bool name="settings_labs_enable_voice_broadcast_default">false</bool>
<bool name="settings_device_manager_show_ip_address">false</bool>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the default value here. But I think it should not be in the labs section, maybe in a new section Level 3: Security & Privacy, Sessions?

@@ -1228,4 +1231,14 @@ class VectorPreferences @Inject constructor(
return vectorFeatures.isVoiceBroadcastEnabled() &&
defaultPrefs.getBoolean(SETTINGS_LABS_VOICE_BROADCAST_KEY, getDefault(R.bool.settings_labs_enable_voice_broadcast_default))
}

fun showIpAddressInDeviceManagerScreens(): Boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small question about naming, should we align the methods and preference setting names on SessionManager instead of DeviceManager?

import im.vector.app.features.settings.VectorPreferences
import javax.inject.Inject

class ToggleIpAddressVisibilityUseCase @Inject constructor(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add unit tests for this new use case.

@@ -77,6 +79,8 @@ class SessionOverviewViewModelTest {
private val togglePushNotificationUseCase = FakeTogglePushNotificationUseCase()
private val fakeGetNotificationsStatusUseCase = FakeGetNotificationsStatusUseCase()
private val notificationsStatus = NotificationsStatus.ENABLED
private val fakeVectorPreferences = FakeVectorPreferences()
private val toggleIpAddressVisibilityUseCase = mockk<ToggleIpAddressVisibilityUseCase>()

private fun createViewModel() = SessionOverviewViewModel(
Copy link
Contributor

@mnaturel mnaturel Nov 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New tests should also be added for this ViewModel. Maybe a FakeToggleIpAddressVisibilityUseCase can be created to reuse it in the other ViewModel?

Copy link
Contributor

@mnaturel mnaturel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates! I have added some small comments we should handle before merge.

@ElementBot
Copy link

Warnings
⚠️

vector/src/main/res/layout/item_other_session.xml#L7 - Attribute android:foreground has no effect on API levels lower than 23 (current min is 21)

⚠️

vector/src/main/res/layout/item_other_session.xml#L7 - Attribute android:foreground has no effect on API levels lower than 23 (current min is 21)

Generated by 🚫 dangerJS against abea9b6

@sonarcloud
Copy link

sonarcloud bot commented Nov 22, 2022

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

47.2% 47.2% Coverage
0.0% 0.0% Duplication

@onurays onurays merged commit 0957b38 into develop Nov 22, 2022
@onurays onurays deleted the feature/ons/toggle_ip_address_visibility branch November 22, 2022 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants