diff options
-rw-r--r-- | app/src/main/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java | 1 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java | 12 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CancelCallback.java | 5 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java | 43 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivityCallback.java (renamed from app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupInterface.java) | 13 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java | 88 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java | 42 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_setup.xml | 10 | ||||
-rw-r--r-- | app/src/main/res/layout/f_configure_provider.xml | 107 |
10 files changed, 257 insertions, 66 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a9971904..091fa0b6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> @@ -28,6 +29,7 @@ android:theme="@style/BitmaskTheme"> <activity android:name=".providersetup.activities.SetupActivity" + android:launchMode="singleInstance" android:exported="false" /> <service diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 4748b22e..241fa4b9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -54,7 +54,6 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.DateHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipCommand; -import se.leap.bitmaskclient.providersetup.ProviderListActivity; import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java b/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java index b0b81624..380ddf23 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java @@ -48,6 +48,16 @@ public class ProgressSpinner extends RelativeLayout { } public void update(int progress) { - textView.setText(textView.getContext().getString(R.string.percentage, progress)); + String text = ""; + if (progress > 0) { + if ((progress / 10) == 0) { + text = text + " "; + } + if ((progress / 100) == 0) { + text = text + " "; + } + text = text + progress + "%"; + } + textView.setText(text); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CancelCallback.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CancelCallback.java new file mode 100644 index 00000000..a3f387d8 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CancelCallback.java @@ -0,0 +1,5 @@ +package se.leap.bitmaskclient.providersetup.activities; + +public interface CancelCallback { + void onCanceled(); +} diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java index f62f959d..33e9cbbd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java @@ -4,6 +4,8 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static androidx.appcompat.app.ActionBar.DISPLAY_SHOW_CUSTOM; +import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF; + import androidx.annotation.ColorInt; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; @@ -13,22 +15,29 @@ import androidx.viewpager2.widget.ViewPager2; import android.annotation.SuppressLint; import android.content.Context; import android.os.Bundle; +import android.util.Log; import android.view.Gravity; import android.view.View; -import android.widget.Button; import android.widget.Toast; +import java.util.HashSet; +import java.util.Iterator; + import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.views.ActionBarTitle; import se.leap.bitmaskclient.databinding.ActivitySetupBinding; import se.leap.bitmaskclient.providersetup.SetupViewPagerAdapter; +import se.leap.bitmaskclient.tor.TorServiceCommand; +import se.leap.bitmaskclient.tor.TorStatusObservable; -public class SetupActivity extends AppCompatActivity implements SetupInterface { +public class SetupActivity extends AppCompatActivity implements SetupActivityCallback { + private static final String TAG = SetupActivity.class.getSimpleName(); ActivitySetupBinding binding; Provider provider; + private final HashSet<CancelCallback> cancelCallbacks = new HashSet<>(); @SuppressLint("ClickableViewAccessibility") @Override @@ -66,6 +75,17 @@ public class SetupActivity extends AppCompatActivity implements SetupInterface { } binding.viewPager.setCurrentItem(newPos); }); + binding.setupCancelButton.setOnClickListener(v -> { + binding.viewPager.setCurrentItem(0, false); + if (TorStatusObservable.getStatus() != OFF) { + Log.d(TAG, "SHUTDOWN - cancelSettingUpProvider"); + TorServiceCommand.stopTorServiceAsync(this); + } + provider = null; + for (CancelCallback cancelCallback : cancelCallbacks) { + cancelCallback.onCanceled(); + } + }); setupActionBar(); } @@ -116,13 +136,23 @@ public class SetupActivity extends AppCompatActivity implements SetupInterface { } @Override + public void registerCancelCallback(CancelCallback cancelCallback) { + cancelCallbacks.add(cancelCallback); + } + + @Override + public void removeCancelCallback(CancelCallback cancelCallback) { + cancelCallbacks.remove(cancelCallback); + } + + @Override public void setNavigationButtonHidden(boolean isHidden) { binding.setupNextButton.setVisibility(isHidden ? GONE : VISIBLE); } @Override - public void onCanceled() { - binding.viewPager.setCurrentItem(0); + public void setCancelButtonHidden(boolean isHidden) { + binding.setupCancelButton.setVisibility(isHidden ? GONE : VISIBLE); } @Override @@ -131,6 +161,11 @@ public class SetupActivity extends AppCompatActivity implements SetupInterface { } @Override + public void onConfigurationSuccess() { + binding.viewPager.setCurrentItem(binding.viewPager.getCurrentItem() + 1); + } + + @Override public Provider getSelectedProvider() { return provider; } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupInterface.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivityCallback.java index 1438ee5d..8fe4118d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupInterface.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivityCallback.java @@ -4,16 +4,25 @@ import androidx.viewpager2.widget.ViewPager2; import se.leap.bitmaskclient.base.models.Provider; -public interface SetupInterface { +public interface SetupActivityCallback { void onSetupStepValidationChanged(boolean isValid); void registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback callback); void removeOnPageChangeCallback(ViewPager2.OnPageChangeCallback callback); + + void registerCancelCallback(CancelCallback cancelCallback); + + void removeCancelCallback(CancelCallback cancelCallback); + + void setNavigationButtonHidden(boolean isHidden); - void onCanceled(); + + void setCancelButtonHidden(boolean isHidden); void onProviderSelected(Provider provider); + void onConfigurationSuccess(); + Provider getSelectedProvider(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index ceed2c3c..42d516a0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -1,9 +1,14 @@ package se.leap.bitmaskclient.providersetup.fragments; +import static android.app.Activity.RESULT_CANCELED; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.utils.ViewHelper.animateContainerVisibility; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_OK; import static se.leap.bitmaskclient.providersetup.ProviderAPI.SET_UP_PROVIDER; import static se.leap.bitmaskclient.tor.TorStatusObservable.getBootstrapProgress; import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastLogs; @@ -12,6 +17,7 @@ import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -28,21 +34,27 @@ import java.util.List; import java.util.Observable; import java.util.Observer; +import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.databinding.FConfigureProviderBinding; +import se.leap.bitmaskclient.eip.EipSetupListener; +import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.providersetup.ProviderAPICommand; import se.leap.bitmaskclient.providersetup.TorLogAdapter; -import se.leap.bitmaskclient.providersetup.activities.SetupInterface; +import se.leap.bitmaskclient.providersetup.activities.CancelCallback; +import se.leap.bitmaskclient.providersetup.activities.SetupActivityCallback; import se.leap.bitmaskclient.tor.TorStatusObservable; -public class ConfigureProviderFragment extends Fragment implements Observer { +public class ConfigureProviderFragment extends Fragment implements Observer, CancelCallback, EipSetupListener { + + private static final String TAG = ConfigureProviderFragment.class.getSimpleName(); public static ConfigureProviderFragment newInstance(int position) { return new ConfigureProviderFragment(position); } FConfigureProviderBinding binding; - private SetupInterface setupInterface; + private SetupActivityCallback setupActivityCallback; private boolean isExpanded = false; private final int position; private ViewPager2.OnPageChangeCallback viewPagerCallback; @@ -56,6 +68,7 @@ public class ConfigureProviderFragment extends Fragment implements Observer { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + torLogAdapter = new TorLogAdapter(getLastLogs()); } @Override @@ -64,13 +77,16 @@ public class ConfigureProviderFragment extends Fragment implements Observer { binding = FConfigureProviderBinding.inflate(inflater, container, false); binding.detailContainer.setVisibility(PreferenceHelper.getUseSnowflake(getContext()) ? VISIBLE : GONE); binding.detailHeaderContainer.setOnClickListener(v -> { - binding.ivExpand.animate().setDuration(250).rotation(isExpanded ? 0 : 270); + binding.ivExpand.animate().setDuration(250).rotation(isExpanded ? -90 : 0); showConnectionDetails(); animateContainerVisibility(binding.expandableDetailContainer, isExpanded); isExpanded = !isExpanded; }); binding.ivExpand.animate().setDuration(0).rotation(270); + LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext()); + binding.connectionDetailLogs.setLayoutManager(layoutManager); + binding.connectionDetailLogs.setAdapter(torLogAdapter); return binding.getRoot(); } @@ -85,35 +101,40 @@ public class ConfigureProviderFragment extends Fragment implements Observer { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); - setupInterface = (SetupInterface) getActivity(); - viewPagerCallback = new ViewPager2.OnPageChangeCallback() { - @Override - public void onPageSelected(int position) { - super.onPageSelected(position); - if (position == ConfigureProviderFragment.this.position) { - binding.detailContainer.setVisibility(PreferenceHelper.getUseSnowflake(getContext()) ? VISIBLE : GONE); - setupInterface.setNavigationButtonHidden(true); - ProviderAPICommand.execute(context, SET_UP_PROVIDER, setupInterface.getSelectedProvider()); + if (getActivity() instanceof SetupActivityCallback) { + setupActivityCallback = (SetupActivityCallback) getActivity(); + viewPagerCallback = new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int position) { + super.onPageSelected(position); + if (position == ConfigureProviderFragment.this.position) { + binding.detailContainer.setVisibility(PreferenceHelper.getUseSnowflake(getContext()) ? VISIBLE : GONE); + setupActivityCallback.setNavigationButtonHidden(true); + setupActivityCallback.setCancelButtonHidden(false); + ProviderAPICommand.execute(context, SET_UP_PROVIDER, setupActivityCallback.getSelectedProvider()); + } } - } - }; - setupInterface.registerOnPageChangeCallback(viewPagerCallback); + }; + setupActivityCallback.registerOnPageChangeCallback(viewPagerCallback); + setupActivityCallback.registerCancelCallback(this); + } TorStatusObservable.getInstance().addObserver(this); + EipSetupObserver.addListener(this); } @Override public void onDetach() { super.onDetach(); TorStatusObservable.getInstance().deleteObserver(this); - setupInterface.removeOnPageChangeCallback(viewPagerCallback); - setupInterface = null; + if (setupActivityCallback != null) { + setupActivityCallback.removeOnPageChangeCallback(viewPagerCallback); + setupActivityCallback.removeCancelCallback(this); + setupActivityCallback = null; + } + EipSetupObserver.removeListener(this); } protected void showConnectionDetails() { - LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext()); - binding.connectionDetailLogs.setLayoutManager(layoutManager); - torLogAdapter = new TorLogAdapter(getLastLogs()); - binding.connectionDetailLogs.setAdapter(torLogAdapter); binding.connectionDetailLogs.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -150,6 +171,7 @@ public class ConfigureProviderFragment extends Fragment implements Observer { setLogs(getLastTorLog(), getLastSnowflakeLog(), getLastLogs()); } } + binding.tvProgressStatus.setText(TorStatusObservable.getStringForCurrentStatus(activity)); binding.progressSpinner.update(getBootstrapProgress()); }); } @@ -160,4 +182,26 @@ public class ConfigureProviderFragment extends Fragment implements Observer { binding.torState.setText(torLog); binding.snowflakeState.setText(snowflakeLog); } + + @Override + public void onCanceled() { + + } + + @Override + public void handleEipEvent(Intent intent) {} + + @Override + public void handleProviderApiEvent(Intent intent) { + int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, RESULT_CANCELED); + Bundle resultData = intent.getParcelableExtra(BROADCAST_RESULT_KEY); + if (resultData == null) { + resultData = Bundle.EMPTY; + } + if (resultCode == PROVIDER_OK) { + Provider provider = resultData.getParcelable(PROVIDER_KEY); + setupActivityCallback.onProviderSelected(provider); + setupActivityCallback.onConfigurationSuccess(); + } + } }
\ No newline at end of file diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java index 45ba73dc..6ebb149c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java @@ -16,21 +16,39 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; +import androidx.viewpager2.widget.ViewPager2; import java.util.ArrayList; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.databinding.FProviderSelectionBinding; -import se.leap.bitmaskclient.providersetup.activities.SetupInterface; +import se.leap.bitmaskclient.providersetup.activities.CancelCallback; +import se.leap.bitmaskclient.providersetup.activities.SetupActivityCallback; import se.leap.bitmaskclient.providersetup.fragments.viewmodel.ProviderSelectionViewModel; import se.leap.bitmaskclient.providersetup.fragments.viewmodel.ProviderSelectionViewModelFactory; -public class ProviderSelectionFragment extends Fragment { +public class ProviderSelectionFragment extends Fragment implements CancelCallback { private ProviderSelectionViewModel viewModel; private ArrayList<RadioButton> radioButtons; - private SetupInterface setupCallback; + private SetupActivityCallback setupCallback; + + private FProviderSelectionBinding binding; + + private final ViewPager2.OnPageChangeCallback onPageChangeCallback = new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int position) { + super.onPageSelected(position); + if (position == 0) { + if (setupCallback != null) { + setupCallback.setCancelButtonHidden(!ProviderObservable.getInstance().getCurrentProvider().isConfigured()); + setupCallback.setNavigationButtonHidden(false); + } + } + } + }; public static ProviderSelectionFragment newInstance() { return new ProviderSelectionFragment(); @@ -49,7 +67,7 @@ public class ProviderSelectionFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - FProviderSelectionBinding binding = FProviderSelectionBinding.inflate(inflater, container, false); + binding = FProviderSelectionBinding.inflate(inflater, container, false); radioButtons = new ArrayList<>(); for (int i = 0; i < viewModel.size(); i++) { @@ -108,20 +126,27 @@ public class ProviderSelectionFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); - if (getActivity() instanceof SetupInterface) { - setupCallback = (SetupInterface) getActivity(); + if (getActivity() instanceof SetupActivityCallback) { + setupCallback = (SetupActivityCallback) getActivity(); + setupCallback.registerOnPageChangeCallback(onPageChangeCallback); + setupCallback.registerCancelCallback(this); } } @Override public void onDetach() { super.onDetach(); + if (setupCallback != null) { + setupCallback.removeOnPageChangeCallback(onPageChangeCallback); + setupCallback.removeCancelCallback(this); + } setupCallback = null; } @Override public void onDestroyView() { super.onDestroyView(); + binding = null; radioButtons = null; } @@ -135,4 +160,9 @@ public class ProviderSelectionFragment extends Fragment { super.onResume(); setupCallback.onSetupStepValidationChanged(viewModel.isValidConfig()); } + + @Override + public void onCanceled() { + binding.providerRadioGroup.check(0); + } }
\ No newline at end of file diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml index fe302bb1..770b8ab3 100644 --- a/app/src/main/res/layout/activity_setup.xml +++ b/app/src/main/res/layout/activity_setup.xml @@ -114,5 +114,15 @@ android:layout_alignParentBottom="true" android:text="@string/next" /> + + <Button + android:id="@+id/setup_cancel_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_alignParentBottom="true" + android:text="@string/cancel" + android:visibility="gone" + /> </RelativeLayout> </androidx.appcompat.widget.LinearLayoutCompat> diff --git a/app/src/main/res/layout/f_configure_provider.xml b/app/src/main/res/layout/f_configure_provider.xml index 6e272260..8400a05d 100644 --- a/app/src/main/res/layout/f_configure_provider.xml +++ b/app/src/main/res/layout/f_configure_provider.xml @@ -7,14 +7,18 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/stdpadding" - android:layout_margin="@dimen/activity_margin" + android:layout_marginTop="@dimen/activity_margin" + android:layout_marginStart="@dimen/activity_margin" + android:layout_marginEnd="@dimen/activity_margin" tools:context=".providersetup.fragments.ProviderSelectionFragment"> - <androidx.appcompat.widget.LinearLayoutCompat + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:layout_margin="@dimen/activity_margin" + android:layout_marginTop="@dimen/activity_margin" + android:layout_marginStart="@dimen/activity_margin" + android:layout_marginEnd="@dimen/activity_margin" > <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tv_title" @@ -23,18 +27,42 @@ android:textAppearance="@style/TextAppearance.AppCompat.Title" android:text="@string/configuring_provider" android:paddingBottom="@dimen/stdpadding" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tv_circumvention_description" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.AppCompat.Body1" - android:text="@string/description_configure_provider"/> + android:text="@string/description_configure_provider" + app:layout_constraintTop_toBottomOf="@id/tv_title" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + /> <se.leap.bitmaskclient.base.views.ProgressSpinner android:id="@+id/progress_spinner" android:layout_width="100dp" - android:layout_height="100dp" /> + android:layout_height="100dp" + app:layout_constraintTop_toBottomOf="@id/tv_circumvention_description" + app:layout_constraintStart_toStartOf="parent" + /> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/tv_progress_status" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:maxLines="2" + android:ellipsize="end" + app:layout_constraintBottom_toBottomOf="@id/progress_spinner" + app:layout_constraintTop_toTopOf="@id/progress_spinner" + app:layout_constraintStart_toEndOf="@id/progress_spinner" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + tools:text="Starting bridges this is a very long text 123" + /> <androidx.cardview.widget.CardView android:id="@+id/detail_container" @@ -42,6 +70,11 @@ android:layout_height="wrap_content" app:cardCornerRadius="12dp" app:cardElevation="1dp" + app:layout_constraintTop_toBottomOf="@id/progress_spinner" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintVertical_bias="0" > <androidx.appcompat.widget.LinearLayoutCompat android:layout_width="match_parent" @@ -80,7 +113,7 @@ android:visibility="gone" tools:visibility="visible" > - <RelativeLayout + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/connection_detail_container" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -91,6 +124,7 @@ android:id="@+id/tv_tor_status" android:layout_width="match_parent" android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" android:text="@string/tor_status" android:textStyle="bold" android:paddingHorizontal="@dimen/stdpadding"/> @@ -99,21 +133,24 @@ android:id="@+id/tor_icon" android:layout_width="35dp" android:layout_height="35dp" - android:layout_below="@id/tv_tor_status" - android:layout_alignParentStart="true" + app:layout_constraintTop_toBottomOf="@id/tv_tor_status" + app:layout_constraintStart_toStartOf="parent" android:padding="4dp" android:src="@drawable/ic_tor" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tor_state" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="0dp" + android:layout_height="0dp" android:fadingEdge="horizontal" android:maxLines="2" android:text="@string/configuring_provider" android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" - android:layout_alignBottom="@id/tor_icon" - android:layout_toEndOf="@id/tor_icon" - android:layout_alignParentEnd="true" + app:layout_constraintTop_toTopOf="@id/tor_icon" + app:layout_constraintBottom_toBottomOf="@id/tor_icon" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/tor_icon" + app:layout_constraintHorizontal_bias="0" + android:paddingHorizontal="@dimen/stdpadding" android:gravity="bottom" tools:text="test 12321 123 \n sdf,sdf,m\nn 123 " android:ellipsize="end" @@ -123,8 +160,10 @@ <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tv_snowflake_status" - android:layout_below="@id/tor_state" - android:layout_width="match_parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tor_icon" + app:layout_constraintEnd_toEndOf="parent" + android:layout_width="0dp" android:layout_height="wrap_content" android:text="@string/snowflake_status" android:textStyle="bold" @@ -136,25 +175,28 @@ android:layout_width="35dp" android:layout_height="35dp" android:src="@drawable/ic_snowflake" - android:layout_below="@id/tv_snowflake_status" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_snowflake_status" android:layout_alignParentStart="true" android:layout_marginBottom="@dimen/stdpadding" android:padding="4dp" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/snowflake_state" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/tor_state" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/snowflake_icon" + app:layout_constraintTop_toTopOf="@id/snowflake_icon" + app:layout_constraintBottom_toBottomOf="@id/snowflake_icon" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + android:paddingBottom="1dp" + android:paddingHorizontal="@dimen/stdpadding" android:fadingEdge="horizontal" android:maxLines="2" android:text="@string/configuring_provider" android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" - android:layout_alignTop="@id/snowflake_icon" - android:layout_alignBottom="@+id/snowflake_icon" - android:layout_toEndOf="@+id/snowflake_icon" - android:layout_alignParentEnd="true" - android:paddingBottom="1dp" + android:gravity="bottom" tools:text="test \n another \n and a third \n blkud" android:ellipsize="end" @@ -162,7 +204,9 @@ /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tv_logs" - android:layout_below="@id/snowflake_state" + app:layout_constraintTop_toBottomOf="@id/snowflake_state" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/log_fragment_title" @@ -171,18 +215,21 @@ android:paddingHorizontal="@dimen/stdpadding"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/connection_detail_logs" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_logs" + app:layout_constraintHeight_max="180dp" android:layout_below="@+id/tv_logs" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_height="wrap_content" tools:listitem="@layout/v_log_item" android:isScrollContainer="false" /> - - </RelativeLayout> + </androidx.constraintlayout.widget.ConstraintLayout> </androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat> </androidx.cardview.widget.CardView> - </androidx.appcompat.widget.LinearLayoutCompat> + </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView>
\ No newline at end of file |