Merge pull request #6903 from vector-im/feature/ons/device_manager_current_session
[Device Manager] Render current session (PSG-668)
This commit is contained in:
commit
dc99c1122d
1
changelog.d/6902.wip
Normal file
1
changelog.d/6902.wip
Normal file
@ -0,0 +1 @@
|
||||
[Device Manager] Current Session Section
|
@ -23,10 +23,23 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
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.dialogs.ManuallyVerifyDialog
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSettingsDevicesBinding
|
||||
import im.vector.app.features.crypto.recover.SetupMode
|
||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||
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.DevicesViewState
|
||||
|
||||
/**
|
||||
* Display the list of the user's devices and sessions.
|
||||
@ -35,6 +48,8 @@ import im.vector.app.databinding.FragmentSettingsDevicesBinding
|
||||
class VectorSettingsDevicesFragment :
|
||||
VectorBaseFragment<FragmentSettingsDevicesBinding>() {
|
||||
|
||||
private val viewModel: DevicesViewModel by fragmentViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsDevicesBinding {
|
||||
return FragmentSettingsDevicesBinding.inflate(inflater, container, false)
|
||||
}
|
||||
@ -52,7 +67,45 @@ class VectorSettingsDevicesFragment :
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
initLearnMoreButtons()
|
||||
initWaitingView()
|
||||
observerViewEvents()
|
||||
}
|
||||
|
||||
private fun observerViewEvents() {
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is DevicesViewEvents.Loading -> showLoading(it.message)
|
||||
is DevicesViewEvents.Failure -> showFailure(it.throwable)
|
||||
is DevicesViewEvents.RequestReAuth -> Unit // TODO. Next PR
|
||||
is DevicesViewEvents.PromptRenameDevice -> Unit // TODO. Next PR
|
||||
is DevicesViewEvents.ShowVerifyDevice -> {
|
||||
VerificationBottomSheet.withArgs(
|
||||
roomId = null,
|
||||
otherUserId = it.userId,
|
||||
transactionId = it.transactionId
|
||||
).show(childFragmentManager, "REQPOP")
|
||||
}
|
||||
is DevicesViewEvents.SelfVerification -> {
|
||||
VerificationBottomSheet.forSelfVerification(it.session)
|
||||
.show(childFragmentManager, "REQPOP")
|
||||
}
|
||||
is DevicesViewEvents.ShowManuallyVerify -> {
|
||||
ManuallyVerifyDialog.show(requireActivity(), it.cryptoDeviceInfo) {
|
||||
viewModel.handle(DevicesAction.MarkAsManuallyVerified(it.cryptoDeviceInfo))
|
||||
}
|
||||
}
|
||||
is DevicesViewEvents.PromptResetSecrets -> {
|
||||
navigator.open4SSetup(requireContext(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initWaitingView() {
|
||||
views.waitingView.waitingStatusText.setText(R.string.please_wait)
|
||||
views.waitingView.waitingStatusText.isVisible = true
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
@ -61,12 +114,48 @@ class VectorSettingsDevicesFragment :
|
||||
}
|
||||
|
||||
private fun initLearnMoreButtons() {
|
||||
views.devicesListHeaderSectionOther.onLearnMoreClickListener = {
|
||||
views.deviceListHeaderSectionOther.onLearnMoreClickListener = {
|
||||
Toast.makeText(context, "Learn more other", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleanUpLearnMoreButtonsListeners() {
|
||||
views.devicesListHeaderSectionOther.onLearnMoreClickListener = null
|
||||
views.deviceListHeaderSectionOther.onLearnMoreClickListener = null
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
val currentDeviceInfo = state.devices()
|
||||
?.firstOrNull {
|
||||
it.deviceInfo.deviceId == state.myDeviceId
|
||||
}
|
||||
|
||||
if (state.devices is Success && currentDeviceInfo != null) {
|
||||
renderCurrentDevice(state)
|
||||
} else {
|
||||
hideCurrentSessionView()
|
||||
}
|
||||
|
||||
handleRequestStatus(state.request)
|
||||
}
|
||||
|
||||
private fun hideCurrentSessionView() {
|
||||
views.deviceListHeaderSectionCurrent.isVisible = false
|
||||
views.deviceListCurrentSession.isVisible = false
|
||||
}
|
||||
|
||||
private fun renderCurrentDevice(state: DevicesViewState) {
|
||||
views.deviceListHeaderSectionCurrent.isVisible = true
|
||||
views.deviceListCurrentSession.isVisible = true
|
||||
views.deviceListCurrentSession.update(
|
||||
accountCrossSigningIsTrusted = state.accountCrossSigningIsTrusted,
|
||||
legacyMode = !state.hasAccountCrossSigning
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleRequestStatus(unIgnoreRequest: Async<Unit>) {
|
||||
views.waitingView.root.isVisible = when (unIgnoreRequest) {
|
||||
is Loading -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.ViewCurrentSessionBinding
|
||||
import im.vector.app.features.settings.devices.TrustUtils
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||
|
||||
class CurrentSessionView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val views: ViewCurrentSessionBinding
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_current_session, this)
|
||||
views = ViewCurrentSessionBinding.bind(this)
|
||||
}
|
||||
|
||||
fun update(accountCrossSigningIsTrusted: Boolean, legacyMode: Boolean) {
|
||||
renderDeviceType()
|
||||
renderVerificationStatus(accountCrossSigningIsTrusted, legacyMode)
|
||||
}
|
||||
|
||||
private fun renderVerificationStatus(accountCrossSigningIsTrusted: Boolean, legacyMode: Boolean) {
|
||||
val deviceTrustLevel = DeviceTrustLevel(crossSigningVerified = accountCrossSigningIsTrusted, locallyVerified = true)
|
||||
val shield = TrustUtils.shieldForTrust(
|
||||
currentDevice = true,
|
||||
trustMSK = accountCrossSigningIsTrusted,
|
||||
legacyMode = legacyMode,
|
||||
deviceTrustLevel = deviceTrustLevel
|
||||
)
|
||||
views.currentSessionVerificationStatusImageView.render(shield)
|
||||
if (deviceTrustLevel.crossSigningVerified) {
|
||||
renderCrossSigningVerified()
|
||||
} else {
|
||||
renderCrossSigningUnverified()
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderCrossSigningVerified() {
|
||||
views.currentSessionVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_verified)
|
||||
views.currentSessionVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorPrimary))
|
||||
views.currentSessionVerificationStatusDetailTextView.text = context.getString(R.string.device_manager_verification_status_detail_verified)
|
||||
views.currentSessionVerifySessionButton.isVisible = false
|
||||
}
|
||||
|
||||
private fun renderCrossSigningUnverified() {
|
||||
views.currentSessionVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unverified)
|
||||
views.currentSessionVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorError))
|
||||
views.currentSessionVerificationStatusDetailTextView.text = context.getString(R.string.device_manager_verification_status_detail_unverified)
|
||||
views.currentSessionVerifySessionButton.isVisible = true
|
||||
}
|
||||
|
||||
// TODO. We don't have this info yet. Update later accordingly.
|
||||
private fun renderDeviceType() {
|
||||
views.currentSessionDeviceTypeImageView.setImageResource(R.drawable.ic_device_type_mobile)
|
||||
views.currentSessionDeviceTypeImageView.contentDescription = context.getString(R.string.a11y_device_manager_device_type_mobile)
|
||||
views.currentSessionDeviceTypeTextView.text = context.getString(R.string.device_manager_device_type_android)
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextWithColoredPart
|
||||
import im.vector.app.databinding.ViewDevicesListHeaderBinding
|
||||
@ -58,12 +59,18 @@ class DevicesListHeaderView @JvmOverloads constructor(
|
||||
|
||||
private fun setDescription(typedArray: TypedArray) {
|
||||
val description = typedArray.getString(R.styleable.DevicesListHeaderView_devicesListHeaderDescription)
|
||||
if (description.isNullOrEmpty()) {
|
||||
binding.devicesListHeaderDescription.isVisible = false
|
||||
return
|
||||
}
|
||||
|
||||
val learnMore = context.getString(R.string.action_learn_more)
|
||||
val stringBuilder = StringBuilder()
|
||||
stringBuilder.append(description)
|
||||
stringBuilder.append(" ")
|
||||
stringBuilder.append(learnMore)
|
||||
|
||||
binding.devicesListHeaderDescription.isVisible = true
|
||||
binding.devicesListHeaderDescription.setTextWithColoredPart(
|
||||
fullText = stringBuilder.toString(),
|
||||
coloredPart = learnMore,
|
||||
|
13
vector/src/main/res/drawable/bg_current_session.xml
Normal file
13
vector/src/main/res/drawable/bg_current_session.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@android:color/transparent" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="?vctr_content_quinary" />
|
||||
|
||||
<corners android:radius="8dp" />
|
||||
|
||||
</shape>
|
7
vector/src/main/res/drawable/bg_device_type.xml
Normal file
7
vector/src/main/res/drawable/bg_device_type.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="?vctr_system" />
|
||||
|
||||
</shape>
|
11
vector/src/main/res/drawable/ic_device_type_desktop.xml
Normal file
11
vector/src/main/res/drawable/ic_device_type_desktop.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="22dp"
|
||||
android:height="19dp"
|
||||
android:viewportWidth="22"
|
||||
android:viewportHeight="19"
|
||||
tools:ignore="UnusedResources">
|
||||
<path
|
||||
android:pathData="M3,15.5C2.45,15.5 1.979,15.304 1.588,14.913C1.196,14.521 1,14.05 1,13.5V2.5C1,1.95 1.196,1.479 1.588,1.087C1.979,0.696 2.45,0.5 3,0.5H19C19.55,0.5 20.021,0.696 20.413,1.087C20.804,1.479 21,1.95 21,2.5V13.5C21,14.05 20.804,14.521 20.413,14.913C20.021,15.304 19.55,15.5 19,15.5H3ZM3,13.5H19V2.5H3V13.5ZM1,18.5C0.717,18.5 0.479,18.404 0.288,18.212C0.096,18.021 0,17.783 0,17.5C0,17.217 0.096,16.979 0.288,16.788C0.479,16.596 0.717,16.5 1,16.5H21C21.283,16.5 21.521,16.596 21.712,16.788C21.904,16.979 22,17.217 22,17.5C22,17.783 21.904,18.021 21.712,18.212C21.521,18.404 21.283,18.5 21,18.5H1ZM3,13.5V2.5V13.5Z"
|
||||
android:fillColor="#737D8C"/>
|
||||
</vector>
|
9
vector/src/main/res/drawable/ic_device_type_mobile.xml
Normal file
9
vector/src/main/res/drawable/ic_device_type_mobile.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="14dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="14"
|
||||
android:viewportHeight="22">
|
||||
<path
|
||||
android:pathData="M12,0.01L2,0C0.9,0 0,0.9 0,2V20C0,21.1 0.9,22 2,22H12C13.1,22 14,21.1 14,20V2C14,0.9 13.1,0.01 12,0.01ZM12,18H2V4H12V18Z"
|
||||
android:fillColor="#737D8C"/>
|
||||
</vector>
|
11
vector/src/main/res/drawable/ic_device_type_web.xml
Normal file
11
vector/src/main/res/drawable/ic_device_type_web.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="20dp"
|
||||
android:height="17dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="17"
|
||||
tools:ignore="UnusedResources">
|
||||
<path
|
||||
android:pathData="M18,16.5H2C1.45,16.5 0.979,16.304 0.588,15.913C0.196,15.521 0,15.05 0,14.5V2.5C0,1.95 0.196,1.479 0.588,1.088C0.979,0.696 1.45,0.5 2,0.5H18C18.55,0.5 19.021,0.696 19.413,1.088C19.804,1.479 20,1.95 20,2.5V14.5C20,15.05 19.804,15.521 19.413,15.913C19.021,16.304 18.55,16.5 18,16.5ZM2,4.5V14.5H18V4.5H2Z"
|
||||
android:fillColor="#737D8C"/>
|
||||
</vector>
|
@ -5,13 +5,37 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<im.vector.app.features.settings.devices.v2.list.DevicesListHeaderView
|
||||
android:id="@+id/devices_list_header_section_other"
|
||||
android:id="@+id/deviceListHeaderSectionCurrent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:devicesListHeaderDescription=""
|
||||
app:devicesListHeaderTitle="@string/device_manager_header_section_current_session"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<im.vector.app.features.settings.devices.v2.list.CurrentSessionView
|
||||
android:id="@+id/deviceListCurrentSession"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/deviceListHeaderSectionCurrent" />
|
||||
|
||||
<im.vector.app.features.settings.devices.v2.list.DevicesListHeaderView
|
||||
android:id="@+id/deviceListHeaderSectionOther"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:devicesListHeaderDescription="@string/settings_sessions_other_description"
|
||||
app:devicesListHeaderTitle="@string/settings_sessions_other_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@id/deviceListCurrentSession" />
|
||||
|
||||
<include
|
||||
android:id="@+id/waiting_view"
|
||||
layout="@layout/merge_overlay_waiting_view" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
98
vector/src/main/res/layout/view_current_session.xml
Normal file
98
vector/src/main/res/layout/view_current_session.xml
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_current_session"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/currentSessionDeviceTypeImageView"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="@string/a11y_device_manager_device_type_mobile"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@drawable/bg_device_type"
|
||||
tools:src="@drawable/ic_device_type_mobile" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentSessionDeviceTypeTextView"
|
||||
style="@style/TextAppearance.Vector.Headline.Medium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/currentSessionDeviceTypeImageView"
|
||||
tools:text="@string/device_manager_device_type_android" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/currentSessionVerificationStatusContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/currentSessionDeviceTypeTextView">
|
||||
|
||||
<im.vector.app.core.ui.views.ShieldImageView
|
||||
android:id="@+id/currentSessionVerificationStatusImageView"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="@drawable/ic_shield_trusted" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentSessionVerificationStatusTextView"
|
||||
style="@style/TextAppearance.Vector.Body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
tools:text="@string/device_manager_verification_status_verified"
|
||||
tools:textColor="?colorPrimary" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentSessionVerificationStatusDetailTextView"
|
||||
style="@style/TextAppearance.Vector.Caption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="32dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/currentSessionVerificationStatusContainer"
|
||||
tools:text="@string/device_manager_verification_status_detail_verified" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/currentSessionVerifySessionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/device_manager_verify_session"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/currentSessionVerificationStatusDetailTextView" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/currentSessionViewDetailsButton"
|
||||
style="@style/Widget.Vector.Button.Text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/device_manager_view_details"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/currentSessionVerifySessionButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -3209,4 +3209,16 @@
|
||||
|
||||
<!-- Device Manager -->
|
||||
<string name="device_manager_settings_active_sessions_show_all">Show All Sessions (V2, WIP)</string>
|
||||
<string name="a11y_device_manager_device_type_mobile">Mobile</string>
|
||||
<string name="a11y_device_manager_device_type_web" tools:ignore="UnusedResources">Web</string>
|
||||
<string name="a11y_device_manager_device_type_desktop" tools:ignore="UnusedResources">Desktop</string>
|
||||
<string name="device_manager_device_type_android">${app_name} Mobile: Android</string>
|
||||
<string name="device_manager_verification_status_verified">Verified session</string>
|
||||
<string name="device_manager_verification_status_unverified">Unverified session</string>
|
||||
<string name="device_manager_verification_status_detail_verified">Your current session is ready for secure messaging.</string>
|
||||
<string name="device_manager_verification_status_detail_unverified">Verify your current session for enhanced secure messaging.</string>
|
||||
<string name="device_manager_verify_session">Verify Session</string>
|
||||
<string name="device_manager_view_details">View Details</string>
|
||||
<string name="device_manager_header_section_current_session">Current Session</string>
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user