diff options
author | cyberta <cyberta@riseup.net> | 2022-12-16 01:05:57 +0000 |
---|---|---|
committer | cyberta <cyberta@riseup.net> | 2022-12-16 01:05:57 +0000 |
commit | b4b5d98fe0bc0498773870990df2442f800158c4 (patch) | |
tree | 739de8a232d539804f8b61143879505271f52858 /app/src/main | |
parent | 62d9effae8fe5983056a7b225535ec763f03d87b (diff) | |
parent | d988fb9e977a78c31fa902a99308d97d95b8487b (diff) |
Merge branch 'rc_review' into 'master'
Bugfixes after Release Candidate Review
Closes #9121, #8934, and #9052
See merge request leap/bitmask_android!226
Diffstat (limited to 'app/src/main')
34 files changed, 501 insertions, 307 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index f56f2223..9225755e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -17,6 +17,7 @@ package se.leap.bitmaskclient.base; +import static androidx.appcompat.app.ActionBar.DISPLAY_SHOW_CUSTOM; import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; @@ -34,7 +35,6 @@ import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; -import static se.leap.bitmaskclient.base.utils.ViewHelper.isBrightColor; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; @@ -46,17 +46,14 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_TIMEOUT; import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.graphics.drawable.ColorDrawable; -import android.os.Build; import android.os.Bundle; import android.util.Log; -import android.view.Window; -import android.view.WindowManager; +import android.view.Gravity; -import androidx.annotation.ColorRes; -import androidx.annotation.StringRes; +import androidx.annotation.ColorInt; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; @@ -70,6 +67,7 @@ import org.json.JSONObject; import java.util.Observable; import java.util.Observer; +import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.fragments.EipFragment; import se.leap.bitmaskclient.base.fragments.ExcludeAppsFragment; @@ -81,7 +79,7 @@ import se.leap.bitmaskclient.base.fragments.SettingsFragment; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.base.utils.ViewHelper; +import se.leap.bitmaskclient.base.views.ActionBarTitle; import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipSetupListener; @@ -103,8 +101,6 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, public final static String ACTION_SHOW_DIALOG_FRAGMENT = "action_show_dialog_fragment"; public final static String ACTION_SHOW_MOTD_FRAGMENT = "action_show_motd_fragment"; - private @ColorRes int actionBarTextColor = R.color.colorActionBarTitleFont; - /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. */ @@ -113,8 +109,7 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.a_main); - setSupportActionBar(findViewById(R.id.toolbar)); - + setupActionBar(); navigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); @@ -143,7 +138,6 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, newFragment.setArguments(bundle); } fragmentManagerEnhanced.replace(R.id.main_container, newFragment, MainActivity.TAG); - hideActionBarSubTitle(); } else { super.onBackPressed(); } @@ -171,7 +165,6 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } bundle.putParcelable(PROVIDER_KEY, provider); fragment.setArguments(bundle); - hideActionBarSubTitle(); showActionBar(); break; case ACTION_SHOW_MOTD_FRAGMENT: @@ -181,12 +174,10 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, motdBundle.putString(EXTRA_MOTD_MSG, intent.getStringExtra(EXTRA_MOTD_MSG)); } fragment.setArguments(motdBundle); - hideActionBarSubTitle(); hideActionBar(); break; case ACTION_SHOW_LOG_FRAGMENT: fragment = new LogFragment(); - setActionBarTitle(R.string.log_fragment_title); showActionBar(); break; case ACTION_SHOW_DIALOG_FRAGMENT: @@ -209,6 +200,31 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } } + private void setupActionBar() { + setSupportActionBar(findViewById(R.id.toolbar)); + final ActionBar actionBar = getSupportActionBar(); + Context context = actionBar.getThemedContext(); + actionBar.setDisplayOptions(DISPLAY_SHOW_CUSTOM); + + ActionBarTitle actionBarTitle = new ActionBarTitle(context); + actionBarTitle.setTitleCaps(BuildConfig.actionbar_capitalize_title); + actionBarTitle.setTitle(getString(R.string.app_name)); + + @ColorInt int titleColor = ContextCompat.getColor(context, R.color.colorActionBarTitleFont); + actionBarTitle.setTitleTextColor(titleColor); + + actionBarTitle.setCentered(BuildConfig.actionbar_center_title); + if (BuildConfig.actionbar_center_title) { + ActionBar.LayoutParams params = new ActionBar.LayoutParams( + ActionBar.LayoutParams.WRAP_CONTENT, + ActionBar.LayoutParams.MATCH_PARENT, + Gravity.CENTER); + actionBar.setCustomView(actionBarTitle, params); + } else { + actionBar.setCustomView(actionBarTitle); + } + } + private void hideActionBar() { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { @@ -223,53 +239,6 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } } - private void hideActionBarSubTitle() { - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setSubtitle(null); - } - } - private void setActionBarTitle(@StringRes int stringId) { - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setSubtitle(stringId); - } - } - - public @ColorRes int getActionBarTitleColor() { - return actionBarTextColor; - } - - public void setDefaultActivityBarColor() { - setActivityBarColor(R.color.colorPrimary, R.color.colorPrimaryDark, R.color.colorActionBarTitleFont); - } - - public void setActivityBarColor(@ColorRes int primaryColor, @ColorRes int secondaryColor, @ColorRes int textColor) { - ActionBar bar = getSupportActionBar(); - if (bar == null) { - return; - } - int color = ContextCompat.getColor(this, secondaryColor); - bar.setBackgroundDrawable(new ColorDrawable(color)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - Window window = this.getWindow(); - window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - window.setStatusBarColor(ContextCompat.getColor(this, primaryColor)); - } - - if (bar.getTitle() == null) { - return; - } - - if (textColor == 0) { - actionBarTextColor = isBrightColor(color) ? R.color.actionbar_connectivity_state_text_color_dark : R.color.actionbar_connectivity_state_text_color_light; - } else { - actionBarTextColor = textColor; - } - - ViewHelper.setActionBarTextColor(bar, actionBarTextColor); - } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -313,7 +282,6 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, fragment.setArguments(arguments); new FragmentManagerEnhanced(getSupportFragmentManager()) .replace(R.id.main_container, fragment, MainActivity.TAG); - hideActionBarSubTitle(); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java index 646637b9..e92aa703 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java @@ -18,7 +18,7 @@ import se.leap.bitmaskclient.R; import static android.view.View.VISIBLE; import static se.leap.bitmaskclient.R.string.about_fragment_title; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarTitle; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; public class AboutFragment extends Fragment { @@ -36,7 +36,7 @@ public class AboutFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.f_about, container, false); unbinder = ButterKnife.bind(this, view); - setActionBarTitle(this, about_fragment_title); + setActionBarSubtitle(this, about_fragment_title); return view; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index 02feafd3..409efcf0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -16,7 +16,6 @@ */ package se.leap.bitmaskclient.base.fragments; -import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; @@ -36,16 +35,12 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; import android.app.Activity; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; import android.content.SharedPreferences; import android.graphics.drawable.Animatable; -import android.graphics.drawable.Animatable2; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.IBinder; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; @@ -65,17 +60,13 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; -import androidx.vectordrawable.graphics.drawable.Animatable2Compat; import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback; import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; import java.util.Observable; import java.util.Observer; -import java.util.concurrent.atomic.AtomicBoolean; import de.blinkt.openvpn.core.ConnectionStatus; -import de.blinkt.openvpn.core.IOpenVPNServiceInternal; -import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; @@ -84,6 +75,7 @@ import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.ViewHelper; import se.leap.bitmaskclient.base.views.LocationButton; import se.leap.bitmaskclient.base.views.MainButton; import se.leap.bitmaskclient.databinding.FEipBinding; @@ -129,10 +121,6 @@ public class EipFragment extends Fragment implements Observer { //------------------------ AlertDialog alertDialog; - private IOpenVPNServiceInternal mService; - // We use this service connection to detect if openvpn is running without network - private EipFragmentServiceConnection openVpnConnection; - @Override public void onAttach(Context context) { super.onAttach(context); @@ -166,7 +154,6 @@ public class EipFragment extends Fragment implements Observer { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - openVpnConnection = new EipFragmentServiceConnection(); eipStatus = EipStatus.getInstance(); providerObservable = ProviderObservable.getInstance(); torStatusObservable = TorStatusObservable.getInstance(); @@ -178,8 +165,6 @@ public class EipFragment extends Fragment implements Observer { } gatewaysManager = new GatewaysManager(getContext()); - - } @Override @@ -192,6 +177,7 @@ public class EipFragment extends Fragment implements Observer { mainDescription = binding.mainDescription; subDescription = binding.subDescription; stateView = binding.stateView; + ViewHelper.setActionBarTitle(this, R.string.app_name); eipStatus.addObserver(this); torStatusObservable.addObserver(this); @@ -233,16 +219,14 @@ public class EipFragment extends Fragment implements Observer { @Override public void onResume() { super.onResume(); - if (!eipStatus.isDisconnected()) { - openVpnConnection.bindService(); - } + Log.d(TAG, "onResume"); handleNewState(); } @Override public void onPause() { super.onPause(); - openVpnConnection.unbindService(); + Log.d(TAG, "onPause"); } @Override @@ -270,10 +254,9 @@ public class EipFragment extends Fragment implements Observer { @Override public void onDestroyView() { super.onDestroyView(); - Activity activity = getActivity(); - if (activity != null) { - ((MainActivity) activity).setDefaultActivityBarColor(); - } + Log.d(TAG, "onDestroyView"); + + ViewHelper.setDefaultActivityBarColor(getActivity()); eipStatus.deleteObserver(this); providerObservable.deleteObserver(this); torStatusObservable.deleteObserver(this); @@ -290,7 +273,7 @@ public class EipFragment extends Fragment implements Observer { } void handleIcon() { - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) + if (eipStatus.isVPNRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) handleSwitchOff(); else handleSwitchOn(); @@ -326,7 +309,7 @@ public class EipFragment extends Fragment implements Observer { } private void handleSwitchOff() { - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) { + if (eipStatus.isVPNRunningWithoutNetwork() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) { askPendingStartCancellation(); } else if (eipStatus.isConnected()) { askToStopEIP(); @@ -420,13 +403,6 @@ public class EipFragment extends Fragment implements Observer { eipStatus = (EipStatus) observable; handleNewStateOnMain(); - if (eipStatus.isConnecting()) { - openVpnConnection.bindService(); - } - if ("NOPROCESS".equals(EipStatus.getInstance().getState())) { - //assure that the Service is shutdown completely if openvpn was stopped - openVpnConnection.unbindService(); - } } else if (observable instanceof ProviderObservable) { provider = ((ProviderObservable) observable).getCurrentProvider(); } else if (observable instanceof TorStatusObservable && EipStatus.getInstance().isUpdatingVpnCert()) { @@ -444,11 +420,7 @@ public class EipFragment extends Fragment implements Observer { } private void setActivityBarColor(@ColorRes int primaryColor, @ColorRes int secondaryColor) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - ((MainActivity) getActivity()).setActivityBarColor(primaryColor, secondaryColor, R.color.actionbar_connectivity_state_text_color_dark); + ViewHelper.setActivityBarColor(getActivity(), primaryColor, secondaryColor, R.color.actionbar_connectivity_state_text_color_dark); } private void handleNewState() { @@ -480,7 +452,7 @@ public class EipFragment extends Fragment implements Observer { } background.setImageResource(R.drawable.bg_connecting); animateState(R.drawable.state_connecting); - mainButton.updateState(false, true, false); + mainButton.updateState(false, true); setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isConnecting()) { setMainButtonEnabled(true); @@ -496,11 +468,11 @@ public class EipFragment extends Fragment implements Observer { subDescription.setText(null); background.setImageResource(R.drawable.bg_connecting); animateState(R.drawable.state_connecting); - mainButton.updateState(false, true, false); + mainButton.updateState(false, true); setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isConnected()) { setMainButtonEnabled(true); - mainButton.updateState(true, false, false); + mainButton.updateState(true, false); Connection.TransportType transportType = PreferenceHelper.getUseBridges(getContext()) ? Connection.TransportType.OBFS4 : Connection.TransportType.OPENVPN; locationButton.setLocationLoad(PreferenceHelper.useObfuscationPinning(getContext()) ? GatewaysManager.Load.UNKNOWN : gatewaysManager.getLoadForLocation(VpnStatus.getLastConnectedVpnName(), transportType)); locationButton.setText(VpnStatus.getLastConnectedVpnName()); @@ -511,10 +483,10 @@ public class EipFragment extends Fragment implements Observer { background.setImageResource(R.drawable.bg_connected); animateState(R.drawable.state_connected); setActivityBarColor(R.color.bg_running_top, R.color.bg_running_top_light_transparent); - } else if(isOpenVpnRunningWithoutNetwork()) { + } else if(eipStatus.isVPNRunningWithoutNetwork()) { Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); setMainButtonEnabled(true); - mainButton.updateState(true, false, true); + mainButton.updateState(false, true); locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); @@ -525,6 +497,8 @@ public class EipFragment extends Fragment implements Observer { animateState(R.drawable.state_connecting); setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { + setMainButtonEnabled(true); + mainButton.updateState(false, true); locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); @@ -536,7 +510,7 @@ public class EipFragment extends Fragment implements Observer { setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isDisconnecting()) { setMainButtonEnabled(false); - mainButton.updateState(false, false, false); + mainButton.updateState(false, false); mainDescription.setText(R.string.eip_status_unsecured); background.setImageResource(R.drawable.bg_disconnected); if (previousEipLevel == EipStatus.EipLevel.CONNECTED) { @@ -547,7 +521,7 @@ public class EipFragment extends Fragment implements Observer { setActivityBarColor(R.color.bg_disconnected_top, R.color.bg_disconnected_top_light_transparent); } else if (eipStatus.isBlocking()) { setMainButtonEnabled(true); - mainButton.updateState(false, true, true); + mainButton.updateState(false, true); locationButton.setText(R.string.no_location); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); @@ -560,7 +534,7 @@ public class EipFragment extends Fragment implements Observer { } else { locationButton.setText(R.string.vpn_button_turn_on); setMainButtonEnabled(true); - mainButton.updateState(false, false, false); + mainButton.updateState(false, false); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); String city = getPreferredCity(getContext()); @@ -614,19 +588,6 @@ public class EipFragment extends Fragment implements Observer { } } - private boolean isOpenVpnRunningWithoutNetwork() { - boolean isRunning = false; - try { - isRunning = eipStatus.getLevel() == LEVEL_NONETWORK && - mService.isVpnRunning(); - } catch (Exception e) { - //eat me - e.printStackTrace(); - } - - return isRunning; - } - private void updateInvalidVpnCertificate() { eipStatus.setUpdatingVpnCert(true); ProviderAPICommand.execute(getContext(), UPDATE_INVALID_VPN_CERTIFICATE, provider); @@ -646,52 +607,6 @@ public class EipFragment extends Fragment implements Observer { } } - private class EipFragmentServiceConnection implements ServiceConnection { - private final AtomicBoolean bind = new AtomicBoolean(false); - - void bindService() { - Activity activity = getActivity(); - if (activity == null) { - Log.e(TAG, "activity is null when binding OpenVpn"); - return; - } - if (!bind.get()) { - activity.runOnUiThread(() -> { - Intent intent = new Intent(activity, OpenVPNService.class); - intent.setAction(OpenVPNService.START_SERVICE); - - activity.bindService(intent, EipFragmentServiceConnection.this, Context.BIND_AUTO_CREATE); - bind.set(true); - }); - } - } - - void unbindService() { - Activity activity = getActivity(); - if (activity == null) { - return; - } - if (bind.get()) { - activity.runOnUiThread(() -> { - activity.unbindService(EipFragmentServiceConnection.this); - bind.set(false); - }); - } - } - - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - mService = IOpenVPNServiceInternal.Stub.asInterface(service); - handleNewState(); - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mService = null; - } - } - public void showDonationReminderDialog() { try { FragmentTransaction fragmentTransaction = new FragmentManagerEnhanced( diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ExcludeAppsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ExcludeAppsFragment.java index 1574dbb0..98c2e438 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ExcludeAppsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ExcludeAppsFragment.java @@ -312,7 +312,7 @@ public class ExcludeAppsFragment extends Fragment implements AdapterView.OnItemC mListView.setOnItemClickListener(this); mListView.setEmptyView(v.findViewById(R.id.loading_container)); - ViewHelper.setActionBarTitle(this, exclude_apps_fragment_title); + ViewHelper.setActionBarSubtitle(this, exclude_apps_fragment_title); new Thread(() -> mListAdapter.populateList(getActivity())).start(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java index a2bfff7c..749ffd9f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java @@ -52,7 +52,6 @@ import se.leap.bitmaskclient.eip.GatewaysManager; import static android.content.Context.MODE_PRIVATE; import static android.view.View.GONE; import static android.view.View.VISIBLE; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; @@ -60,7 +59,7 @@ import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarTitle; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; interface LocationListSelectionListener { void onLocationManuallySelected(Location location); @@ -90,16 +89,16 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca super.onCreate(savedInstanceState); gatewaysManager = new GatewaysManager(getContext()); eipStatus = EipStatus.getInstance(); - eipStatus.addObserver(this); preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - selectedTransport = getUseBridges(preferences) ? PT : OPENVPN; - preferences.registerOnSharedPreferenceChangeListener(this); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment + selectedTransport = getUseBridges(preferences) ? PT : OPENVPN; + preferences.registerOnSharedPreferenceChangeListener(this); + eipStatus.addObserver(this); return inflater.inflate(R.layout.f_gateway_selection, container, false); } @@ -109,7 +108,7 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca initRecyclerView(); initRecommendedLocationEntry(); initBridgesHint(view); - setActionBarTitle(this, R.string.gateway_selection_title); + setActionBarSubtitle(this, R.string.gateway_selection_title); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/LogFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/LogFragment.java index 6f0f29ef..8f73595d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/LogFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/LogFragment.java @@ -5,6 +5,10 @@ package se.leap.bitmaskclient.base.fragments; +import static de.blinkt.openvpn.core.OpenVPNService.humanReadableByteCount; +import static se.leap.bitmaskclient.R.string.log_fragment_title; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -59,10 +63,6 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Constants; -import static de.blinkt.openvpn.core.OpenVPNService.humanReadableByteCount; -import static se.leap.bitmaskclient.R.string.log_fragment_title; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarTitle; - public class LogFragment extends ListFragment implements StateListener, SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener, VpnStatus.ByteCountListener { public static final String TAG = LogFragment.class.getSimpleName(); private static final String LOGTIMEFORMAT = "logtimeformat"; @@ -533,7 +533,7 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar. if (mShowOptionsLayout) mOptionsLayout.setVisibility(View.VISIBLE); - setActionBarTitle(this, log_fragment_title); + setActionBarSubtitle(this, log_fragment_title); return v; } @@ -557,7 +557,6 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index fe36e00a..68435fec 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -38,9 +38,6 @@ import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -48,15 +45,11 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import androidx.annotation.ColorRes; import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import androidx.appcompat.widget.ViewUtils; -import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; @@ -70,7 +63,6 @@ import se.leap.bitmaskclient.base.FragmentManagerEnhanced; import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.base.utils.ViewHelper; import se.leap.bitmaskclient.base.views.IconSwitchEntry; import se.leap.bitmaskclient.base.views.IconTextEntry; import se.leap.bitmaskclient.eip.EipStatus; @@ -179,7 +171,6 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen this.drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); toolbar = this.drawerLayout.findViewById(R.id.toolbar); - setupActionBar(); setupEntries(); setupActionBarDrawerToggle(activity); @@ -240,7 +231,6 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen Bundle arguments = new Bundle(); arguments.putParcelable(PROVIDER_KEY, currentProvider); fragment.setArguments(arguments); - hideActionBarSubTitle(); fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); closeDrawer(); }); @@ -307,6 +297,10 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen manualGatewaySelection.setOnClickListener(v -> { FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); closeDrawer(); + Fragment current = fragmentManager.findFragmentByTag(MainActivity.TAG); + if (current instanceof GatewaySelectionFragment) { + return; + } Fragment fragment = new GatewaySelectionFragment(); fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); }); @@ -351,15 +345,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen } } - private ActionBar setupActionBar() { - AppCompatActivity activity = (AppCompatActivity) getActivity(); - activity.setSupportActionBar(toolbar); - final ActionBar actionBar = activity.getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setHomeButtonEnabled(true); - actionBar.setDisplayShowTitleEnabled(true); - return actionBar; - } + @NonNull private void closeDrawerWithDelay() { @@ -421,14 +407,6 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (drawerLayout != null && isDrawerOpen()) { - showGlobalContextActionBar(); - } - super.onCreateOptionsMenu(menu, inflater); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { if (drawerToggle.onOptionsItemSelected(item)) { return true; @@ -442,33 +420,6 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen preferences.unregisterOnSharedPreferenceChangeListener(this); } - /** - * Per the navigation drawer design guidelines, updates the action bar to show the global app - * 'context', rather than just what's in the current screen. - */ - private void showGlobalContextActionBar() { - ActionBar actionBar = getActionBar(); - actionBar.setDisplayShowTitleEnabled(true); - actionBar.setTitle(R.string.app_name); - Activity activity = getActivity(); - if (activity == null) { - return; - } - @ColorRes int titleColor = ((MainActivity) activity).getActionBarTitleColor(); - ViewHelper.setActionBarTextColor(actionBar, titleColor); - } - - private ActionBar getActionBar() { - return ((AppCompatActivity) getActivity()).getSupportActionBar(); - } - - private void hideActionBarSubTitle() { - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.setSubtitle(null); - } - } - public void refresh() { Provider currentProvider = ProviderObservable.getInstance().getCurrentProvider(); account.setText(currentProvider.getName()); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index f7d20aa9..d5bbd2c5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -24,7 +24,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseObfuscatio import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarTitle; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; import android.app.AlertDialog; import android.content.Context; @@ -90,7 +90,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh initGatewayPinningEntry(view); initExperimentalTransportsEntry(view); initObfuscationPinningEntry(view); - setActionBarTitle(this, advanced_settings); + setActionBarSubtitle(this, advanced_settings); return view; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java index 8076f99e..8f4d7862 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java @@ -1,26 +1,39 @@ package se.leap.bitmaskclient.base.utils; +import android.app.Activity; import android.app.Notification; import android.content.Context; import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; import androidx.annotation.ColorRes; import androidx.annotation.DimenRes; import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.AppCompatTextView; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.views.ActionBarTitle; + /** * Created by cyberta on 29.06.18. */ public class ViewHelper { + private static final String TAG = ViewHelper.class.getSimpleName(); + public static int convertDimensionToPx(Context context, @DimenRes int dimension) { return context.getResources().getDimensionPixelSize(dimension); } @@ -30,16 +43,81 @@ public class ViewHelper { * @param fragment * @param stringId */ + public static void setActionBarSubtitle(Fragment fragment, @StringRes int stringId) { + AppCompatActivity appCompatActivity = (AppCompatActivity) fragment.getActivity(); + if (appCompatActivity != null) { + ActionBar actionBar = appCompatActivity.getSupportActionBar(); + if (actionBar != null) { + View customView = actionBar.getCustomView(); + if (customView instanceof ActionBarTitle) { + ActionBarTitle actionBarTitle = (ActionBarTitle) customView; + actionBarTitle.setSubtitle(stringId); + actionBarTitle.showSubtitle(true); + } + } + } + } + + /** + * Sets the subtitle of an activities action bar. The activity needs to be an AppCompatActivity. + * @param fragment + * @param stringId + */ public static void setActionBarTitle(Fragment fragment, @StringRes int stringId) { AppCompatActivity appCompatActivity = (AppCompatActivity) fragment.getActivity(); if (appCompatActivity != null) { ActionBar actionBar = appCompatActivity.getSupportActionBar(); if (actionBar != null) { - actionBar.setSubtitle(stringId); + View customView = actionBar.getCustomView(); + if (customView instanceof ActionBarTitle) { + ActionBarTitle actionBarTitle = (ActionBarTitle) customView; + actionBarTitle.setTitle(stringId); + actionBarTitle.showSubtitle(false); + } else { + Log.e(TAG, "ActionBar has no custom action title!"); + } } } } + + public static void setDefaultActivityBarColor(Activity activity) { + setActivityBarColor(activity, R.color.colorPrimary, R.color.colorPrimaryDark, R.color.colorActionBarTitleFont); + } + + public static void setActivityBarColor(Activity activity, @ColorRes int primaryColor, @ColorRes int secondaryColor, @ColorRes int textColor) { + if (!(activity instanceof AppCompatActivity)) { + return; + } + + ActionBar bar = ((AppCompatActivity) activity).getSupportActionBar(); + if (bar == null) { + return; + } + int color = ContextCompat.getColor(activity, secondaryColor); + bar.setBackgroundDrawable(new ColorDrawable(color)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(ContextCompat.getColor(activity, primaryColor)); + } + + int actionBarTextColor; + if (textColor == 0) { + actionBarTextColor = isBrightColor(color) ? R.color.actionbar_connectivity_state_text_color_dark : R.color.actionbar_connectivity_state_text_color_light; + } else { + actionBarTextColor = textColor; + } + + View customView = bar.getCustomView(); + if (customView instanceof ActionBarTitle) { + ActionBarTitle actionBarTitle = (ActionBarTitle) customView; + actionBarTitle.setTitleTextColor(ContextCompat.getColor(bar.getThemedContext(), actionBarTextColor)); + } + } + + public static boolean isBrightColor(int color) { if (android.R.color.transparent == color) return true; @@ -61,7 +139,7 @@ public class ViewHelper { public static void setActionBarTextColor(ActionBar bar, @ColorRes int titleColor) { CharSequence titleCharSequence = bar.getTitle(); - if (titleCharSequence == null) { + if (titleCharSequence == null || titleCharSequence.length() == 0) { return; } String title = titleCharSequence.toString(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/ActionBarTitle.java b/app/src/main/java/se/leap/bitmaskclient/base/views/ActionBarTitle.java new file mode 100644 index 00000000..a151305e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/ActionBarTitle.java @@ -0,0 +1,96 @@ +package se.leap.bitmaskclient.base.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.widget.RelativeLayout; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.widget.AppCompatTextView; +import androidx.appcompat.widget.LinearLayoutCompat; + +import se.leap.bitmaskclient.databinding.VActionbarTitleBinding; + +public class ActionBarTitle extends LinearLayoutCompat { + private AppCompatTextView actionBarTitle; + private AppCompatTextView actionBarSubtitle; + private LinearLayoutCompat container; + + public ActionBarTitle(@NonNull Context context) { + super(context); + initLayout(context); + } + + public ActionBarTitle(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initLayout(context); + } + + public ActionBarTitle(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context); + } + + public void initLayout(Context context) { + VActionbarTitleBinding binding = VActionbarTitleBinding.inflate(LayoutInflater.from(context), this, true); + actionBarTitle = binding.actionBarTitle; + actionBarSubtitle = binding.actionBarSubtitle; + container = binding.actionBarTitleContainer; + } + + public void setTitle(CharSequence text) { + actionBarTitle.setText(text); + } + + public void setTitleCaps(boolean caps) { + actionBarTitle.setAllCaps(caps); + } + + public void setSubtitle(CharSequence text) { + actionBarSubtitle.setText(text); + } + + public void setTitle(@StringRes int resId) { + actionBarTitle.setText(resId); + } + + public void setSubtitle(@StringRes int resId) { + actionBarSubtitle.setText(resId); + } + + public void setTitleTextColor(@ColorInt int color) { + actionBarTitle.setTextColor(color); + } + + public void setSubtitleTextColor(@ColorInt int color) { + actionBarSubtitle.setTextColor(color); + } + + public void showSubtitle(boolean show) { + actionBarSubtitle.setVisibility(show ? VISIBLE : GONE); + } + + public void setCentered(boolean centered) { + LayoutParams titleLayoutParams = (LayoutParams) actionBarTitle.getLayoutParams(); + LayoutParams subtitleLayoutParams = (LayoutParams) actionBarSubtitle.getLayoutParams(); + LayoutParams containerLayoutParams = (LayoutParams) container.getLayoutParams(); + if (centered) { + titleLayoutParams.gravity = Gravity.CENTER; + subtitleLayoutParams.gravity = Gravity.CENTER; + containerLayoutParams.gravity = Gravity.CENTER; + } else { + titleLayoutParams.gravity = Gravity.NO_GRAVITY; + subtitleLayoutParams.gravity = Gravity.NO_GRAVITY; + containerLayoutParams.gravity = Gravity.NO_GRAVITY; + } + actionBarTitle.setLayoutParams(titleLayoutParams); + actionBarSubtitle.setLayoutParams(subtitleLayoutParams); + container.setLayoutParams(containerLayoutParams); + + + } +} 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 index 715063b5..fc86fc0b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java @@ -45,7 +45,7 @@ public class MainButton extends RelativeLayout { button = binding.button; } - public void updateState(boolean isOn, boolean isProcessing, boolean isError) { + public void updateState(boolean isOn, boolean isProcessing) { if (isProcessing) { button.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.button_circle_cancel)); } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index b3efd21f..88cdc715 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -594,7 +594,7 @@ public final class EIP extends JobIntentService implements Observer { } public static class VoidVpnServiceConnection implements Closeable { - private final Context context; + private Context context; private ServiceConnection serviceConnection; private VoidVpnService voidVpnService; @@ -608,6 +608,9 @@ public final class EIP extends JobIntentService implements Observer { @Override public void close() { context.unbindService(serviceConnection); + serviceConnection = null; + voidVpnService = null; + context = null; } private void initSynchronizedServiceConnection(final Context context) throws InterruptedException { @@ -649,7 +652,7 @@ public final class EIP extends JobIntentService implements Observer { */ @WorkerThread public static class OpenVpnServiceConnection implements Closeable { - private final Context context; + private Context context; private ServiceConnection serviceConnection; private IOpenVPNServiceInternal service; @@ -686,6 +689,9 @@ public final class EIP extends JobIntentService implements Observer { @Override public void close() { context.unbindService(serviceConnection); + serviceConnection = null; + service = null; + context = null; } public IOpenVPNServiceInternal getService() { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index c9cf6041..9244f531 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -16,6 +16,8 @@ */ package se.leap.bitmaskclient.eip; +import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; + import android.content.Context; import android.os.AsyncTask; import androidx.annotation.VisibleForTesting; @@ -92,6 +94,11 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return "RECONNECTING".equals(currentStatus.getState()); } + public boolean isVPNRunningWithoutNetwork() { + return currentStatus.getLevel() == LEVEL_NONETWORK && + !"NO_PROCESS".equals(currentStatus.getState()); + } + private void setEipLevel(ConnectionStatus level) { switch (level) { case LEVEL_CONNECTED: diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorServiceConnection.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorServiceConnection.java index dbfce2b5..87d3cad4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/TorServiceConnection.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorServiceConnection.java @@ -15,6 +15,9 @@ package se.leap.bitmaskclient.tor; * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; + import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -30,13 +33,9 @@ import java.io.Closeable; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import se.leap.bitmaskclient.providersetup.ProviderAPI; - -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; - public class TorServiceConnection implements Closeable { private static final String TAG = TorServiceConnection.class.getSimpleName(); - private final Context context; + private Context context; private ServiceConnection serviceConnection; private TorService torService; @@ -50,6 +49,9 @@ public class TorServiceConnection implements Closeable { @Override public void close() { context.unbindService(serviceConnection); + context = null; + serviceConnection = null; + torService = null; } private void initSynchronizedServiceConnection(final Context context) throws InterruptedException { diff --git a/app/src/main/res/color/button_state_font_color.xml b/app/src/main/res/color/button_state_font_color.xml deleted file mode 100644 index f7fed335..00000000 --- a/app/src/main/res/color/button_state_font_color.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@color/colorFontBtnEnabled" android:state_enabled="true"/> - <item android:color="@color/colorFontBtn"/> -</selector>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_cancel_pressed.xml b/app/src/main/res/drawable/button_circle_cancel_pressed.xml index b2efa78b..6b280959 100644 --- a/app/src/main/res/drawable/button_circle_cancel_pressed.xml +++ b/app/src/main/res/drawable/button_circle_cancel_pressed.xml @@ -51,10 +51,10 @@ </shape> </item> <item - android:top="68dp" - android:bottom="62dp" - android:left="50dp" - android:right="50dp" + android:top="88dp" + android:bottom="82dp" + android:left="70dp" + android:right="70dp" android:drawable="@drawable/ic_btn_cancel" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_cancel_released.xml b/app/src/main/res/drawable/button_circle_cancel_released.xml index 70d47257..cd93ab2b 100644 --- a/app/src/main/res/drawable/button_circle_cancel_released.xml +++ b/app/src/main/res/drawable/button_circle_cancel_released.xml @@ -44,7 +44,7 @@ android:type="radial" android:gradientRadius="125dp" android:centerX="0.51" - android:centerY="0.58" + android:centerY="0.55" android:startColor="#000000" android:centerColor="#000000" android:endColor="@color/transparent" /> @@ -52,10 +52,10 @@ </shape> </item> <item - android:top="65dp" - android:bottom="65dp" - android:left="50dp" - android:right="50dp" + android:top="85dp" + android:bottom="85dp" + android:left="70dp" + android:right="70dp" android:drawable="@drawable/ic_btn_cancel" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_start_pressed.xml b/app/src/main/res/drawable/button_circle_start_pressed.xml index dd8496c3..08712c47 100644 --- a/app/src/main/res/drawable/button_circle_start_pressed.xml +++ b/app/src/main/res/drawable/button_circle_start_pressed.xml @@ -36,9 +36,9 @@ </shape> </item> <item - android:top="68dp" - android:bottom="62dp" - android:left="50dp" - android:right="50dp" + android:top="78dp" + android:bottom="72dp" + android:left="60dp" + android:right="60dp" android:drawable="@drawable/ic_btn_on" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_start_released.xml b/app/src/main/res/drawable/button_circle_start_released.xml index ad748e9c..c47d1019 100644 --- a/app/src/main/res/drawable/button_circle_start_released.xml +++ b/app/src/main/res/drawable/button_circle_start_released.xml @@ -28,7 +28,7 @@ android:type="radial" android:gradientRadius="125dp" android:centerX="0.51" - android:centerY="0.58" + android:centerY="0.55" android:startColor="#000000" android:centerColor="#000000" android:endColor="@color/transparent" /> @@ -36,9 +36,9 @@ </shape> </item> <item - android:top="65dp" - android:bottom="65dp" - android:left="50dp" - android:right="50dp" + android:top="75dp" + android:bottom="75dp" + android:left="60dp" + android:right="60dp" android:drawable="@drawable/ic_btn_on" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_stop_pressed.xml b/app/src/main/res/drawable/button_circle_stop_pressed.xml index 79f794b2..52a5a88e 100644 --- a/app/src/main/res/drawable/button_circle_stop_pressed.xml +++ b/app/src/main/res/drawable/button_circle_stop_pressed.xml @@ -36,9 +36,9 @@ </shape> </item> <item - android:top="68dp" - android:bottom="62dp" - android:left="50dp" - android:right="50dp" + android:top="88dp" + android:bottom="82dp" + android:left="70dp" + android:right="70dp" android:drawable="@drawable/ic_btn_cancel" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_stop_released.xml b/app/src/main/res/drawable/button_circle_stop_released.xml index 62827b66..d29bfe1e 100644 --- a/app/src/main/res/drawable/button_circle_stop_released.xml +++ b/app/src/main/res/drawable/button_circle_stop_released.xml @@ -28,7 +28,7 @@ android:type="radial" android:gradientRadius="125dp" android:centerX="0.51" - android:centerY="0.58" + android:centerY="0.55" android:startColor="#000000" android:centerColor="#000000" android:endColor="@color/transparent" /> @@ -36,10 +36,10 @@ </shape> </item> <item - android:top="65dp" - android:bottom="65dp" - android:left="50dp" - android:right="50dp" + android:top="85dp" + android:bottom="85dp" + android:left="70dp" + android:right="70dp" android:drawable="@drawable/ic_btn_cancel" /> </layer-list>
\ No newline at end of file diff --git a/app/src/main/res/drawable/cust_button_light_rect.xml b/app/src/main/res/drawable/cust_button_light_rect.xml index dd66c739..9840d7e1 100644 --- a/app/src/main/res/drawable/cust_button_light_rect.xml +++ b/app/src/main/res/drawable/cust_button_light_rect.xml @@ -61,19 +61,6 @@ <corners android:radius="@dimen/stdpadding"/> </shape> </item> - <!-- gradient --> - <item - android:bottom="@dimen/button_bevel" - android:right="1dp" - > - <shape android:shape="rectangle"> - <gradient android:startColor="@color/btn_light_transparent_dark" - android:endColor="@color/white_transparent" - android:angle="90" - /> - <corners android:radius="@dimen/stdpadding"/> - </shape> - </item> </layer-list> </item> </selector>
\ No newline at end of file diff --git a/app/src/main/res/layout-port/f_eip.xml b/app/src/main/res/layout-port/f_eip.xml index 83aabcde..80f42f91 100644 --- a/app/src/main/res/layout-port/f_eip.xml +++ b/app/src/main/res/layout-port/f_eip.xml @@ -79,13 +79,13 @@ android:textAppearance="@android:style/TextAppearance.Large" android:textStyle="bold" android:textSize="34sp" - android:autoSizeMinTextSize="28sp" - android:autoSizeTextType="uniform" + app:autoSizeMinTextSize="28sp" + app:autoSizeTextType="uniform" android:textColor="@color/colorEipFragmentFont" app:layout_constraintDimensionRatio="1:1" tools:text="Connection secure" android:gravity="center" - android:maxLines="1" + android:maxLines="2" /> <androidx.appcompat.widget.AppCompatTextView @@ -95,7 +95,8 @@ app:layout_constraintTop_toBottomOf="@id/main_description" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - android:padding="@dimen/activity_margin" + android:paddingLeft="@dimen/stdpadding" + android:paddingRight="@dimen/stdpadding" android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium" android:textStyle="bold" android:textColor="@color/colorEipFragmentFont" diff --git a/app/src/main/res/layout-sw600dp-port/f_eip.xml b/app/src/main/res/layout-sw600dp-port/f_eip.xml new file mode 100644 index 00000000..93393565 --- /dev/null +++ b/app/src/main/res/layout-sw600dp-port/f_eip.xml @@ -0,0 +1,147 @@ +<?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" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/eipServiceFragment" + > + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_vertical_left" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintGuide_percent="0.3" + /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_horizontal_center" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="horizontal" + app:layout_constraintGuide_percent="0.25" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_vertical_outer_left" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintGuide_percent="0.125" + /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_vertical_outer_right" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintGuide_percent="0.875" + /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_horizontal_bottom" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="horizontal" + app:layout_constraintGuide_percent="0.6" + /> + + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_vertical_right" + android:layout_width="0dp" + android:layout_height="0dp" + android:orientation="vertical" + app:layout_constraintGuide_percent="0.7" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/background" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:srcCompat="@drawable/bg_disconnected" + android:scaleType="fitXY" + /> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/main_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toTopOf="@+id/guideline_horizontal_center" + android:padding="@dimen/activity_margin" + android:layout_marginTop="@dimen/activity_margin" + android:textAppearance="@android:style/TextAppearance.Large" + android:textStyle="bold" + android:textSize="48sp" + app:autoSizeMinTextSize="32sp" + app:autoSizeTextType="uniform" + android:textColor="@color/colorEipFragmentFont" + app:layout_constraintDimensionRatio="1:1" + tools:text="Connection secure" + android:gravity="center" + android:maxLines="1" + /> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/sub_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_constraintTop_toBottomOf="@id/main_description" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:paddingLeft="@dimen/stdpadding" + android:paddingRight="@dimen/stdpadding" + android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium" + android:textStyle="bold" + android:textColor="@color/colorEipFragmentFont" + app:layout_constraintDimensionRatio="1:1" + tools:text="A LONG TEXT WITH SEVERAL THINGS BLABLkk \n kdjfkj \n kjdfkjdf" + android:gravity="center" + android:maxLines="3" + android:ellipsize="end" + /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/state_view" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintBottom_toTopOf="@id/guideline_horizontal_bottom" + app:layout_constraintTop_toTopOf="@id/guideline_horizontal_center" + app:layout_constraintLeft_toLeftOf="@id/guideline_vertical_outer_left" + app:layout_constraintRight_toRightOf="@id/guideline_vertical_outer_right" + app:layout_constraintVertical_bias="1" + app:srcCompat="@drawable/state_disconnected" + /> + <se.leap.bitmaskclient.base.views.MainButton + android:id="@+id/main_button" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_margin="@dimen/stdpadding" + app:layout_constraintTop_toBottomOf="@+id/guideline_horizontal_bottom" + app:layout_constraintBottom_toTopOf="@id/gateway_location_button" + app:layout_constraintDimensionRatio="1:1" + app:layout_constraintEnd_toStartOf="@+id/guideline_vertical_right" + app:layout_constraintStart_toStartOf="@+id/guideline_vertical_left" + /> + + <se.leap.bitmaskclient.base.views.LocationButton + android:id="@+id/gateway_location_button" + android:layout_width="match_parent" + android:layout_height="64dp" + android:layout_marginBottom="@dimen/stdpadding" + android:layout_marginEnd="@dimen/stdpadding" + android:layout_marginStart="@dimen/stdpadding" + android:layout_marginTop="@dimen/stdpadding" + android:layout_marginLeft="@dimen/stdpadding" + android:layout_marginRight="@dimen/stdpadding" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + tools:text="SEATTLE" + android:gravity="center_vertical" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/a_add_provider.xml b/app/src/main/res/layout/a_add_provider.xml index 517c8c19..aad64630 100644 --- a/app/src/main/res/layout/a_add_provider.xml +++ b/app/src/main/res/layout/a_add_provider.xml @@ -70,6 +70,7 @@ android:id="@+id/button_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:textColor="@color/color_font_btn_primary" android:text="@string/cancel" /> <Button @@ -79,6 +80,7 @@ android:layout_marginLeft="@dimen/add_button_margin" android:layout_marginStart="@dimen/add_button_margin" android:enabled="false" + android:textColor="@color/color_font_btn_primary" android:text="@string/save" /> </LinearLayout> diff --git a/app/src/main/res/layout/a_add_provider_tablet_scrollview.xml b/app/src/main/res/layout/a_add_provider_tablet_scrollview.xml index d3b8fc58..74904f36 100644 --- a/app/src/main/res/layout/a_add_provider_tablet_scrollview.xml +++ b/app/src/main/res/layout/a_add_provider_tablet_scrollview.xml @@ -75,6 +75,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:minWidth="80dp" + android:textColor="@color/color_font_btn_primary" android:text="@string/cancel" /> <Button @@ -84,6 +85,7 @@ android:minWidth="80dp" android:layout_marginLeft="@dimen/add_button_margin" android:layout_marginStart="@dimen/add_button_margin" + android:textColor="@color/color_font_btn_primary" android:enabled="false" android:text="@string/save" /> </LinearLayout> diff --git a/app/src/main/res/layout/a_main.xml b/app/src/main/res/layout/a_main.xml index 92e0a3c0..927217f4 100644 --- a/app/src/main/res/layout/a_main.xml +++ b/app/src/main/res/layout/a_main.xml @@ -22,8 +22,6 @@ android:minHeight="?attr/actionBarSize" android:layout_width="match_parent" android:layout_height="wrap_content" - app:titleTextColor="@color/colorActionBarTitleFont" - app:subtitleTextColor="@color/colorActionBarSubtitleFont" android:background="?attr/colorPrimary"> </androidx.appcompat.widget.Toolbar> diff --git a/app/src/main/res/layout/a_provider_credentials.xml b/app/src/main/res/layout/a_provider_credentials.xml index c5ff5f99..033aae16 100644 --- a/app/src/main/res/layout/a_provider_credentials.xml +++ b/app/src/main/res/layout/a_provider_credentials.xml @@ -44,6 +44,7 @@ android:layout_height="wrap_content" android:layout_gravity="end" android:enabled="false" + android:textColor="@color/color_font_btn_primary" android:text="@string/login_button" /> </LinearLayout> diff --git a/app/src/main/res/layout/a_provider_credentials_tablet_linear_layout.xml b/app/src/main/res/layout/a_provider_credentials_tablet_linear_layout.xml index 56222813..73557853 100644 --- a/app/src/main/res/layout/a_provider_credentials_tablet_linear_layout.xml +++ b/app/src/main/res/layout/a_provider_credentials_tablet_linear_layout.xml @@ -50,6 +50,7 @@ android:layout_height="wrap_content" android:layout_gravity="end" android:enabled="false" + android:textColor="@color/color_font_btn_primary" android:text="@string/login_button" /> </LinearLayout> diff --git a/app/src/main/res/layout/d_obfuscation_proxy.xml b/app/src/main/res/layout/d_obfuscation_proxy.xml index 92d51fec..2ce9d7b3 100644 --- a/app/src/main/res/layout/d_obfuscation_proxy.xml +++ b/app/src/main/res/layout/d_obfuscation_proxy.xml @@ -81,6 +81,7 @@ android:layout_height="wrap_content" android:text="Use defaults" android:background="@drawable/cust_button_secondary" + android:textColor="@color/color_font_btn_secondary" android:layout_marginHorizontal="@dimen/stdpadding" /> <androidx.appcompat.widget.LinearLayoutCompat @@ -93,6 +94,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/stdpadding" + android:textColor="@color/color_font_btn_primary" android:text="@string/cancel" /> @@ -101,6 +103,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/stdpadding" + android:textColor="@color/color_font_btn_primary" android:text="@string/save" /> </androidx.appcompat.widget.LinearLayoutCompat> diff --git a/app/src/main/res/layout/donation_reminder_dialog.xml b/app/src/main/res/layout/donation_reminder_dialog.xml index 0a93c867..17eaf009 100644 --- a/app/src/main/res/layout/donation_reminder_dialog.xml +++ b/app/src/main/res/layout/donation_reminder_dialog.xml @@ -50,7 +50,7 @@ android:layout_marginTop="@dimen/add_button_margin" android:background="@drawable/cust_button_primary" android:text="@string/donate_button_donate" - android:textColor="@color/white" + android:textColor="@color/color_font_btn_primary" android:textStyle="bold" /> <Button @@ -63,7 +63,7 @@ android:layout_marginTop="@dimen/standard_margin" android:background="@drawable/cust_button_secondary" android:text="@string/donate_button_remind_later" - android:textColor="@android:color/tab_indicator_text" + android:textColor="@color/color_font_btn_secondary" android:textStyle="bold" /> </LinearLayout> diff --git a/app/src/main/res/layout/v_actionbar_title.xml b/app/src/main/res/layout/v_actionbar_title.xml new file mode 100644 index 00000000..1985ef21 --- /dev/null +++ b/app/src/main/res/layout/v_actionbar_title.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> + +<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/action_bar_title_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="vertical"> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/action_bar_title" + android:layout_width="wrap_content" + tools:text="Bitmask" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:textStyle="normal" + android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" + /> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/action_bar_subtitle" + android:layout_width="wrap_content" + tools:text="Advanced Settings" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" + android:textColor="@color/colorActionBarSubtitleFont" + /> + +</androidx.appcompat.widget.LinearLayoutCompat> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 35e49370..ead4785e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -10,6 +10,7 @@ <color name="colorMainBtnHighlight">#03DAC6</color> <color name="colorMainBtnError">#eF2222</color> + <color name="black">#000000</color> <color name="black800_dark">#1b1b1b</color> <color name="black800">#424242</color> <color name="black800_secondary">#3b3b3b</color> @@ -39,9 +40,12 @@ <color name="black_high_transparent">#05000000</color> <color name="colorEipFragmentFont">@color/black800</color> - <color name="colorFontBtn">@color/black800</color> - <color name="colorFontBtnEnabled">@color/white</color> - <color name="colorLocationButtonTint">@color/black800</color> + <!-- button text colors in Alerts etc. --> + <color name="color_font_btn">@color/black800</color> + <!-- pill style button text colors --> + <color name="color_font_btn_primary">@color/black800</color> + <color name="color_font_btn_secondary">@color/black800</color> + <color name="colorLocationButtonTint">@color/black</color> <color name="colorLocationButtonTintTransparent">@color/black800_high_transparent</color> <color name="colorWarning">#B33A3A</color> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9b05d3fe..f42be3c1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -65,7 +65,7 @@ <item name="android:background">@drawable/cust_button_primary</item> <item name="android:height">36dp</item> <item name="android:minWidth">75dp</item> - <item name="android:textColor">@color/colorFontBtn</item> + <item name="android:textColor">@color/color_font_btn</item> </style> <style name="BitmaskActivity"> |