Implement UI element refresh on transfer or restore screen.

This commit is contained in:
Alex Hart
2024-03-15 15:13:16 -03:00
committed by Cody Henthorne
parent 6f46331772
commit b38865bdc7
6 changed files with 208 additions and 89 deletions

View File

@@ -1,16 +1,17 @@
package org.thoughtcrime.securesms.devicetransfer.newdevice;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import org.signal.core.util.concurrent.LifecycleDisposable;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.databinding.FragmentTransferRestoreBinding;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
@@ -19,22 +20,42 @@ import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
*/
public final class TransferOrRestoreFragment extends LoggingFragment {
private final LifecycleDisposable lifecycleDisposable = new LifecycleDisposable();
private FragmentTransferRestoreBinding binding;
public TransferOrRestoreFragment() {
super(R.layout.fragment_transfer_restore);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
view.findViewById(R.id.transfer_or_restore_fragment_transfer)
.setOnClickListener(v -> SafeNavigation.safeNavigate(Navigation.findNavController(v), R.id.action_new_device_transfer_instructions));
binding = FragmentTransferRestoreBinding.bind(view);
View restoreBackup = view.findViewById(R.id.transfer_or_restore_fragment_restore);
restoreBackup.setOnClickListener(v -> SafeNavigation.safeNavigate(Navigation.findNavController(v), R.id.action_choose_backup));
TransferOrRestoreViewModel viewModel = new ViewModelProvider(this).get(TransferOrRestoreViewModel.class);
binding.transferOrRestoreFragmentTransfer.setOnClickListener(v -> viewModel.onTransferFromAndroidDeviceSelected());
binding.transferOrRestoreFragmentRestore.setOnClickListener(v -> viewModel.onRestoreFromLocalBackupSelected());
binding.transferOrRestoreFragmentNext.setOnClickListener(v -> launchSelection(viewModel.getStateSnapshot()));
String description = getString(R.string.TransferOrRestoreFragment__transfer_your_account_and_messages_from_your_old_android_device);
String toBold = getString(R.string.TransferOrRestoreFragment__you_need_access_to_your_old_device);
TextView transferDescriptionView = view.findViewById(R.id.transfer_or_restore_fragment_transfer_description);
transferDescriptionView.setText(SpanUtil.boldSubstring(description, toBold));
binding.transferOrRestoreFragmentTransferDescription.setText(SpanUtil.boldSubstring(description, toBold));
lifecycleDisposable.bindTo(getViewLifecycleOwner());
lifecycleDisposable.add(viewModel.getState().subscribe(this::updateSelection));
}
private void updateSelection(TransferOrRestoreViewModel.RestorationType restorationType) {
binding.transferOrRestoreFragmentTransferCard.setSelected(restorationType == TransferOrRestoreViewModel.RestorationType.DEVICE_TRANSFER);
binding.transferOrRestoreFragmentRestoreCard.setSelected(restorationType == TransferOrRestoreViewModel.RestorationType.LOCAL_BACKUP);
}
private void launchSelection(TransferOrRestoreViewModel.RestorationType restorationType) {
switch (restorationType) {
case DEVICE_TRANSFER -> SafeNavigation.safeNavigate(Navigation.findNavController(requireView()), R.id.action_new_device_transfer_instructions);
case LOCAL_BACKUP -> SafeNavigation.safeNavigate(Navigation.findNavController(requireView()), R.id.action_choose_backup);
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.devicetransfer.newdevice
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.processors.BehaviorProcessor
/**
* Maintains state of the TransferOrRestoreFragment
*/
class TransferOrRestoreViewModel : ViewModel() {
private val internalState = BehaviorProcessor.createDefault(RestorationType.DEVICE_TRANSFER)
val state: Flowable<RestorationType> = internalState.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread())
val stateSnapshot: RestorationType get() = internalState.value!!
fun onTransferFromAndroidDeviceSelected() {
internalState.onNext(RestorationType.DEVICE_TRANSFER)
}
fun onRestoreFromLocalBackupSelected() {
internalState.onNext(RestorationType.LOCAL_BACKUP)
}
enum class RestorationType {
DEVICE_TRANSFER,
LOCAL_BACKUP
}
}

View File

@@ -6,7 +6,6 @@
package org.thoughtcrime.securesms.jobs
import androidx.annotation.WorkerThread
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.thoughtcrime.securesms.database.CallTable
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2024 Signal Messenger, LLC
~ SPDX-License-Identifier: AGPL-3.0-only
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/signal_colorPrimary" android:state_selected="true" />
<item android:color="@color/transparent" />
</selector>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12 2.75c-5.1 0-9.25 4.14-9.25 9.25 0 2.42 0.93 4.62 2.45 6.27l0.57-0.57C6.1 17.36 6.7 17.52 6.82 18l0.75 2.97c0.12 0.46-0.3 0.87-0.76 0.76l-2.96-0.76c-0.47-0.12-0.63-0.7-0.29-1.05l0.58-0.58c-1.8-1.92-2.89-4.5-2.89-7.33C1.25 6.06 6.06 1.25 12 1.25S22.75 6.06 22.75 12 17.94 22.75 12 22.75c-0.41 0-0.75-0.34-0.75-0.75s0.34-0.75 0.75-0.75c5.1 0 9.25-4.14 9.25-9.25 0-5.1-4.14-9.25-9.25-9.25Z"/>
<path
android:fillColor="#FF000000"
android:pathData="M10.87 5.24c0-0.34 0.29-0.62 0.63-0.62s0.62 0.28 0.63 0.62l0.22 6.42 4.42 0.2c0.34 0.02 0.6 0.3 0.6 0.64s-0.26 0.62-0.6 0.64l-5.2 0.23H11.5c-0.48 0-0.88-0.39-0.88-0.87v-0.05l0.25-7.21Z"/>
</vector>

View File

@@ -4,8 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:viewBindingIgnore="true">
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
@@ -14,7 +13,7 @@
android:paddingStart="32dp"
android:paddingTop="@dimen/transfer_top_padding"
android:paddingEnd="32dp"
android:paddingBottom="16dp">
android:paddingBottom="24dp">
<TextView
android:layout_width="match_parent"
@@ -33,98 +32,142 @@
android:textAppearance="@style/Signal.Text.BodyLarge"
android:textColor="@color/signal_colorOnSurfaceVariant" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/transfer_or_restore_fragment_transfer"
<org.thoughtcrime.securesms.components.ClippedCardView
android:id="@+id/transfer_or_restore_fragment_transfer_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="@drawable/selectable_rounded_background"
android:padding="16dp">
app:cardBackgroundColor="@color/signal_colorSurface2"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:strokeColor="@color/transfer_option_stroke_color_selector"
app:strokeWidth="2dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/transfer_or_restore_fragment_transfer_icon"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/transfer_or_restore_fragment_transfer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_transfer_phone_48"
app:tint="@color/signal_colorPrimary" />
android:paddingVertical="16dp">
<TextView
android:id="@+id/transfer_or_restore_fragment_transfer_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/TransferOrRestoreFragment__transfer_from_android_device"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toTopOf="@+id/transfer_or_restore_fragment_transfer_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/transfer_or_restore_fragment_transfer_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/transfer_or_restore_fragment_transfer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_transfer_phone_48"
app:tint="@color/signal_colorPrimary" />
<TextView
android:id="@+id/transfer_or_restore_fragment_transfer_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="@+id/transfer_or_restore_fragment_transfer_header"
app:layout_constraintTop_toBottomOf="@+id/transfer_or_restore_fragment_transfer_header"
tools:text="@string/TransferOrRestoreFragment__transfer_your_account_and_messages_from_your_old_android_device" />
<TextView
android:id="@+id/transfer_or_restore_fragment_transfer_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="16dp"
android:text="@string/TransferOrRestoreFragment__transfer_from_android_device"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toTopOf="@+id/transfer_or_restore_fragment_transfer_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/transfer_or_restore_fragment_transfer_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/transfer_or_restore_fragment_transfer_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="@+id/transfer_or_restore_fragment_transfer_header"
app:layout_constraintTop_toBottomOf="@+id/transfer_or_restore_fragment_transfer_header"
tools:text="@string/TransferOrRestoreFragment__transfer_your_account_and_messages_from_your_old_android_device" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/transfer_or_restore_fragment_restore"
</androidx.constraintlayout.widget.ConstraintLayout>
</org.thoughtcrime.securesms.components.ClippedCardView>
<org.thoughtcrime.securesms.components.ClippedCardView
android:id="@+id/transfer_or_restore_fragment_restore_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="@drawable/selectable_rounded_background"
android:padding="16dp">
app:cardBackgroundColor="@color/signal_colorSurface2"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:strokeColor="@color/transfer_option_stroke_color_selector"
app:strokeWidth="2dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/transfer_or_restore_fragment_restore_icon"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/transfer_or_restore_fragment_restore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/transfer_or_restore_fragment_restore_icon"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/symbol_backup_light"
app:tint="@color/signal_colorPrimary" />
<TextView
android:id="@+id/transfer_or_restore_fragment_restore_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="16dp"
android:text="@string/TransferOrRestoreFragment__restore_from_backup"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toTopOf="@+id/transfer_or_restore_fragment_restore_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/transfer_or_restore_fragment_restore_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/transfer_or_restore_fragment_restore_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/TransferOrRestoreFragment__restore_your_messages_from_a_local_backup"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="@+id/transfer_or_restore_fragment_restore_header"
app:layout_constraintTop_toBottomOf="@+id/transfer_or_restore_fragment_restore_header" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.thoughtcrime.securesms.components.ClippedCardView>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/transfer_or_restore_fragment_next"
style="@style/Signal.Widget.Button.Large.Tonal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_backup_48"
app:tint="@color/signal_colorPrimary" />
<TextView
android:id="@+id/transfer_or_restore_fragment_restore_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/TransferOrRestoreFragment__restore_from_backup"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toTopOf="@+id/transfer_or_restore_fragment_restore_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/transfer_or_restore_fragment_restore_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/transfer_or_restore_fragment_restore_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/TransferOrRestoreFragment__restore_your_messages_from_a_local_backup"
android:textColor="@color/signal_colorOnSurfaceVariant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="@+id/transfer_or_restore_fragment_restore_header"
app:layout_constraintTop_toBottomOf="@+id/transfer_or_restore_fragment_restore_header" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:layout_gravity="end"
android:text="@string/RegistrationActivity_next" />
</FrameLayout>
</LinearLayout>
</ScrollView>