diff options
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java | 161 | ||||
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java | 23 | ||||
-rw-r--r-- | app/src/main/res/drawable/ic_snowflake.png | bin | 0 -> 2653 bytes | |||
-rw-r--r-- | app/src/main/res/drawable/ic_tor.png | bin | 0 -> 10221 bytes | |||
-rw-r--r-- | app/src/main/res/drawable/v_vertical_gradient.xml | 8 | ||||
-rw-r--r-- | app/src/main/res/layout-xlarge/v_loading_screen.xml | 138 | ||||
-rw-r--r-- | app/src/main/res/layout/v_add_provider.xml | 57 | ||||
-rw-r--r-- | app/src/main/res/layout/v_loading_screen.xml | 139 | ||||
-rw-r--r-- | app/src/main/res/layout/v_log_item.xml | 16 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 1 |
10 files changed, 474 insertions, 69 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java index 7d452200..a0c046de 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java @@ -5,20 +5,28 @@ import android.graphics.PorterDuff; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.widget.Button; import android.widget.LinearLayout; import android.widget.ProgressBar; +import android.widget.RelativeLayout; import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.widget.AppCompatTextView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Guideline; import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import java.util.List; import java.util.Observable; import java.util.Observer; @@ -31,8 +39,14 @@ import se.leap.bitmaskclient.tor.TorStatusObservable; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 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.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getBootstrapProgress; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastLogs; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastSnowflakeLog; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getStringForCurrentStatus; /** * Base Activity for configuration wizard activities @@ -55,6 +69,32 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple protected LinearLayout loadingScreen; @Nullable + @BindView(R.id.btn_connection_detail) + protected Button connectionDetailBtn; + + @Nullable + @BindView(R.id.connection_detail_container) + protected RelativeLayout connectionDetailContainer; + + @Nullable + @BindView(R.id.log_container) + protected RelativeLayout logsContainer; + + @Nullable + @BindView(R.id.tor_state) + protected AppCompatTextView torState; + + @Nullable + @BindView(R.id.snowflake_state) + protected AppCompatTextView snowflakeState; + + @Nullable + @BindView(R.id.connection_detail_logs) + protected RecyclerView connectionDetailLogs; + + private TorLogAdapter torLogAdapter; + + @Nullable @BindView(R.id.progressbar) protected ProgressBar progressBar; @@ -157,7 +197,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple super.onResume(); isActivityShowing = true; TorStatusObservable.getInstance().addObserver(this); - setProgressbarDescription(TorStatusObservable.getStringForCurrentStatus(this)); + setProgressbarDescription(getStringForCurrentStatus(this)); } protected void restoreState(Bundle savedInstanceState) { @@ -178,10 +218,48 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple providerHeaderView.setTitle(providerHeaderText); } + protected void showConnectionDetails() { + if (loadingScreen == null) { + return; + } + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + connectionDetailLogs.setLayoutManager(layoutManager); + connectionDetailLogs.addItemDecoration( new DividerItemDecoration(this, layoutManager.getOrientation())); + torLogAdapter = new TorLogAdapter(getLastLogs()); + connectionDetailLogs.setAdapter(torLogAdapter); + + connectionDetailLogs.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState != SCROLL_STATE_IDLE) { + torLogAdapter.postponeUpdate = true; + } else if (newState == SCROLL_STATE_IDLE && getFirstVisibleItemPosion() == 0) { + torLogAdapter.postponeUpdate = false; + } + } + }); + + snowflakeState.setText(getLastSnowflakeLog()); + torState.setText(getLastTorLog()); + connectionDetailBtn.setOnClickListener(v -> { + connectionDetailBtn.setVisibility(GONE); + logsContainer.setVisibility(VISIBLE); + }); + connectionDetailContainer.setVisibility(VISIBLE); + } + + private int getFirstVisibleItemPosion() { + return ((LinearLayoutManager)connectionDetailLogs.getLayoutManager()).findFirstVisibleItemPosition(); + } + protected void hideProgressBar() { if (loadingScreen == null) { return; } + connectionDetailBtn.setVisibility(VISIBLE); + connectionDetailContainer.setVisibility(GONE); + logsContainer.setVisibility(GONE); loadingScreen.setVisibility(GONE); content.setVisibility(VISIBLE); } @@ -195,19 +273,28 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple } protected void setProgressbarTitle(@StringRes int progressbarTitle) { - if (this.progressbarTitle == null) { + if (loadingScreen == null) { return; } this.progressbarTitle.setText(progressbarTitle); } protected void setProgressbarDescription(String progressbarDescription) { - if (this.progressbarDescription == null) { + if (loadingScreen == null) { return; } this.progressbarDescription.setText(progressbarDescription); } + protected void setConfigProgress(int value) { + if (loadingScreen == null) { + return; + } + + progressBar.setProgress(value, true); + progressBar.setIndeterminate(value >= 100 || value < 0); + } + protected void showCompactLayout() { if (isCompactLayout) { @@ -307,7 +394,73 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple @Override public void update(Observable o, Object arg) { if (o instanceof TorStatusObservable) { - runOnUiThread(() -> setProgressbarDescription(TorStatusObservable.getStringForCurrentStatus(ConfigWizardBaseActivity.this))); + runOnUiThread(() -> { + if (TorStatusObservable.getStatus() != TorStatusObservable.TorStatus.OFF && loadingScreen != null) { + if (connectionDetailContainer.getVisibility() == GONE) { + showConnectionDetails(); + } else { + setLogs(getLastTorLog(), getLastSnowflakeLog(), getLastLogs()); + } + } + setProgressbarDescription(getStringForCurrentStatus(ConfigWizardBaseActivity.this)); + setConfigProgress(getBootstrapProgress()); + }); + } + } + + protected void setLogs(String torLog, String snowflakeLog, List<String> lastLogs) { + if (loadingScreen == null) { + return; + } + torLogAdapter.updateData(lastLogs); + torState.setText(torLog); + snowflakeState.setText(snowflakeLog); + } + + static class TorLogAdapter extends RecyclerView.Adapter<TorLogAdapter.ViewHolder> { + private List<String> values; + private boolean postponeUpdate; + + static class ViewHolder extends RecyclerView.ViewHolder { + public AppCompatTextView logTextLabel; + public View layout; + + public ViewHolder(View v) { + super(v); + layout = v; + logTextLabel = v.findViewById(android.R.id.text1); + } + } + + public void updateData(List<String> data) { + values = data; + if (!postponeUpdate) { + notifyDataSetChanged(); + } + } + + public TorLogAdapter(List<String> data) { + values = data; + } + + @NonNull + @Override + public TorLogAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater inflater = LayoutInflater.from( + parent.getContext()); + View v = inflater.inflate(R.layout.v_log_item, parent, false); + return new TorLogAdapter.ViewHolder(v); + } + + @Override + public void onBindViewHolder(TorLogAdapter.ViewHolder holder, final int position) { + final String log = values.get(position); + holder.logTextLabel.setText(log); + } + + @Override + public int getItemCount() { + return values.size(); } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java index 449955af..281b21c0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java @@ -55,7 +55,7 @@ public class TorStatusObservable extends Observable { addLog(message); getInstance().lastSnowflakeLog = message; if (getInstance().status != TorStatus.OFF) { - getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getNotificationProgress()); + getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getBootstrapProgress()); } instance.setChanged(); instance.notifyObservers(); @@ -72,15 +72,15 @@ public class TorStatusObservable extends Observable { snowflakeIcon + ": " + snowflakeLog; } - private static int getNotificationProgress() { + public static int getBootstrapProgress() { return getInstance().status == TorStatus.STARTING ? getInstance().bootstrapPercent : -1; } private static void addLog(String message) { if (instance.lastLogs.size() > 100) { - instance.lastLogs.remove(0); + instance.lastLogs.remove(99); } - instance.lastLogs.add(message); + instance.lastLogs.add(0, message.trim()); } public static void updateState(Context context, String status) { @@ -102,7 +102,7 @@ public class TorStatusObservable extends Observable { getInstance().lastTorLog = getStringFor(context, logKey); addLog(getInstance().lastTorLog); } - getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getNotificationProgress()); + getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getBootstrapProgress()); } instance.setChanged(); @@ -168,8 +168,17 @@ public class TorStatusObservable extends Observable { @Nullable - public String getLastError() { - return lastError; + public static String getLastTorLog() { + return getInstance().lastTorLog; + } + + @Nullable + public static String getLastSnowflakeLog() { + return getInstance().lastSnowflakeLog; + } + + public static Vector<String> getLastLogs() { + return getInstance().lastLogs; } public static String getStringForCurrentStatus(Context context) { diff --git a/app/src/main/res/drawable/ic_snowflake.png b/app/src/main/res/drawable/ic_snowflake.png Binary files differnew file mode 100644 index 00000000..992662ee --- /dev/null +++ b/app/src/main/res/drawable/ic_snowflake.png diff --git a/app/src/main/res/drawable/ic_tor.png b/app/src/main/res/drawable/ic_tor.png Binary files differnew file mode 100644 index 00000000..a5f9ae89 --- /dev/null +++ b/app/src/main/res/drawable/ic_tor.png diff --git a/app/src/main/res/drawable/v_vertical_gradient.xml b/app/src/main/res/drawable/v_vertical_gradient.xml new file mode 100644 index 00000000..877634b5 --- /dev/null +++ b/app/src/main/res/drawable/v_vertical_gradient.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:angle="270" + android:startColor="#00FFFFFF" + android:endColor="#FFFFFFFF" + android:type="linear" /> +</shape> diff --git a/app/src/main/res/layout-xlarge/v_loading_screen.xml b/app/src/main/res/layout-xlarge/v_loading_screen.xml index ed25f07b..0b71099e 100644 --- a/app/src/main/res/layout-xlarge/v_loading_screen.xml +++ b/app/src/main/res/layout-xlarge/v_loading_screen.xml @@ -56,4 +56,142 @@ android:layout_marginTop="@dimen/standard_margin" /> + <RelativeLayout + android:id="@+id/connection_detail_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="30dp" + android:visibility="gone" + tools:visibility="visible" + > + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/connection_details_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/connection_details" + android:gravity="start" + android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" + android:paddingBottom="@dimen/stdpadding" + android:paddingStart="4dp" + android:paddingLeft="4dp" + android:paddingEnd="4dp" + android:paddingRight="4dp" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/tor_icon" + android:layout_width="35dp" + android:layout_height="35dp" + android:src="@drawable/ic_tor" + android:layout_below="@id/connection_details_title" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginBottom="@dimen/stdpadding" + /> + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/tor_state" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/connection_details_title" + 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_toRightOf="@+id/tor_icon" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:gravity="bottom" + tools:text="test 12321 123 \n sdf,sdf,m\nn 123 " + android:ellipsize="end" + + tools:visibility="visible" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/snowflake_icon" + android:layout_width="35dp" + android:layout_height="35dp" + android:src="@drawable/ic_snowflake" + android:layout_below="@id/tor_icon" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginBottom="@dimen/stdpadding" + /> + <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: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_toRightOf="@+id/snowflake_icon" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:paddingBottom="1dp" + android:gravity="bottom" + tools:text="test \n another \n and a third \n blkud" + android:ellipsize="end" + tools:visibility="visible" + /> + <Button + android:id="@+id/btn_connection_detail" + android:layout_marginTop="30dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_below="@id/snowflake_icon" + android:text="@string/show_log" + android:visibility="visible" + /> + </RelativeLayout> + <RelativeLayout + android:id="@+id/log_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + tools:visibility="visible" + > + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/connection_detail_logs_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/log_fragment_title" + android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" + android:layout_alignParentTop="true" + android:paddingStart="4dp" + android:paddingLeft="4dp" + android:paddingEnd="4dp" + android:paddingRight="4dp" + android:paddingTop="@dimen/stdpadding" + android:paddingBottom="@dimen/stdpadding" + /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/connection_detail_logs" + android:layout_below="@+id/connection_detail_logs_title" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:listitem="@layout/v_log_item" + android:isScrollContainer="false" + /> + + <ImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignBottom="@+id/connection_detail_logs" + android:layout_alignTop="@id/connection_detail_logs" + android:src="@drawable/v_vertical_gradient" + android:layout_marginTop="200dp" + android:importantForAccessibility="no" + /> + </RelativeLayout> + </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/v_add_provider.xml b/app/src/main/res/layout/v_add_provider.xml deleted file mode 100644 index 933f19d0..00000000 --- a/app/src/main/res/layout/v_add_provider.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout 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:id="@+id/loading_screen" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - android:visibility="gone" - tools:visibility="visible"> - - <androidx.appcompat.widget.AppCompatImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:adjustViewBounds="true" - app:tint="@color/colorPrimary" - app:srcCompat="@drawable/action_history" - android:layout_marginTop="@dimen/loading_screen_icon_vertical_margin" - android:layout_marginBottom="@dimen/loading_screen_icon_vertical_margin" - /> - - <androidx.appcompat.widget.AppCompatTextView - android:id="@+id/progressbar_title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:fadingEdge="horizontal" - android:singleLine="true" - android:text="@string/introduce_new_provider" - android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" - android:layout_marginTop="@dimen/standard_margin" - android:layout_marginBottom="@dimen/standard_margin" - /> - - <androidx.appcompat.widget.AppCompatTextView - android:id="@+id/progressbar_description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:fadingEdge="horizontal" - android:maxLines="2" - android:text="@string/configuring_provider" - android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" - android:layout_marginTop="@dimen/standard_margin" - android:layout_marginBottom="@dimen/standard_margin" - tools:text="test" - tools:visibility="visible" - /> - - <ProgressBar - android:id="@+id/progressbar" - style="@style/Widget.AppCompat.ProgressBar.Horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:indeterminate="true" - android:layout_marginTop="@dimen/standard_margin" - /> - -</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/v_loading_screen.xml b/app/src/main/res/layout/v_loading_screen.xml index f7f58e7b..9942a1c5 100644 --- a/app/src/main/res/layout/v_loading_screen.xml +++ b/app/src/main/res/layout/v_loading_screen.xml @@ -30,7 +30,6 @@ android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" android:layout_marginTop="@dimen/standard_margin" android:layout_marginBottom="@dimen/standard_margin" - tools:text="title" /> <androidx.appcompat.widget.AppCompatTextView @@ -56,4 +55,142 @@ android:layout_marginTop="@dimen/standard_margin" /> + <RelativeLayout + android:id="@+id/connection_detail_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="30dp" + android:visibility="gone" + tools:visibility="visible" + > + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/connection_details_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/show_log" + android:gravity="start" + android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" + android:paddingBottom="@dimen/stdpadding" + android:paddingStart="4dp" + android:paddingLeft="4dp" + android:paddingEnd="4dp" + android:paddingRight="4dp" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/tor_icon" + android:layout_width="35dp" + android:layout_height="35dp" + android:src="@drawable/ic_tor" + android:layout_below="@id/connection_details_title" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginBottom="@dimen/stdpadding" + /> + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/tor_state" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/connection_details_title" + 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_toRightOf="@+id/tor_icon" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:gravity="bottom" + tools:text="test 12321 123 \n sdf,sdf,m\nn 123 " + android:ellipsize="end" + + tools:visibility="visible" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/snowflake_icon" + android:layout_width="35dp" + android:layout_height="35dp" + android:src="@drawable/ic_snowflake" + android:layout_below="@id/tor_icon" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginBottom="@dimen/stdpadding" + /> + <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: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_toRightOf="@+id/snowflake_icon" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:paddingBottom="1dp" + android:gravity="bottom" + tools:text="test \n another \n and a third \n blkud" + android:ellipsize="end" + tools:visibility="visible" + /> + <Button + android:id="@+id/btn_connection_detail" + android:layout_marginTop="30dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_below="@id/snowflake_icon" + android:text="@string/show_log" + android:visibility="visible" + /> + </RelativeLayout> + <RelativeLayout + android:id="@+id/log_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + tools:visibility="visible" + > + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/connection_detail_logs_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/log_fragment_title" + android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" + android:layout_alignParentTop="true" + android:paddingStart="4dp" + android:paddingLeft="4dp" + android:paddingEnd="4dp" + android:paddingRight="4dp" + android:paddingTop="@dimen/stdpadding" + android:paddingBottom="@dimen/stdpadding" + /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/connection_detail_logs" + android:layout_below="@+id/connection_detail_logs_title" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:listitem="@layout/v_log_item" + android:isScrollContainer="false" + /> + + <ImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignBottom="@+id/connection_detail_logs" + android:layout_alignTop="@id/connection_detail_logs" + android:src="@drawable/v_vertical_gradient" + android:layout_marginTop="200dp" + android:importantForAccessibility="no" + /> + </RelativeLayout> + </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/v_log_item.xml b/app/src/main/res/layout/v_log_item.xml new file mode 100644 index 00000000..c3039f46 --- /dev/null +++ b/app/src/main/res/layout/v_log_item.xml @@ -0,0 +1,16 @@ +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" + android:gravity="center_vertical" + tools:text="test \ntest2\ntest3" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:paddingRight="?android:attr/listPreferredItemPaddingRight" + android:background="?android:attr/activatedBackgroundIndicator" + android:paddingTop="2dp" + android:paddingBottom="2dp" + />
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4c5cffd4..0b3d1d9b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ <string name="switch_provider_menu_option">Switch provider</string> <string name="info">info</string> <string name="show_connection_details">Show connection details</string> + <string name="connection_details">Connection details</string> <string name="routes_info">Routes: %s</string> <string name="routes_info6">IPv6 routes: %s</string> <string name="error_empty_username">The username must not be empty.</string> |