diff options
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/base/views')
8 files changed, 449 insertions, 11 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java index 977056f7..0957712b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java @@ -7,10 +7,10 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; -import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; @@ -23,7 +23,7 @@ import se.leap.bitmaskclient.base.fragments.TetheringDialog; public class IconCheckboxEntry extends LinearLayout { @BindView(android.R.id.text1) - TextView textView; + AppCompatTextView textView; @BindView(R.id.material_icon) AppCompatImageView iconView; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/IconSwitchEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/IconSwitchEntry.java index b6d72ab6..a499cdd1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/IconSwitchEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/IconSwitchEntry.java @@ -24,6 +24,7 @@ import androidx.annotation.DrawableRes; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.SwitchCompat; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -36,8 +37,8 @@ import se.leap.bitmaskclient.R; public class IconSwitchEntry extends LinearLayout { - private TextView textView; - private TextView subtitleView; + private AppCompatTextView textView; + private AppCompatTextView subtitleView; private AppCompatImageView iconView; private SwitchCompat switchView; private CompoundButton.OnCheckedChangeListener checkedChangeListener; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java index 6b9bd760..2d9525ed 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java @@ -4,25 +4,26 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import androidx.annotation.ColorRes; -import androidx.annotation.DrawableRes; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.TextView; + +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.widget.AppCompatTextView; import se.leap.bitmaskclient.R; public class IconTextEntry extends LinearLayout { - private TextView textView; + private AppCompatTextView textView; private ImageView iconView; - private TextView subtitleView; + private AppCompatTextView subtitleView; public IconTextEntry(Context context) { super(context); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java new file mode 100644 index 00000000..b2182d61 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java @@ -0,0 +1,58 @@ +package se.leap.bitmaskclient.base.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.GatewaysManager; + +public class LocationButton extends RelativeLayout { + private LocationIndicator locationIndicator; + private AppCompatTextView textView; + private AppCompatImageView bridgeView; + private AppCompatImageView recommendedView; + + public LocationButton(@NonNull Context context) { + super(context); + initLayout(context); + } + + public LocationButton(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initLayout(context); + } + + private void initLayout(Context context) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_location_button, this, true); + locationIndicator = rootview.findViewById(R.id.load_indicator); + textView = rootview.findViewById(R.id.text_location); + bridgeView = rootview.findViewById(R.id.bridge_icn); + recommendedView = rootview.findViewById(R.id.recommended_icn); + } + + public void setLocationLoad(GatewaysManager.Load load) { + locationIndicator.setLoad(load); + } + + public void setText(CharSequence text) { + textView.setText(text); + } + + public void showBridgeIndicator(boolean show) { + bridgeView.setVisibility(show ? VISIBLE : GONE); + } + + public void showRecommendedIndicator(boolean show) { + recommendedView.setVisibility(show? VISIBLE : GONE ); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/LocationIndicator.java b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationIndicator.java new file mode 100644 index 00000000..8245893d --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationIndicator.java @@ -0,0 +1,91 @@ +package se.leap.bitmaskclient.base.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.GatewaysManager; + +import static androidx.core.content.ContextCompat.getColor; + +public class LocationIndicator extends LinearLayout { + + private View level1; + private View level1_2; + private View level2; + private View level2_2; + private View level3; + private View level3_2; + + public LocationIndicator(Context context) { + super(context); + initLayout(context); + } + + public LocationIndicator(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initLayout(context); + + } + + public LocationIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context); + } + + + void initLayout(Context context) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_location_status_indicator, this, true); + level1 = rootview.findViewById(R.id.level1); + level1_2 = rootview.findViewById(R.id.level1_2); + level2 = rootview.findViewById(R.id.level2); + level2_2 = rootview.findViewById(R.id.level2_2); + level3 = rootview.findViewById(R.id.level3); + level3_2 = rootview.findViewById(R.id.level3_2); + } + + public void setLoad(GatewaysManager.Load load) { + switch (load) { + case GOOD: + level1.setBackgroundColor(getColor(getContext(), R.color.green200)); + level1_2.setBackgroundColor(getColor(getContext(), R.color.green200)); + level2.setBackgroundColor(getColor(getContext(), R.color.green200)); + level2_2.setBackgroundColor(getColor(getContext(), R.color.green200)); + level3.setBackgroundColor(getColor(getContext(), R.color.green200)); + level3_2.setBackgroundColor(getColor(getContext(), R.color.green200)); + break; + case AVERAGE: + level1.setBackgroundColor(getColor(getContext(), R.color.yellow200)); + level1_2.setBackgroundColor(getColor(getContext(), R.color.yellow200)); + level2.setBackgroundColor(getColor(getContext(), R.color.yellow200)); + level2_2.setBackgroundColor(getColor(getContext(), R.color.yellow200)); + level3.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level3_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + break; + case CRITICAL: + level1.setBackgroundColor(getColor(getContext(), R.color.red200)); + level1_2.setBackgroundColor(getColor(getContext(), R.color.red200)); + level2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level2_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level3.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level3_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + break; + default: + level1.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level1_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level2_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level3.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent)); + level3_2.setBackgroundColor(getColor(getContext(), R.color.black800_high_transparent));; + break; + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java b/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java new file mode 100644 index 00000000..c5ac4544 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java @@ -0,0 +1,124 @@ +package se.leap.bitmaskclient.base.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.drawable.AnimationDrawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.RelativeLayout; + +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.core.content.ContextCompat; + +import se.leap.bitmaskclient.R; + +public class MainButton extends RelativeLayout { + + private static final String TAG = MainButton.class.getSimpleName(); + + AppCompatImageView glow; + AppCompatImageView shadowLight; + AnimationDrawable glowAnimation; + + private boolean isOn = false; + private boolean isProcessing = false; + private boolean isError = true; + + + public MainButton(Context context) { + super(context); + initLayout(context); + } + + public MainButton(Context context, AttributeSet attrs) { + super(context, attrs); + initLayout(context); + } + + public MainButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context); + } + + + @TargetApi(21) + public MainButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initLayout(context); + } + + private void initLayout(Context context) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_main_btn, this, true); + + glow = rootview.findViewById(R.id.vpn_btn_glow); + glowAnimation = (AnimationDrawable) glow.getBackground(); + shadowLight = rootview.findViewById(R.id.vpn_btn_shadow_light); + } + + + private void stopGlowAnimation() { + AlphaAnimation fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f); + fadeOutAnimation.setDuration(300); + fadeOutAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + + @Override + public void onAnimationEnd(Animation animation) { + glow.setVisibility(GONE); + glowAnimation.stop(); + } + + @Override + public void onAnimationRepeat(Animation animation) {} + }); + glow.startAnimation(fadeOutAnimation); + } + + private void startGlowAnimation() { + glow.setAlpha(1.0f); + glow.setVisibility(VISIBLE); + glowAnimation.start(); + } + + public void updateState(boolean isOn, boolean isProcessing, boolean isError) { + if (this.isOn != isOn) { + this.isOn = isOn; + shadowLight.setVisibility(isOn ? VISIBLE : GONE); + } + + if (this.isProcessing != isProcessing) { + if (!isProcessing) { + stopGlowAnimation(); + } else { + startGlowAnimation(); + } + this.isProcessing = isProcessing; + } + + if (this.isError != isError) { + @DrawableRes int drawableResource = isOn ? R.drawable.on_off_btn_start_2_enabled : R.drawable.on_off_btn_start_2_disabled; + if (!isError) { + setImageWithTint(shadowLight, drawableResource, R.color.colorMainBtnHighlight); + } else { + setImageWithTint(shadowLight, drawableResource, R.color.colorMainBtnError); + } + this.isError = isError; + } + } + + private void setImageWithTint(AppCompatImageView view, @DrawableRes int resourceId, @ColorRes int color) { + view.setImageDrawable(ContextCompat.getDrawable(getContext(), resourceId)); + view.setColorFilter(ContextCompat.getColor(getContext(), color), PorterDuff.Mode.SRC_ATOP); + } + + + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java new file mode 100644 index 00000000..2a082579 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java @@ -0,0 +1,90 @@ +package se.leap.bitmaskclient.base.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; + +import de.blinkt.openvpn.core.connection.Connection; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.models.Location; +import se.leap.bitmaskclient.eip.GatewaysManager.Load; + +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; + +public class SelectLocationEntry extends LinearLayout { + + private static final String TAG = SelectLocationEntry.class.getSimpleName(); + AppCompatTextView title; + AppCompatTextView locationText; + SimpleCheckBox selectedView; + AppCompatImageView bridgesView; + LocationIndicator locationIndicator; + View divider; + + public SelectLocationEntry(Context context) { + super(context); + initLayout(context); + } + + public SelectLocationEntry(Context context, AttributeSet attrs) { + super(context, attrs); + initLayout(context); + } + + public SelectLocationEntry(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context); + } + + @TargetApi(21) + public SelectLocationEntry(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initLayout(context); + } + + private void initLayout(Context context) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_select_text_list_item, this, true); + title = rootview.findViewById(R.id.title); + locationIndicator = rootview.findViewById(R.id.quality); + locationText = rootview.findViewById(R.id.location); + bridgesView = rootview.findViewById(R.id.bridge_image); + selectedView = rootview.findViewById(R.id.selected); + divider = rootview.findViewById(R.id.divider); + } + + public void setTitle(String text) { + title.setText(text); + title.setVisibility(text != null ? VISIBLE : GONE); + } + public void setLocation(Location location, Connection.TransportType transportType) { + boolean valid = location.hasLocationInfo(); + locationText.setVisibility(valid ? VISIBLE : GONE); + locationIndicator.setVisibility(valid ? VISIBLE : GONE); + bridgesView.setVisibility(transportType == OBFS4 && location.supportsTransport(OBFS4) ? VISIBLE : GONE); + locationText.setText(location.getName()); + locationIndicator.setLoad(Load.getLoadByValue(location.getAverageLoad(transportType))); + selectedView.setChecked(location.selected); + } + + public void showDivider(boolean show) { + divider.setVisibility(show ? VISIBLE : GONE); + } + + public void setSelected(boolean selected) { + selectedView.setChecked(selected); + } + + public boolean isSelected() { + return selectedView.checkView.getVisibility() == VISIBLE; + } + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/SimpleCheckBox.java b/app/src/main/java/se/leap/bitmaskclient/base/views/SimpleCheckBox.java new file mode 100644 index 00000000..09a9132e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/SimpleCheckBox.java @@ -0,0 +1,73 @@ +package se.leap.bitmaskclient.base.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; + +import androidx.appcompat.widget.AppCompatImageView; + +import java.lang.ref.WeakReference; + +import se.leap.bitmaskclient.R; + +public class SimpleCheckBox extends RelativeLayout { + + AppCompatImageView checkView; + private WeakReference<OnCheckedChangeListener> checkedChangeListener = new WeakReference<OnCheckedChangeListener>(null); + private boolean checked; + + public interface OnCheckedChangeListener { + void onCheckedChanged(SimpleCheckBox simpleCheckBox, boolean isChecked); + } + + + public SimpleCheckBox(Context context) { + super(context); + initLayout(context); + } + + public SimpleCheckBox(Context context, AttributeSet attrs) { + super(context, attrs); + initLayout(context); + } + + public SimpleCheckBox(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context); + } + + @TargetApi(21) + public SimpleCheckBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initLayout(context); + } + + private void initLayout(Context context) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_simple_checkbox, this, true); + this.checkView = rootview.findViewById(R.id.check_view); + } + + public void setChecked(boolean checked) { + if (this.checked != checked) { + this.checkView.setVisibility(checked ? VISIBLE : INVISIBLE); + this.checked = checked; + OnCheckedChangeListener listener = checkedChangeListener.get(); + if (listener != null) { + listener.onCheckedChanged(this, this.checked); + } + } + } + + public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + checkedChangeListener = new WeakReference<>(listener); + } + + public void toggle() { + setChecked(!this.checked); + } +} |