From 138fac0a70c62d99586a0454cac8944a20ca29cf Mon Sep 17 00:00:00 2001 From: cyberta Date: Wed, 23 Nov 2022 10:14:13 +0100 Subject: move EipFragment to normal and custom flavor for now --- .../bitmaskclient/base/fragments/EipFragment.java | 684 -------------------- .../EipFragment.java | 686 +++++++++++++++++++++ 2 files changed, 686 insertions(+), 684 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java create mode 100644 app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java 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 deleted file mode 100644 index a95a14ef..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ /dev/null @@ -1,684 +0,0 @@ -/** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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; -import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; -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.ConfigHelper.isDefaultBitmask; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; -import static se.leap.bitmaskclient.base.utils.ViewHelper.convertDimensionToPx; -import static se.leap.bitmaskclient.eip.EipSetupObserver.gatewayOrder; -import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; -import static se.leap.bitmaskclient.eip.GatewaysManager.Load.UNKNOWN; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; -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.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Vibrator; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.TextUtils; -import android.text.style.RelativeSizeSpan; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.AppCompatImageView; -import androidx.appcompat.widget.AppCompatTextView; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; - -import java.util.Observable; -import java.util.Observer; -import java.util.concurrent.atomic.AtomicBoolean; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Unbinder; -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.BuildConfig; -import se.leap.bitmaskclient.R; -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.PreferenceHelper; -import se.leap.bitmaskclient.base.views.LocationButton; -import se.leap.bitmaskclient.base.views.MainButton; -import se.leap.bitmaskclient.eip.EipCommand; -import se.leap.bitmaskclient.eip.EipStatus; -import se.leap.bitmaskclient.eip.GatewaysManager; -import se.leap.bitmaskclient.providersetup.ProviderAPICommand; -import se.leap.bitmaskclient.providersetup.ProviderListActivity; -import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; -import se.leap.bitmaskclient.providersetup.activities.LoginActivity; -import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; -import se.leap.bitmaskclient.tor.TorServiceCommand; -import se.leap.bitmaskclient.tor.TorStatusObservable; - -public class EipFragment extends Fragment implements Observer { - - public final static String TAG = EipFragment.class.getSimpleName(); - - - private SharedPreferences preferences; - private Provider provider; - - @BindView(R.id.background) - AppCompatImageView background; - - @BindView(R.id.main_button) - MainButton mainButton; - - @BindView(R.id.gateway_location_button) - LocationButton locationButton; - - @BindView(R.id.main_description) - AppCompatTextView mainDescription; - - @BindView(R.id.sub_description) - AppCompatTextView subDescription; - - private Unbinder unbinder; - private EipStatus eipStatus; - private ProviderObservable providerObservable; - private TorStatusObservable torStatusObservable; - - private GatewaysManager gatewaysManager; - - //---saved Instance ------- - private final String KEY_SHOW_PENDING_START_CANCELLATION = "KEY_SHOW_PENDING_START_CANCELLATION"; - private final String KEY_SHOW_ASK_TO_STOP_EIP = "KEY_SHOW_ASK_TO_STOP_EIP"; - private boolean showPendingStartCancellation = false; - private boolean showAskToStopEip = false; - //------------------------ - 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); - Bundle arguments = getArguments(); - Activity activity = getActivity(); - if (activity != null) { - if (arguments != null) { - provider = arguments.getParcelable(PROVIDER_KEY); - if (provider == null) { - handleNoProvider(activity); - } else { - Log.d(TAG, provider.getName() + " configured as provider"); - } - } else { - handleNoProvider(activity); - } - } - } - - private void handleNoProvider(Activity activity) { - if (isDefaultBitmask()) { - activity.startActivityForResult(new Intent(activity, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); - } else { - Log.e(TAG, "no provider given - try to reconfigure custom provider"); - startActivityForResult(new Intent(activity, CustomProviderSetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); - - } - - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - openVpnConnection = new EipFragmentServiceConnection(); - eipStatus = EipStatus.getInstance(); - providerObservable = ProviderObservable.getInstance(); - torStatusObservable = TorStatusObservable.getInstance(); - Activity activity = getActivity(); - if (activity != null) { - preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); - } else { - Log.e(TAG, "activity is null in onCreate - no preferences set!"); - } - - gatewaysManager = new GatewaysManager(getContext()); - - - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - eipStatus.addObserver(this); - torStatusObservable.addObserver(this); - providerObservable.addObserver(this); - View view = inflater.inflate(R.layout.f_eip, container, false); - unbinder = ButterKnife.bind(this, view); - - try { - Bundle arguments = getArguments(); - if (arguments != null && arguments.containsKey(ASK_TO_CANCEL_VPN) && arguments.getBoolean(ASK_TO_CANCEL_VPN)) { - arguments.remove(ASK_TO_CANCEL_VPN); - setArguments(arguments); - askToStopEIP(); - } - } catch (IllegalStateException e) { - // probably setArguments failed because the fragments state is already saved - e.printStackTrace(); - } - - restoreFromSavedInstance(savedInstanceState); - locationButton.setOnClickListener(v -> { - FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); - Fragment fragment = new GatewaySelectionFragment(); - fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); - }); - return view; - } - - @Override - public void onStart() { - super.onStart(); - if (DonationReminderDialog.isCallable(getContext())) { - showDonationReminderDialog(); - } - } - - @Override - public void onResume() { - super.onResume(); - if (!eipStatus.isDisconnected()) { - openVpnConnection.bindService(); - } - handleNewState(); - } - - @Override - public void onPause() { - super.onPause(); - openVpnConnection.unbindService(); - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (showAskToStopEip) { - outState.putBoolean(KEY_SHOW_ASK_TO_STOP_EIP, true); - alertDialog.dismiss(); - } else if (showPendingStartCancellation) { - outState.putBoolean(KEY_SHOW_PENDING_START_CANCELLATION, true); - alertDialog.dismiss(); - } - } - - private void restoreFromSavedInstance(Bundle savedInstanceState) { - if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_PENDING_START_CANCELLATION)) { - showPendingStartCancellation = true; - askPendingStartCancellation(); - } else if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_ASK_TO_STOP_EIP)) { - showAskToStopEip = true; - askToStopEIP(); - } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - eipStatus.deleteObserver(this); - providerObservable.deleteObserver(this); - torStatusObservable.deleteObserver(this); - unbinder.unbind(); - } - - private void saveStatus(boolean restartOnBoot) { - preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, restartOnBoot).apply(); - } - - @OnClick(R.id.main_button) - void onButtonClick() { - handleIcon(); - } - - void handleIcon() { - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) - handleSwitchOff(); - else - handleSwitchOn(); - } - - private void handleSwitchOn() { - Context context = getContext(); - if (context == null) { - Log.e(TAG, "context is null when switch turning on"); - return; - } - - if (canStartEIP()) { - startEipFromScratch(); - } else if (canLogInToStartEIP()) { - askUserToLogIn(getString(vpn_certificate_user_message)); - } else { - // provider has no VpnCertificate but user is logged in - updateInvalidVpnCertificate(); - } - } - - private boolean canStartEIP() { - boolean certificateExists = provider.hasVpnCertificate(); - boolean isAllowedAnon = provider.allowsAnonymous(); - return (isAllowedAnon || certificateExists) && !eipStatus.isConnected() && !eipStatus.isConnecting(); - } - - private boolean canLogInToStartEIP() { - boolean isAllowedRegistered = provider.allowsRegistered(); - boolean isLoggedIn = LeapSRPSession.loggedIn(); - return isAllowedRegistered && !isLoggedIn && !eipStatus.isConnecting() && !eipStatus.isConnected(); - } - - private void handleSwitchOff() { - if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) { - askPendingStartCancellation(); - } else if (eipStatus.isConnected()) { - askToStopEIP(); - } - } - - private void setMainButtonEnabled(boolean enabled) { - locationButton.setEnabled(enabled); - mainButton.setEnabled(enabled); - } - - public void startEipFromScratch() { - saveStatus(true); - Context context = getContext(); - if (context == null) { - Log.e(TAG, "context is null when trying to start VPN"); - return; - } - if (!provider.getGeoipUrl().isDefault() && provider.shouldUpdateGeoIpJson()) { - Bundle bundle = new Bundle(); - bundle.putBoolean(EIP_ACTION_START, true); - bundle.putBoolean(EIP_EARLY_ROUTES, false); - ProviderAPICommand.execute(context, DOWNLOAD_GEOIP_JSON, bundle, provider); - } else { - EipCommand.startVPN(context, false); - } - EipStatus.getInstance().updateState("UI_CONNECTING", "", 0, ConnectionStatus.LEVEL_START); - } - - protected void stopEipIfPossible() { - Context context = getContext(); - if (context == null) { - Log.e(TAG, "context is null when trying to stop EIP"); - return; - } - EipCommand.stopVPN(context); - } - - private void askPendingStartCancellation() { - Activity activity = getActivity(); - if (activity == null) { - Log.e(TAG, "activity is null when asking to cancel"); - return; - } - - try { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); - showPendingStartCancellation = true; - alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) - .setMessage(activity.getString(R.string.eip_cancel_connect_text)) - .setPositiveButton((android.R.string.yes), (dialog, which) -> { - Context context = getContext(); - if (context != null && eipStatus.isUpdatingVpnCert() && - TorStatusObservable.isRunning()) { - TorServiceCommand.stopTorServiceAsync(context.getApplicationContext()); - } - stopEipIfPossible(); - }) - .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { - }).setOnDismissListener(dialog -> showPendingStartCancellation = false).show(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } - - } - - protected void askToStopEIP() { - Activity activity = getActivity(); - if (activity == null) { - Log.e(TAG, "activity is null when asking to stop EIP"); - return; - } - try { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity); - showAskToStopEip = true; - alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) - .setMessage(activity.getString(R.string.eip_warning_browser_inconsistency)) - .setPositiveButton((android.R.string.yes), (dialog, which) -> stopEipIfPossible()) - .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { - }).setOnDismissListener(dialog -> showAskToStopEip = false).show(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } - - } - - @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - 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()) { - handleNewStateOnMain(); - } - } - - private void handleNewStateOnMain() { - Activity activity = getActivity(); - if (activity != null) { - activity.runOnUiThread(this::handleNewState); - } else { - Log.e("EipFragment", "activity is null"); - } - } - - private void handleNewState() { - Activity activity = getActivity(); - if (activity == null) { - Log.e(TAG, "activity is null while trying to handle new state"); - return; - } - - Log.d(TAG, "eip fragment eipStatus state: " + eipStatus.getState() + " - level: " + eipStatus.getLevel() + " - is reconnecting: " + eipStatus.isReconnecting()); - if (eipStatus.isUpdatingVpnCert()) { - setMainButtonEnabled(true); - showConnectionTransitionLayout(true); - locationButton.setText(getString(R.string.eip_status_start_pending)); - locationButton.setLocationLoad(UNKNOWN); - locationButton.showBridgeIndicator(false); - locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); - String torStatus = TorStatusObservable.getStringForCurrentStatus(getContext()); - if (!TextUtils.isEmpty(torStatus)) { - Spannable spannable = new SpannableString(torStatus); - spannable.setSpan(new RelativeSizeSpan(0.75f), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - subDescription.setText(TextUtils.concat(getString(R.string.updating_certificate_message) + "\n", spannable)); - } else { - subDescription.setText(getString(R.string.updating_certificate_message)); - } - } else if (eipStatus.isConnecting()) { - setMainButtonEnabled(true); - showConnectionTransitionLayout(true); - locationButton.setText(getString(R.string.eip_status_start_pending)); - locationButton.setLocationLoad(UNKNOWN); - locationButton.showBridgeIndicator(false); - locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); - subDescription.setText(null); - } else if (eipStatus.isConnected()) { - setMainButtonEnabled(true); - mainButton.updateState(true, false, 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()); - locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); - locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); - mainDescription.setText(R.string.eip_state_connected); - subDescription.setText(null); - colorBackground(); - } else if(isOpenVpnRunningWithoutNetwork()) { - Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); - setMainButtonEnabled(true); - mainButton.updateState(true, false, true); - locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); - locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); - locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); - locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); - colorBackgroundALittle(); - mainDescription.setText(R.string.eip_state_connected); - subDescription.setText(R.string.eip_state_no_network); - } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { - showConnectionTransitionLayout(true); - // showRetryToast(activity); - locationButton.setText(getString(R.string.eip_status_start_pending)); - locationButton.setLocationLoad(UNKNOWN); - locationButton.showBridgeIndicator(false); - locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); - subDescription.setText(R.string.reconnecting); - } else if (eipStatus.isDisconnecting()) { - setMainButtonEnabled(false); - showConnectionTransitionLayout(false); - mainDescription.setText(R.string.eip_state_insecure); - } else if (eipStatus.isBlocking()) { - setMainButtonEnabled(true); - mainButton.updateState(true, false, true); - colorBackgroundALittle(); - locationButton.setText(getString(R.string.no_location)); - locationButton.setLocationLoad(UNKNOWN); - locationButton.showBridgeIndicator(false); - locationButton.showRecommendedIndicator(false); - mainDescription.setText(R.string.eip_state_connected); - subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); - } else { - locationButton.setText(activity.getString(R.string.vpn_button_turn_on)); - setMainButtonEnabled(true); - mainButton.updateState(false, false, false); - greyscaleBackground(); - locationButton.setLocationLoad(UNKNOWN); - locationButton.showBridgeIndicator(false); - String city = getPreferredCity(getContext()); - locationButton.setText(city == null ? getString(R.string.gateway_selection_recommended_location) : city); - locationButton.showRecommendedIndicator(false); - mainDescription.setText(R.string.eip_state_insecure); - subDescription.setText(R.string.connection_not_connected); - } - } - - private void showToast(Activity activity, String message, boolean vibrateLong) { - LayoutInflater inflater = getLayoutInflater(); - View layout = inflater.inflate(R.layout.custom_toast, - activity.findViewById(R.id.custom_toast_container)); - - AppCompatTextView text = layout.findViewById(R.id.text); - text.setText(message); - - Vibrator v = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); - if (vibrateLong) { - v.vibrate(100); - v.vibrate(200); - } else { - v.vibrate(100); - } - - Toast toast = new Toast(activity.getApplicationContext()); - toast.setGravity(Gravity.BOTTOM, 0, convertDimensionToPx(this.getContext(), R.dimen.stdpadding)); - toast.setDuration(Toast.LENGTH_LONG); - toast.setView(layout); - toast.show(); - } - - private void showRetryToast(Activity activity) { - int nClosestGateway = gatewayOrder(); - String message = String.format("Server number " + nClosestGateway + " not reachable. Trying next gateway."); - showToast(activity, message, true ); - } - - private void showConnectionTransitionLayout(boolean isConnecting) { - mainButton.updateState(true, isConnecting, false); - if (isConnecting) { - colorBackgroundALittle(); - } else { - greyscaleBackground(); - } - } - - 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 greyscaleBackground() { - if (BuildConfig.use_color_filter) { - ColorMatrix matrix = new ColorMatrix(); - matrix.setSaturation(0); - ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); - background.setColorFilter(cf); - background.setImageAlpha(255); - } - } - - private void colorBackgroundALittle() { - if (BuildConfig.use_color_filter) { - background.setColorFilter(null); - background.setImageAlpha(144); - } - } - - private void colorBackground() { - if (BuildConfig.use_color_filter) { - background.setColorFilter(null); - background.setImageAlpha(210); - } - } - - private void updateInvalidVpnCertificate() { - eipStatus.setUpdatingVpnCert(true); - ProviderAPICommand.execute(getContext(), UPDATE_INVALID_VPN_CERTIFICATE, provider); - } - - private void askUserToLogIn(String userMessage) { - Intent intent = new Intent(getContext(), LoginActivity.class); - intent.putExtra(PROVIDER_KEY, provider); - - if(userMessage != null) { - intent.putExtra(USER_MESSAGE, userMessage); - } - - Activity activity = getActivity(); - if (activity != null) { - activity.startActivityForResult(intent, REQUEST_CODE_LOG_IN); - } - } - - 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( - getActivity().getSupportFragmentManager()).removePreviousFragment( - DonationReminderDialog.TAG); - DialogFragment newFragment = new DonationReminderDialog(); - newFragment.setCancelable(false); - newFragment.show(fragmentTransaction, DonationReminderDialog.TAG); - } catch (IllegalStateException | NullPointerException e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java new file mode 100644 index 00000000..2588f436 --- /dev/null +++ b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java @@ -0,0 +1,686 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +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; +import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; +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.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; +import static se.leap.bitmaskclient.base.utils.ViewHelper.convertDimensionToPx; +import static se.leap.bitmaskclient.eip.EipSetupObserver.gatewayOrder; +import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; +import static se.leap.bitmaskclient.eip.GatewaysManager.Load.UNKNOWN; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; +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.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Vibrator; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.RelativeSizeSpan; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import java.util.Observable; +import java.util.Observer; +import java.util.concurrent.atomic.AtomicBoolean; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.Unbinder; +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.BuildConfig; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.FragmentManagerEnhanced; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.fragments.DonationReminderDialog; +import se.leap.bitmaskclient.base.fragments.GatewaySelectionFragment; +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.views.LocationButton; +import se.leap.bitmaskclient.base.views.MainButton; +import se.leap.bitmaskclient.eip.EipCommand; +import se.leap.bitmaskclient.eip.EipStatus; +import se.leap.bitmaskclient.eip.GatewaysManager; +import se.leap.bitmaskclient.providersetup.ProviderAPICommand; +import se.leap.bitmaskclient.providersetup.ProviderListActivity; +import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; +import se.leap.bitmaskclient.providersetup.activities.LoginActivity; +import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; +import se.leap.bitmaskclient.tor.TorServiceCommand; +import se.leap.bitmaskclient.tor.TorStatusObservable; + +public class EipFragment extends Fragment implements Observer { + + public final static String TAG = EipFragment.class.getSimpleName(); + + + private SharedPreferences preferences; + private Provider provider; + + @BindView(R.id.background) + AppCompatImageView background; + + @BindView(R.id.main_button) + MainButton mainButton; + + @BindView(R.id.gateway_location_button) + LocationButton locationButton; + + @BindView(R.id.main_description) + AppCompatTextView mainDescription; + + @BindView(R.id.sub_description) + AppCompatTextView subDescription; + + private Unbinder unbinder; + private EipStatus eipStatus; + private ProviderObservable providerObservable; + private TorStatusObservable torStatusObservable; + + private GatewaysManager gatewaysManager; + + //---saved Instance ------- + private final String KEY_SHOW_PENDING_START_CANCELLATION = "KEY_SHOW_PENDING_START_CANCELLATION"; + private final String KEY_SHOW_ASK_TO_STOP_EIP = "KEY_SHOW_ASK_TO_STOP_EIP"; + private boolean showPendingStartCancellation = false; + private boolean showAskToStopEip = false; + //------------------------ + 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); + Bundle arguments = getArguments(); + Activity activity = getActivity(); + if (activity != null) { + if (arguments != null) { + provider = arguments.getParcelable(PROVIDER_KEY); + if (provider == null) { + handleNoProvider(activity); + } else { + Log.d(TAG, provider.getName() + " configured as provider"); + } + } else { + handleNoProvider(activity); + } + } + } + + private void handleNoProvider(Activity activity) { + if (isDefaultBitmask()) { + activity.startActivityForResult(new Intent(activity, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); + } else { + Log.e(TAG, "no provider given - try to reconfigure custom provider"); + startActivityForResult(new Intent(activity, CustomProviderSetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); + + } + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + openVpnConnection = new EipFragmentServiceConnection(); + eipStatus = EipStatus.getInstance(); + providerObservable = ProviderObservable.getInstance(); + torStatusObservable = TorStatusObservable.getInstance(); + Activity activity = getActivity(); + if (activity != null) { + preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + } else { + Log.e(TAG, "activity is null in onCreate - no preferences set!"); + } + + gatewaysManager = new GatewaysManager(getContext()); + + + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + eipStatus.addObserver(this); + torStatusObservable.addObserver(this); + providerObservable.addObserver(this); + View view = inflater.inflate(R.layout.f_eip, container, false); + unbinder = ButterKnife.bind(this, view); + + try { + Bundle arguments = getArguments(); + if (arguments != null && arguments.containsKey(ASK_TO_CANCEL_VPN) && arguments.getBoolean(ASK_TO_CANCEL_VPN)) { + arguments.remove(ASK_TO_CANCEL_VPN); + setArguments(arguments); + askToStopEIP(); + } + } catch (IllegalStateException e) { + // probably setArguments failed because the fragments state is already saved + e.printStackTrace(); + } + + restoreFromSavedInstance(savedInstanceState); + locationButton.setOnClickListener(v -> { + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + Fragment fragment = new GatewaySelectionFragment(); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + return view; + } + + @Override + public void onStart() { + super.onStart(); + if (DonationReminderDialog.isCallable(getContext())) { + showDonationReminderDialog(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (!eipStatus.isDisconnected()) { + openVpnConnection.bindService(); + } + handleNewState(); + } + + @Override + public void onPause() { + super.onPause(); + openVpnConnection.unbindService(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (showAskToStopEip) { + outState.putBoolean(KEY_SHOW_ASK_TO_STOP_EIP, true); + alertDialog.dismiss(); + } else if (showPendingStartCancellation) { + outState.putBoolean(KEY_SHOW_PENDING_START_CANCELLATION, true); + alertDialog.dismiss(); + } + } + + private void restoreFromSavedInstance(Bundle savedInstanceState) { + if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_PENDING_START_CANCELLATION)) { + showPendingStartCancellation = true; + askPendingStartCancellation(); + } else if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_ASK_TO_STOP_EIP)) { + showAskToStopEip = true; + askToStopEIP(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + eipStatus.deleteObserver(this); + providerObservable.deleteObserver(this); + torStatusObservable.deleteObserver(this); + unbinder.unbind(); + } + + private void saveStatus(boolean restartOnBoot) { + preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, restartOnBoot).apply(); + } + + @OnClick(R.id.main_button) + void onButtonClick() { + handleIcon(); + } + + void handleIcon() { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) + handleSwitchOff(); + else + handleSwitchOn(); + } + + private void handleSwitchOn() { + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when switch turning on"); + return; + } + + if (canStartEIP()) { + startEipFromScratch(); + } else if (canLogInToStartEIP()) { + askUserToLogIn(getString(vpn_certificate_user_message)); + } else { + // provider has no VpnCertificate but user is logged in + updateInvalidVpnCertificate(); + } + } + + private boolean canStartEIP() { + boolean certificateExists = provider.hasVpnCertificate(); + boolean isAllowedAnon = provider.allowsAnonymous(); + return (isAllowedAnon || certificateExists) && !eipStatus.isConnected() && !eipStatus.isConnecting(); + } + + private boolean canLogInToStartEIP() { + boolean isAllowedRegistered = provider.allowsRegistered(); + boolean isLoggedIn = LeapSRPSession.loggedIn(); + return isAllowedRegistered && !isLoggedIn && !eipStatus.isConnecting() && !eipStatus.isConnected(); + } + + private void handleSwitchOff() { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) { + askPendingStartCancellation(); + } else if (eipStatus.isConnected()) { + askToStopEIP(); + } + } + + private void setMainButtonEnabled(boolean enabled) { + locationButton.setEnabled(enabled); + mainButton.setEnabled(enabled); + } + + public void startEipFromScratch() { + saveStatus(true); + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when trying to start VPN"); + return; + } + if (!provider.getGeoipUrl().isDefault() && provider.shouldUpdateGeoIpJson()) { + Bundle bundle = new Bundle(); + bundle.putBoolean(EIP_ACTION_START, true); + bundle.putBoolean(EIP_EARLY_ROUTES, false); + ProviderAPICommand.execute(context, DOWNLOAD_GEOIP_JSON, bundle, provider); + } else { + EipCommand.startVPN(context, false); + } + EipStatus.getInstance().updateState("UI_CONNECTING", "", 0, ConnectionStatus.LEVEL_START); + } + + protected void stopEipIfPossible() { + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when trying to stop EIP"); + return; + } + EipCommand.stopVPN(context); + } + + private void askPendingStartCancellation() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null when asking to cancel"); + return; + } + + try { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); + showPendingStartCancellation = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) + .setMessage(activity.getString(R.string.eip_cancel_connect_text)) + .setPositiveButton((android.R.string.yes), (dialog, which) -> { + Context context = getContext(); + if (context != null && eipStatus.isUpdatingVpnCert() && + TorStatusObservable.isRunning()) { + TorServiceCommand.stopTorServiceAsync(context.getApplicationContext()); + } + stopEipIfPossible(); + }) + .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { + }).setOnDismissListener(dialog -> showPendingStartCancellation = false).show(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + + } + + protected void askToStopEIP() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null when asking to stop EIP"); + return; + } + try { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity); + showAskToStopEip = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) + .setMessage(activity.getString(R.string.eip_warning_browser_inconsistency)) + .setPositiveButton((android.R.string.yes), (dialog, which) -> stopEipIfPossible()) + .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { + }).setOnDismissListener(dialog -> showAskToStopEip = false).show(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + + } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + 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()) { + handleNewStateOnMain(); + } + } + + private void handleNewStateOnMain() { + Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(this::handleNewState); + } else { + Log.e("EipFragment", "activity is null"); + } + } + + private void handleNewState() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null while trying to handle new state"); + return; + } + + Log.d(TAG, "eip fragment eipStatus state: " + eipStatus.getState() + " - level: " + eipStatus.getLevel() + " - is reconnecting: " + eipStatus.isReconnecting()); + if (eipStatus.isUpdatingVpnCert()) { + setMainButtonEnabled(true); + showConnectionTransitionLayout(true); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + String torStatus = TorStatusObservable.getStringForCurrentStatus(getContext()); + if (!TextUtils.isEmpty(torStatus)) { + Spannable spannable = new SpannableString(torStatus); + spannable.setSpan(new RelativeSizeSpan(0.75f), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + subDescription.setText(TextUtils.concat(getString(R.string.updating_certificate_message) + "\n", spannable)); + } else { + subDescription.setText(getString(R.string.updating_certificate_message)); + } + } else if (eipStatus.isConnecting()) { + setMainButtonEnabled(true); + showConnectionTransitionLayout(true); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + subDescription.setText(null); + } else if (eipStatus.isConnected()) { + setMainButtonEnabled(true); + mainButton.updateState(true, false, 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()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(null); + colorBackground(); + } else if(isOpenVpnRunningWithoutNetwork()) { + Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); + setMainButtonEnabled(true); + mainButton.updateState(true, false, true); + locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); + colorBackgroundALittle(); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(R.string.eip_state_no_network); + } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { + showConnectionTransitionLayout(true); + // showRetryToast(activity); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + subDescription.setText(R.string.reconnecting); + } else if (eipStatus.isDisconnecting()) { + setMainButtonEnabled(false); + showConnectionTransitionLayout(false); + mainDescription.setText(R.string.eip_state_insecure); + } else if (eipStatus.isBlocking()) { + setMainButtonEnabled(true); + mainButton.updateState(true, false, true); + colorBackgroundALittle(); + locationButton.setText(getString(R.string.no_location)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); + } else { + locationButton.setText(activity.getString(R.string.vpn_button_turn_on)); + setMainButtonEnabled(true); + mainButton.updateState(false, false, false); + greyscaleBackground(); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + String city = getPreferredCity(getContext()); + locationButton.setText(city == null ? getString(R.string.gateway_selection_recommended_location) : city); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(R.string.eip_state_insecure); + subDescription.setText(R.string.connection_not_connected); + } + } + + private void showToast(Activity activity, String message, boolean vibrateLong) { + LayoutInflater inflater = getLayoutInflater(); + View layout = inflater.inflate(R.layout.custom_toast, + activity.findViewById(R.id.custom_toast_container)); + + AppCompatTextView text = layout.findViewById(R.id.text); + text.setText(message); + + Vibrator v = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrateLong) { + v.vibrate(100); + v.vibrate(200); + } else { + v.vibrate(100); + } + + Toast toast = new Toast(activity.getApplicationContext()); + toast.setGravity(Gravity.BOTTOM, 0, convertDimensionToPx(this.getContext(), R.dimen.stdpadding)); + toast.setDuration(Toast.LENGTH_LONG); + toast.setView(layout); + toast.show(); + } + + private void showRetryToast(Activity activity) { + int nClosestGateway = gatewayOrder(); + String message = String.format("Server number " + nClosestGateway + " not reachable. Trying next gateway."); + showToast(activity, message, true ); + } + + private void showConnectionTransitionLayout(boolean isConnecting) { + mainButton.updateState(true, isConnecting, false); + if (isConnecting) { + colorBackgroundALittle(); + } else { + greyscaleBackground(); + } + } + + 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 greyscaleBackground() { + if (BuildConfig.use_color_filter) { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0); + ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); + background.setColorFilter(cf); + background.setImageAlpha(255); + } + } + + private void colorBackgroundALittle() { + if (BuildConfig.use_color_filter) { + background.setColorFilter(null); + background.setImageAlpha(144); + } + } + + private void colorBackground() { + if (BuildConfig.use_color_filter) { + background.setColorFilter(null); + background.setImageAlpha(210); + } + } + + private void updateInvalidVpnCertificate() { + eipStatus.setUpdatingVpnCert(true); + ProviderAPICommand.execute(getContext(), UPDATE_INVALID_VPN_CERTIFICATE, provider); + } + + private void askUserToLogIn(String userMessage) { + Intent intent = new Intent(getContext(), LoginActivity.class); + intent.putExtra(PROVIDER_KEY, provider); + + if(userMessage != null) { + intent.putExtra(USER_MESSAGE, userMessage); + } + + Activity activity = getActivity(); + if (activity != null) { + activity.startActivityForResult(intent, REQUEST_CODE_LOG_IN); + } + } + + 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( + getActivity().getSupportFragmentManager()).removePreviousFragment( + DonationReminderDialog.TAG); + DialogFragment newFragment = new DonationReminderDialog(); + newFragment.setCancelable(false); + newFragment.show(fragmentTransaction, DonationReminderDialog.TAG); + } catch (IllegalStateException | NullPointerException e) { + e.printStackTrace(); + } + } +} -- cgit v1.2.3 From 86619a6ebb4508cd75584f12db69b2c1ed22ef2d Mon Sep 17 00:00:00 2001 From: cyberta Date: Wed, 23 Nov 2022 11:38:34 +0100 Subject: split eip fragment xml per normal/custom flavor --- app/src/custom/res/layout-port/f_eip.xml | 113 ++++++++++++++++++ app/src/custom/res/layout-xlarge-port/f_eip.xml | 122 ++++++++++++++++++++ app/src/custom/res/layout-xlarge/f_eip.xml | 127 +++++++++++++++++++++ app/src/custom/res/layout/f_eip.xml | 146 ++++++++++++++++++++++++ app/src/main/res/layout-port/f_eip.xml | 113 ------------------ app/src/main/res/layout-xlarge-port/f_eip.xml | 122 -------------------- app/src/main/res/layout-xlarge/f_eip.xml | 127 --------------------- app/src/main/res/layout/f_eip.xml | 146 ------------------------ app/src/main/res/layout/f_test_layout.xml | 8 ++ app/src/normal/res/layout-port/f_eip.xml | 113 ++++++++++++++++++ app/src/normal/res/layout-xlarge-port/f_eip.xml | 122 ++++++++++++++++++++ app/src/normal/res/layout-xlarge/f_eip.xml | 127 +++++++++++++++++++++ app/src/normal/res/layout/f_eip.xml | 146 ++++++++++++++++++++++++ 13 files changed, 1024 insertions(+), 508 deletions(-) create mode 100644 app/src/custom/res/layout-port/f_eip.xml create mode 100644 app/src/custom/res/layout-xlarge-port/f_eip.xml create mode 100644 app/src/custom/res/layout-xlarge/f_eip.xml create mode 100644 app/src/custom/res/layout/f_eip.xml delete mode 100644 app/src/main/res/layout-port/f_eip.xml delete mode 100644 app/src/main/res/layout-xlarge-port/f_eip.xml delete mode 100644 app/src/main/res/layout-xlarge/f_eip.xml delete mode 100644 app/src/main/res/layout/f_eip.xml create mode 100644 app/src/main/res/layout/f_test_layout.xml create mode 100644 app/src/normal/res/layout-port/f_eip.xml create mode 100644 app/src/normal/res/layout-xlarge-port/f_eip.xml create mode 100644 app/src/normal/res/layout-xlarge/f_eip.xml create mode 100644 app/src/normal/res/layout/f_eip.xml diff --git a/app/src/custom/res/layout-port/f_eip.xml b/app/src/custom/res/layout-port/f_eip.xml new file mode 100644 index 00000000..cb99a700 --- /dev/null +++ b/app/src/custom/res/layout-port/f_eip.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/custom/res/layout-xlarge-port/f_eip.xml b/app/src/custom/res/layout-xlarge-port/f_eip.xml new file mode 100644 index 00000000..10b7a7e3 --- /dev/null +++ b/app/src/custom/res/layout-xlarge-port/f_eip.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/custom/res/layout-xlarge/f_eip.xml b/app/src/custom/res/layout-xlarge/f_eip.xml new file mode 100644 index 00000000..e6b28c67 --- /dev/null +++ b/app/src/custom/res/layout-xlarge/f_eip.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/custom/res/layout/f_eip.xml b/app/src/custom/res/layout/f_eip.xml new file mode 100644 index 00000000..9a823b65 --- /dev/null +++ b/app/src/custom/res/layout/f_eip.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-port/f_eip.xml b/app/src/main/res/layout-port/f_eip.xml deleted file mode 100644 index cb99a700..00000000 --- a/app/src/main/res/layout-port/f_eip.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-xlarge-port/f_eip.xml b/app/src/main/res/layout-xlarge-port/f_eip.xml deleted file mode 100644 index 10b7a7e3..00000000 --- a/app/src/main/res/layout-xlarge-port/f_eip.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-xlarge/f_eip.xml b/app/src/main/res/layout-xlarge/f_eip.xml deleted file mode 100644 index e6b28c67..00000000 --- a/app/src/main/res/layout-xlarge/f_eip.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/f_eip.xml b/app/src/main/res/layout/f_eip.xml deleted file mode 100644 index 9a823b65..00000000 --- a/app/src/main/res/layout/f_eip.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/f_test_layout.xml b/app/src/main/res/layout/f_test_layout.xml new file mode 100644 index 00000000..6ec91259 --- /dev/null +++ b/app/src/main/res/layout/f_test_layout.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/normal/res/layout-port/f_eip.xml b/app/src/normal/res/layout-port/f_eip.xml new file mode 100644 index 00000000..cb99a700 --- /dev/null +++ b/app/src/normal/res/layout-port/f_eip.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/normal/res/layout-xlarge-port/f_eip.xml b/app/src/normal/res/layout-xlarge-port/f_eip.xml new file mode 100644 index 00000000..10b7a7e3 --- /dev/null +++ b/app/src/normal/res/layout-xlarge-port/f_eip.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/normal/res/layout-xlarge/f_eip.xml b/app/src/normal/res/layout-xlarge/f_eip.xml new file mode 100644 index 00000000..e6b28c67 --- /dev/null +++ b/app/src/normal/res/layout-xlarge/f_eip.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/normal/res/layout/f_eip.xml b/app/src/normal/res/layout/f_eip.xml new file mode 100644 index 00000000..9a823b65 --- /dev/null +++ b/app/src/normal/res/layout/f_eip.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 0cf31d76c9f48cc73446b3fde478a46cd29c7594 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 00:58:36 +0100 Subject: split EipFragment and MainButon into normal and custom flavor, implement new on-off button design for Bitmask --- .../bitmaskclient/base/fragments/EipFragment.java | 686 +++++++++++++++++++++ .../leap/bitmaskclient/base/views/MainButton.java | 124 ++++ .../leap/bitmaskclient/base/views/MainButton.java | 124 ---- .../bitmaskclient/base/views/VpnStateImage.java | 99 --- app/src/main/res/drawable-hdpi/ic_btn_cancel.png | Bin 0 -> 486 bytes app/src/main/res/drawable-hdpi/ic_btn_on.png | Bin 0 -> 1091 bytes app/src/main/res/drawable-xhdpi/ic_btn_cancel.png | Bin 0 -> 617 bytes app/src/main/res/drawable-xhdpi/ic_btn_on.png | Bin 0 -> 1460 bytes app/src/main/res/drawable-xxhdpi/ic_btn_cancel.png | Bin 0 -> 1009 bytes app/src/main/res/drawable-xxhdpi/ic_btn_on.png | Bin 0 -> 2211 bytes .../main/res/drawable-xxxhdpi/ic_btn_cancel.png | Bin 0 -> 1361 bytes app/src/main/res/drawable-xxxhdpi/ic_btn_on.png | Bin 0 -> 3115 bytes app/src/main/res/drawable/button_circle_cancel.xml | 5 + .../res/drawable/button_circle_cancel_pressed.xml | 64 ++ .../res/drawable/button_circle_cancel_released.xml | 62 ++ app/src/main/res/drawable/button_circle_start.xml | 7 + .../res/drawable/button_circle_start_pressed.xml | 47 ++ .../res/drawable/button_circle_start_released.xml | 46 ++ app/src/main/res/drawable/button_circle_stop.xml | 5 + .../res/drawable/button_circle_stop_pressed.xml | 47 ++ .../res/drawable/button_circle_stop_released.xml | 46 ++ app/src/main/res/drawable/ic_btn_cancel.png | Bin 0 -> 338 bytes app/src/main/res/drawable/ic_btn_on.png | Bin 0 -> 777 bytes app/src/main/res/layout/v_main_button.xml | 136 ---- app/src/main/res/values/colors.xml | 7 + .../leap/bitmaskclient/base/views/MainButton.java | 64 ++ app/src/normal/res/drawable/rainbow_circle.xml | 103 ++++ app/src/normal/res/layout/v_main_button.xml | 142 +++++ 28 files changed, 1455 insertions(+), 359 deletions(-) create mode 100644 app/src/custom/java/se/leap/bitmaskclient/base/fragments/EipFragment.java create mode 100644 app/src/custom/java/se/leap/bitmaskclient/base/views/MainButton.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/base/views/VpnStateImage.java create mode 100644 app/src/main/res/drawable-hdpi/ic_btn_cancel.png create mode 100644 app/src/main/res/drawable-hdpi/ic_btn_on.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_btn_cancel.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_btn_on.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_btn_cancel.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_btn_on.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_btn_cancel.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_btn_on.png create mode 100644 app/src/main/res/drawable/button_circle_cancel.xml create mode 100644 app/src/main/res/drawable/button_circle_cancel_pressed.xml create mode 100644 app/src/main/res/drawable/button_circle_cancel_released.xml create mode 100644 app/src/main/res/drawable/button_circle_start.xml create mode 100644 app/src/main/res/drawable/button_circle_start_pressed.xml create mode 100644 app/src/main/res/drawable/button_circle_start_released.xml create mode 100644 app/src/main/res/drawable/button_circle_stop.xml create mode 100644 app/src/main/res/drawable/button_circle_stop_pressed.xml create mode 100644 app/src/main/res/drawable/button_circle_stop_released.xml create mode 100644 app/src/main/res/drawable/ic_btn_cancel.png create mode 100644 app/src/main/res/drawable/ic_btn_on.png delete mode 100644 app/src/main/res/layout/v_main_button.xml create mode 100644 app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java create mode 100644 app/src/normal/res/drawable/rainbow_circle.xml create mode 100644 app/src/normal/res/layout/v_main_button.xml diff --git a/app/src/custom/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/custom/java/se/leap/bitmaskclient/base/fragments/EipFragment.java new file mode 100644 index 00000000..2588f436 --- /dev/null +++ b/app/src/custom/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -0,0 +1,686 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +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; +import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; +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.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; +import static se.leap.bitmaskclient.base.utils.ViewHelper.convertDimensionToPx; +import static se.leap.bitmaskclient.eip.EipSetupObserver.gatewayOrder; +import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; +import static se.leap.bitmaskclient.eip.GatewaysManager.Load.UNKNOWN; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE; +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.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Vibrator; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.RelativeSizeSpan; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.AppCompatTextView; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import java.util.Observable; +import java.util.Observer; +import java.util.concurrent.atomic.AtomicBoolean; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.Unbinder; +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.BuildConfig; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.FragmentManagerEnhanced; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.fragments.DonationReminderDialog; +import se.leap.bitmaskclient.base.fragments.GatewaySelectionFragment; +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.views.LocationButton; +import se.leap.bitmaskclient.base.views.MainButton; +import se.leap.bitmaskclient.eip.EipCommand; +import se.leap.bitmaskclient.eip.EipStatus; +import se.leap.bitmaskclient.eip.GatewaysManager; +import se.leap.bitmaskclient.providersetup.ProviderAPICommand; +import se.leap.bitmaskclient.providersetup.ProviderListActivity; +import se.leap.bitmaskclient.providersetup.activities.CustomProviderSetupActivity; +import se.leap.bitmaskclient.providersetup.activities.LoginActivity; +import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; +import se.leap.bitmaskclient.tor.TorServiceCommand; +import se.leap.bitmaskclient.tor.TorStatusObservable; + +public class EipFragment extends Fragment implements Observer { + + public final static String TAG = EipFragment.class.getSimpleName(); + + + private SharedPreferences preferences; + private Provider provider; + + @BindView(R.id.background) + AppCompatImageView background; + + @BindView(R.id.main_button) + MainButton mainButton; + + @BindView(R.id.gateway_location_button) + LocationButton locationButton; + + @BindView(R.id.main_description) + AppCompatTextView mainDescription; + + @BindView(R.id.sub_description) + AppCompatTextView subDescription; + + private Unbinder unbinder; + private EipStatus eipStatus; + private ProviderObservable providerObservable; + private TorStatusObservable torStatusObservable; + + private GatewaysManager gatewaysManager; + + //---saved Instance ------- + private final String KEY_SHOW_PENDING_START_CANCELLATION = "KEY_SHOW_PENDING_START_CANCELLATION"; + private final String KEY_SHOW_ASK_TO_STOP_EIP = "KEY_SHOW_ASK_TO_STOP_EIP"; + private boolean showPendingStartCancellation = false; + private boolean showAskToStopEip = false; + //------------------------ + 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); + Bundle arguments = getArguments(); + Activity activity = getActivity(); + if (activity != null) { + if (arguments != null) { + provider = arguments.getParcelable(PROVIDER_KEY); + if (provider == null) { + handleNoProvider(activity); + } else { + Log.d(TAG, provider.getName() + " configured as provider"); + } + } else { + handleNoProvider(activity); + } + } + } + + private void handleNoProvider(Activity activity) { + if (isDefaultBitmask()) { + activity.startActivityForResult(new Intent(activity, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); + } else { + Log.e(TAG, "no provider given - try to reconfigure custom provider"); + startActivityForResult(new Intent(activity, CustomProviderSetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); + + } + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + openVpnConnection = new EipFragmentServiceConnection(); + eipStatus = EipStatus.getInstance(); + providerObservable = ProviderObservable.getInstance(); + torStatusObservable = TorStatusObservable.getInstance(); + Activity activity = getActivity(); + if (activity != null) { + preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + } else { + Log.e(TAG, "activity is null in onCreate - no preferences set!"); + } + + gatewaysManager = new GatewaysManager(getContext()); + + + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + eipStatus.addObserver(this); + torStatusObservable.addObserver(this); + providerObservable.addObserver(this); + View view = inflater.inflate(R.layout.f_eip, container, false); + unbinder = ButterKnife.bind(this, view); + + try { + Bundle arguments = getArguments(); + if (arguments != null && arguments.containsKey(ASK_TO_CANCEL_VPN) && arguments.getBoolean(ASK_TO_CANCEL_VPN)) { + arguments.remove(ASK_TO_CANCEL_VPN); + setArguments(arguments); + askToStopEIP(); + } + } catch (IllegalStateException e) { + // probably setArguments failed because the fragments state is already saved + e.printStackTrace(); + } + + restoreFromSavedInstance(savedInstanceState); + locationButton.setOnClickListener(v -> { + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + Fragment fragment = new GatewaySelectionFragment(); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + return view; + } + + @Override + public void onStart() { + super.onStart(); + if (DonationReminderDialog.isCallable(getContext())) { + showDonationReminderDialog(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (!eipStatus.isDisconnected()) { + openVpnConnection.bindService(); + } + handleNewState(); + } + + @Override + public void onPause() { + super.onPause(); + openVpnConnection.unbindService(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (showAskToStopEip) { + outState.putBoolean(KEY_SHOW_ASK_TO_STOP_EIP, true); + alertDialog.dismiss(); + } else if (showPendingStartCancellation) { + outState.putBoolean(KEY_SHOW_PENDING_START_CANCELLATION, true); + alertDialog.dismiss(); + } + } + + private void restoreFromSavedInstance(Bundle savedInstanceState) { + if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_PENDING_START_CANCELLATION)) { + showPendingStartCancellation = true; + askPendingStartCancellation(); + } else if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SHOW_ASK_TO_STOP_EIP)) { + showAskToStopEip = true; + askToStopEIP(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + eipStatus.deleteObserver(this); + providerObservable.deleteObserver(this); + torStatusObservable.deleteObserver(this); + unbinder.unbind(); + } + + private void saveStatus(boolean restartOnBoot) { + preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, restartOnBoot).apply(); + } + + @OnClick(R.id.main_button) + void onButtonClick() { + handleIcon(); + } + + void handleIcon() { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) + handleSwitchOff(); + else + handleSwitchOn(); + } + + private void handleSwitchOn() { + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when switch turning on"); + return; + } + + if (canStartEIP()) { + startEipFromScratch(); + } else if (canLogInToStartEIP()) { + askUserToLogIn(getString(vpn_certificate_user_message)); + } else { + // provider has no VpnCertificate but user is logged in + updateInvalidVpnCertificate(); + } + } + + private boolean canStartEIP() { + boolean certificateExists = provider.hasVpnCertificate(); + boolean isAllowedAnon = provider.allowsAnonymous(); + return (isAllowedAnon || certificateExists) && !eipStatus.isConnected() && !eipStatus.isConnecting(); + } + + private boolean canLogInToStartEIP() { + boolean isAllowedRegistered = provider.allowsRegistered(); + boolean isLoggedIn = LeapSRPSession.loggedIn(); + return isAllowedRegistered && !isLoggedIn && !eipStatus.isConnecting() && !eipStatus.isConnected(); + } + + private void handleSwitchOff() { + if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) { + askPendingStartCancellation(); + } else if (eipStatus.isConnected()) { + askToStopEIP(); + } + } + + private void setMainButtonEnabled(boolean enabled) { + locationButton.setEnabled(enabled); + mainButton.setEnabled(enabled); + } + + public void startEipFromScratch() { + saveStatus(true); + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when trying to start VPN"); + return; + } + if (!provider.getGeoipUrl().isDefault() && provider.shouldUpdateGeoIpJson()) { + Bundle bundle = new Bundle(); + bundle.putBoolean(EIP_ACTION_START, true); + bundle.putBoolean(EIP_EARLY_ROUTES, false); + ProviderAPICommand.execute(context, DOWNLOAD_GEOIP_JSON, bundle, provider); + } else { + EipCommand.startVPN(context, false); + } + EipStatus.getInstance().updateState("UI_CONNECTING", "", 0, ConnectionStatus.LEVEL_START); + } + + protected void stopEipIfPossible() { + Context context = getContext(); + if (context == null) { + Log.e(TAG, "context is null when trying to stop EIP"); + return; + } + EipCommand.stopVPN(context); + } + + private void askPendingStartCancellation() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null when asking to cancel"); + return; + } + + try { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity()); + showPendingStartCancellation = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) + .setMessage(activity.getString(R.string.eip_cancel_connect_text)) + .setPositiveButton((android.R.string.yes), (dialog, which) -> { + Context context = getContext(); + if (context != null && eipStatus.isUpdatingVpnCert() && + TorStatusObservable.isRunning()) { + TorServiceCommand.stopTorServiceAsync(context.getApplicationContext()); + } + stopEipIfPossible(); + }) + .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { + }).setOnDismissListener(dialog -> showPendingStartCancellation = false).show(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + + } + + protected void askToStopEIP() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null when asking to stop EIP"); + return; + } + try { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity); + showAskToStopEip = true; + alertDialog = alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title)) + .setMessage(activity.getString(R.string.eip_warning_browser_inconsistency)) + .setPositiveButton((android.R.string.yes), (dialog, which) -> stopEipIfPossible()) + .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> { + }).setOnDismissListener(dialog -> showAskToStopEip = false).show(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + + } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + 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()) { + handleNewStateOnMain(); + } + } + + private void handleNewStateOnMain() { + Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(this::handleNewState); + } else { + Log.e("EipFragment", "activity is null"); + } + } + + private void handleNewState() { + Activity activity = getActivity(); + if (activity == null) { + Log.e(TAG, "activity is null while trying to handle new state"); + return; + } + + Log.d(TAG, "eip fragment eipStatus state: " + eipStatus.getState() + " - level: " + eipStatus.getLevel() + " - is reconnecting: " + eipStatus.isReconnecting()); + if (eipStatus.isUpdatingVpnCert()) { + setMainButtonEnabled(true); + showConnectionTransitionLayout(true); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + String torStatus = TorStatusObservable.getStringForCurrentStatus(getContext()); + if (!TextUtils.isEmpty(torStatus)) { + Spannable spannable = new SpannableString(torStatus); + spannable.setSpan(new RelativeSizeSpan(0.75f), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + subDescription.setText(TextUtils.concat(getString(R.string.updating_certificate_message) + "\n", spannable)); + } else { + subDescription.setText(getString(R.string.updating_certificate_message)); + } + } else if (eipStatus.isConnecting()) { + setMainButtonEnabled(true); + showConnectionTransitionLayout(true); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + subDescription.setText(null); + } else if (eipStatus.isConnected()) { + setMainButtonEnabled(true); + mainButton.updateState(true, false, 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()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(null); + colorBackground(); + } else if(isOpenVpnRunningWithoutNetwork()) { + Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); + setMainButtonEnabled(true); + mainButton.updateState(true, false, true); + locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); + locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); + colorBackgroundALittle(); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(R.string.eip_state_no_network); + } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { + showConnectionTransitionLayout(true); + // showRetryToast(activity); + locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(null); + subDescription.setText(R.string.reconnecting); + } else if (eipStatus.isDisconnecting()) { + setMainButtonEnabled(false); + showConnectionTransitionLayout(false); + mainDescription.setText(R.string.eip_state_insecure); + } else if (eipStatus.isBlocking()) { + setMainButtonEnabled(true); + mainButton.updateState(true, false, true); + colorBackgroundALittle(); + locationButton.setText(getString(R.string.no_location)); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(R.string.eip_state_connected); + subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); + } else { + locationButton.setText(activity.getString(R.string.vpn_button_turn_on)); + setMainButtonEnabled(true); + mainButton.updateState(false, false, false); + greyscaleBackground(); + locationButton.setLocationLoad(UNKNOWN); + locationButton.showBridgeIndicator(false); + String city = getPreferredCity(getContext()); + locationButton.setText(city == null ? getString(R.string.gateway_selection_recommended_location) : city); + locationButton.showRecommendedIndicator(false); + mainDescription.setText(R.string.eip_state_insecure); + subDescription.setText(R.string.connection_not_connected); + } + } + + private void showToast(Activity activity, String message, boolean vibrateLong) { + LayoutInflater inflater = getLayoutInflater(); + View layout = inflater.inflate(R.layout.custom_toast, + activity.findViewById(R.id.custom_toast_container)); + + AppCompatTextView text = layout.findViewById(R.id.text); + text.setText(message); + + Vibrator v = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrateLong) { + v.vibrate(100); + v.vibrate(200); + } else { + v.vibrate(100); + } + + Toast toast = new Toast(activity.getApplicationContext()); + toast.setGravity(Gravity.BOTTOM, 0, convertDimensionToPx(this.getContext(), R.dimen.stdpadding)); + toast.setDuration(Toast.LENGTH_LONG); + toast.setView(layout); + toast.show(); + } + + private void showRetryToast(Activity activity) { + int nClosestGateway = gatewayOrder(); + String message = String.format("Server number " + nClosestGateway + " not reachable. Trying next gateway."); + showToast(activity, message, true ); + } + + private void showConnectionTransitionLayout(boolean isConnecting) { + mainButton.updateState(true, isConnecting, false); + if (isConnecting) { + colorBackgroundALittle(); + } else { + greyscaleBackground(); + } + } + + 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 greyscaleBackground() { + if (BuildConfig.use_color_filter) { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0); + ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); + background.setColorFilter(cf); + background.setImageAlpha(255); + } + } + + private void colorBackgroundALittle() { + if (BuildConfig.use_color_filter) { + background.setColorFilter(null); + background.setImageAlpha(144); + } + } + + private void colorBackground() { + if (BuildConfig.use_color_filter) { + background.setColorFilter(null); + background.setImageAlpha(210); + } + } + + private void updateInvalidVpnCertificate() { + eipStatus.setUpdatingVpnCert(true); + ProviderAPICommand.execute(getContext(), UPDATE_INVALID_VPN_CERTIFICATE, provider); + } + + private void askUserToLogIn(String userMessage) { + Intent intent = new Intent(getContext(), LoginActivity.class); + intent.putExtra(PROVIDER_KEY, provider); + + if(userMessage != null) { + intent.putExtra(USER_MESSAGE, userMessage); + } + + Activity activity = getActivity(); + if (activity != null) { + activity.startActivityForResult(intent, REQUEST_CODE_LOG_IN); + } + } + + 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( + getActivity().getSupportFragmentManager()).removePreviousFragment( + DonationReminderDialog.TAG); + DialogFragment newFragment = new DonationReminderDialog(); + newFragment.setCancelable(false); + newFragment.show(fragmentTransaction, DonationReminderDialog.TAG); + } catch (IllegalStateException | NullPointerException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/custom/java/se/leap/bitmaskclient/base/views/MainButton.java b/app/src/custom/java/se/leap/bitmaskclient/base/views/MainButton.java new file mode 100644 index 00000000..c5ac4544 --- /dev/null +++ b/app/src/custom/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/MainButton.java b/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java deleted file mode 100644 index c5ac4544..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/MainButton.java +++ /dev/null @@ -1,124 +0,0 @@ -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/VpnStateImage.java b/app/src/main/java/se/leap/bitmaskclient/base/views/VpnStateImage.java deleted file mode 100644 index 2f8a4448..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/VpnStateImage.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient.base.views; - -import android.content.Context; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.appcompat.widget.AppCompatImageView; -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.ProgressBar; - -import se.leap.bitmaskclient.R; - -/** - * Created by cyberta on 12.02.18. - */ - - -public class VpnStateImage extends ConstraintLayout { - - ProgressBar progressBar; - AppCompatImageView stateIcon; - - public VpnStateImage(Context context) { - super(context); - initLayout(context); - } - - public VpnStateImage(Context context, AttributeSet attrs) { - super(context, attrs); - initLayout(context); - } - - public VpnStateImage(Context context, 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_main_button, this, true); - stateIcon = rootview.findViewById(R.id.vpn_state_key); - progressBar = rootview.findViewById(R.id.progressBar); - progressBar.setIndeterminate(true); - } - - public void showProgress() { - progressBar.setVisibility(VISIBLE); - } - - - public void stopProgress(boolean animated) { - if (!animated) { - progressBar.setVisibility(GONE); - return; - } - - AlphaAnimation fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f); - fadeOutAnimation.setDuration(1000); - fadeOutAnimation.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) {} - - @Override - public void onAnimationEnd(Animation animation) { - progressBar.setVisibility(GONE); - } - - @Override - public void onAnimationRepeat(Animation animation) {} - }); - - progressBar.startAnimation(fadeOutAnimation); - } - - public void setStateIcon(int resource) { - stateIcon.setImageResource(resource); - } - - -} diff --git a/app/src/main/res/drawable-hdpi/ic_btn_cancel.png b/app/src/main/res/drawable-hdpi/ic_btn_cancel.png new file mode 100644 index 00000000..00feedcd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_btn_cancel.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_btn_on.png b/app/src/main/res/drawable-hdpi/ic_btn_on.png new file mode 100644 index 00000000..2b37d25e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_btn_on.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_btn_cancel.png b/app/src/main/res/drawable-xhdpi/ic_btn_cancel.png new file mode 100644 index 00000000..d623f8f5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_btn_cancel.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_btn_on.png b/app/src/main/res/drawable-xhdpi/ic_btn_on.png new file mode 100644 index 00000000..4fdc9464 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_btn_on.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_btn_cancel.png b/app/src/main/res/drawable-xxhdpi/ic_btn_cancel.png new file mode 100644 index 00000000..af604d9b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_btn_cancel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_btn_on.png b/app/src/main/res/drawable-xxhdpi/ic_btn_on.png new file mode 100644 index 00000000..d6cfc10b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_btn_on.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_btn_cancel.png b/app/src/main/res/drawable-xxxhdpi/ic_btn_cancel.png new file mode 100644 index 00000000..6c17bd78 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_btn_cancel.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_btn_on.png b/app/src/main/res/drawable-xxxhdpi/ic_btn_on.png new file mode 100644 index 00000000..b0e54b8c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_btn_on.png differ diff --git a/app/src/main/res/drawable/button_circle_cancel.xml b/app/src/main/res/drawable/button_circle_cancel.xml new file mode 100644 index 00000000..1d94abca --- /dev/null +++ b/app/src/main/res/drawable/button_circle_cancel.xml @@ -0,0 +1,5 @@ + + + + + \ 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 new file mode 100644 index 00000000..13970e9f --- /dev/null +++ b/app/src/main/res/drawable/button_circle_cancel_pressed.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 00000000..2e7bc4b7 --- /dev/null +++ b/app/src/main/res/drawable/button_circle_cancel_released.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_start.xml b/app/src/main/res/drawable/button_circle_start.xml new file mode 100644 index 00000000..6d8482f4 --- /dev/null +++ b/app/src/main/res/drawable/button_circle_start.xml @@ -0,0 +1,7 @@ + + + + + + + \ 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 new file mode 100644 index 00000000..ce8eb8e1 --- /dev/null +++ b/app/src/main/res/drawable/button_circle_start_pressed.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 00000000..ce1ba997 --- /dev/null +++ b/app/src/main/res/drawable/button_circle_start_released.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_circle_stop.xml b/app/src/main/res/drawable/button_circle_stop.xml new file mode 100644 index 00000000..674cbf15 --- /dev/null +++ b/app/src/main/res/drawable/button_circle_stop.xml @@ -0,0 +1,5 @@ + + + + + \ 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 new file mode 100644 index 00000000..0561455a --- /dev/null +++ b/app/src/main/res/drawable/button_circle_stop_pressed.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 00000000..2e168c2d --- /dev/null +++ b/app/src/main/res/drawable/button_circle_stop_released.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_btn_cancel.png b/app/src/main/res/drawable/ic_btn_cancel.png new file mode 100644 index 00000000..0b55460a Binary files /dev/null and b/app/src/main/res/drawable/ic_btn_cancel.png differ diff --git a/app/src/main/res/drawable/ic_btn_on.png b/app/src/main/res/drawable/ic_btn_on.png new file mode 100644 index 00000000..be160a33 Binary files /dev/null and b/app/src/main/res/drawable/ic_btn_on.png differ diff --git a/app/src/main/res/layout/v_main_button.xml b/app/src/main/res/layout/v_main_button.xml deleted file mode 100644 index 741fc88f..00000000 --- a/app/src/main/res/layout/v_main_button.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 40b51436..dbc7326f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -14,6 +14,7 @@ #3b3b3b #AA424242 #22424242 + #00000000 #ef9a9a #f48fb1 @@ -45,5 +46,11 @@ @color/black800 @color/black800_high_transparent #B33A3A + #FF7D7D + #c84c51 + #FFBF00 + #C78F00 + #9FC17F + #709152 diff --git a/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java b/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java new file mode 100644 index 00000000..d8766e6b --- /dev/null +++ b/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java @@ -0,0 +1,64 @@ +package se.leap.bitmaskclient.base.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.RelativeLayout; + +import androidx.appcompat.widget.AppCompatImageView; +import androidx.core.content.ContextCompat; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.databinding.VMainButtonBinding; + +public class MainButton extends RelativeLayout { + + private static final String TAG = MainButton.class.getSimpleName(); + + AppCompatImageView button; + VMainButtonBinding binding; + + 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) { + binding = VMainButtonBinding.inflate(LayoutInflater.from(context), this, true); + button = binding.button; + } + + public void updateState(boolean isOn, boolean isProcessing, boolean isError) { + if (isProcessing) { + button.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.button_circle_cancel)); + } else { + button.setImageDrawable( + ContextCompat.getDrawable(getContext(), + isOn ? R.drawable.button_circle_stop : R.drawable.button_circle_start)); + } + } + +} diff --git a/app/src/normal/res/drawable/rainbow_circle.xml b/app/src/normal/res/drawable/rainbow_circle.xml new file mode 100644 index 00000000..44a35ba9 --- /dev/null +++ b/app/src/normal/res/drawable/rainbow_circle.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/normal/res/layout/v_main_button.xml b/app/src/normal/res/layout/v_main_button.xml new file mode 100644 index 00000000..e3f96693 --- /dev/null +++ b/app/src/normal/res/layout/v_main_button.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From c2f6bc4e2098265fb1fc8f671dbdecbb5917c6fc Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 14:01:05 +0100 Subject: new EipFragment layout for Bitmask - portrait --- .../bitmaskclient/base/views/LocationButton.java | 25 +++- app/src/main/res/drawable-hdpi/bg_green.png | Bin 0 -> 190405 bytes app/src/main/res/drawable-hdpi/bg_red.png | Bin 0 -> 143331 bytes app/src/main/res/drawable-hdpi/bg_yellow.png | Bin 0 -> 236571 bytes app/src/main/res/drawable-hdpi/green_mask.png | Bin 0 -> 81235 bytes app/src/main/res/drawable-hdpi/red_mask.png | Bin 0 -> 73514 bytes app/src/main/res/drawable-hdpi/yellow_mask.png | Bin 0 -> 80386 bytes app/src/main/res/drawable-xhdpi/bg_green.png | Bin 0 -> 319429 bytes app/src/main/res/drawable-xhdpi/bg_red.png | Bin 0 -> 220676 bytes app/src/main/res/drawable-xhdpi/bg_yellow.png | Bin 0 -> 400307 bytes app/src/main/res/drawable-xhdpi/green_mask.png | Bin 0 -> 121655 bytes app/src/main/res/drawable-xhdpi/red_mask.png | Bin 0 -> 116193 bytes app/src/main/res/drawable-xhdpi/yellow_mask.png | Bin 0 -> 122701 bytes app/src/main/res/drawable-xxhdpi/bg_green.png | Bin 0 -> 701727 bytes app/src/main/res/drawable-xxhdpi/bg_red.png | Bin 0 -> 446155 bytes app/src/main/res/drawable-xxhdpi/bg_yellow.png | Bin 0 -> 828368 bytes app/src/main/res/drawable-xxhdpi/green_mask.png | Bin 0 -> 220730 bytes app/src/main/res/drawable-xxhdpi/red_mask.png | Bin 0 -> 222370 bytes app/src/main/res/drawable-xxhdpi/yellow_mask.png | Bin 0 -> 226345 bytes app/src/main/res/drawable-xxxhdpi/bg_green.png | Bin 0 -> 1228810 bytes app/src/main/res/drawable-xxxhdpi/bg_red.png | Bin 0 -> 745847 bytes app/src/main/res/drawable-xxxhdpi/bg_yellow.png | Bin 0 -> 1489207 bytes app/src/main/res/drawable-xxxhdpi/green_mask.png | Bin 0 -> 324196 bytes app/src/main/res/drawable-xxxhdpi/red_mask.png | Bin 0 -> 362086 bytes app/src/main/res/drawable-xxxhdpi/yellow_mask.png | Bin 0 -> 334967 bytes app/src/main/res/drawable/bg_green.png | Bin 0 -> 90299 bytes app/src/main/res/drawable/bg_red.png | Bin 0 -> 143331 bytes app/src/main/res/drawable/bg_yellow.png | Bin 0 -> 112042 bytes app/src/main/res/drawable/green_mask.png | Bin 0 -> 47593 bytes app/src/main/res/drawable/red_mask.png | Bin 0 -> 40172 bytes app/src/main/res/drawable/yellow_mask.png | Bin 0 -> 47055 bytes app/src/main/res/layout/v_location_button.xml | 33 ++--- app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/strings.xml | 3 + .../EipFragment.java | 163 +++++++-------------- app/src/normal/res/color/button_tint_color.xml | 9 ++ app/src/normal/res/drawable/background_red.xml | 26 ++++ .../res/drawable/cust_button_primary_rect.xml | 79 ++++++++++ app/src/normal/res/layout-port/f_eip.xml | 85 ++++++++--- app/src/normal/res/layout-xlarge-port/f_eip.xml | 1 - app/src/normal/res/layout-xlarge/f_eip.xml | 1 - app/src/normal/res/layout/f_eip.xml | 65 ++++---- app/src/normal/res/layout/v_location_button.xml | 104 +++++++++++++ 43 files changed, 417 insertions(+), 182 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/bg_green.png create mode 100644 app/src/main/res/drawable-hdpi/bg_red.png create mode 100644 app/src/main/res/drawable-hdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-hdpi/green_mask.png create mode 100644 app/src/main/res/drawable-hdpi/red_mask.png create mode 100644 app/src/main/res/drawable-hdpi/yellow_mask.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_green.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_red.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xhdpi/green_mask.png create mode 100644 app/src/main/res/drawable-xhdpi/red_mask.png create mode 100644 app/src/main/res/drawable-xhdpi/yellow_mask.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_green.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_red.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xxhdpi/green_mask.png create mode 100644 app/src/main/res/drawable-xxhdpi/red_mask.png create mode 100644 app/src/main/res/drawable-xxhdpi/yellow_mask.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_green.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_red.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xxxhdpi/green_mask.png create mode 100644 app/src/main/res/drawable-xxxhdpi/red_mask.png create mode 100644 app/src/main/res/drawable-xxxhdpi/yellow_mask.png create mode 100644 app/src/main/res/drawable/bg_green.png create mode 100644 app/src/main/res/drawable/bg_red.png create mode 100644 app/src/main/res/drawable/bg_yellow.png create mode 100644 app/src/main/res/drawable/green_mask.png create mode 100644 app/src/main/res/drawable/red_mask.png create mode 100644 app/src/main/res/drawable/yellow_mask.png create mode 100644 app/src/normal/res/color/button_tint_color.xml create mode 100644 app/src/normal/res/drawable/background_red.xml create mode 100644 app/src/normal/res/drawable/cust_button_primary_rect.xml create mode 100644 app/src/normal/res/layout/v_location_button.xml 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 index b2182d61..2118ecb5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java @@ -1,17 +1,25 @@ package se.leap.bitmaskclient.base.views; import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.ColorDrawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.RelativeLayout; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatTextView; +import androidx.core.content.ContextCompat; +import androidx.core.view.LayoutInflaterCompat; +import androidx.core.view.ViewCompat; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.databinding.VLocationButtonBinding; import se.leap.bitmaskclient.eip.GatewaysManager; public class LocationButton extends RelativeLayout { @@ -31,13 +39,16 @@ public class LocationButton extends RelativeLayout { } 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); + VLocationButtonBinding binding = VLocationButtonBinding.inflate(LayoutInflater.from(context), this, true); + locationIndicator = binding.loadIndicator; + textView = binding.textLocation; + bridgeView = binding.bridgeIcn; + recommendedView = binding.recommendedIcn; + + } + + public void setTextColor(@ColorRes int color) { + textView.setTextColor(ContextCompat.getColor(getContext(), color)); } public void setLocationLoad(GatewaysManager.Load load) { diff --git a/app/src/main/res/drawable-hdpi/bg_green.png b/app/src/main/res/drawable-hdpi/bg_green.png new file mode 100644 index 00000000..0e98f705 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_green.png differ diff --git a/app/src/main/res/drawable-hdpi/bg_red.png b/app/src/main/res/drawable-hdpi/bg_red.png new file mode 100644 index 00000000..de96be57 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_red.png differ diff --git a/app/src/main/res/drawable-hdpi/bg_yellow.png b/app/src/main/res/drawable-hdpi/bg_yellow.png new file mode 100644 index 00000000..24632712 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_yellow.png differ diff --git a/app/src/main/res/drawable-hdpi/green_mask.png b/app/src/main/res/drawable-hdpi/green_mask.png new file mode 100644 index 00000000..fccc060a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/green_mask.png differ diff --git a/app/src/main/res/drawable-hdpi/red_mask.png b/app/src/main/res/drawable-hdpi/red_mask.png new file mode 100644 index 00000000..d2ef7d99 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/red_mask.png differ diff --git a/app/src/main/res/drawable-hdpi/yellow_mask.png b/app/src/main/res/drawable-hdpi/yellow_mask.png new file mode 100644 index 00000000..72e3ae45 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/yellow_mask.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_green.png b/app/src/main/res/drawable-xhdpi/bg_green.png new file mode 100644 index 00000000..915dff95 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_green.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_red.png b/app/src/main/res/drawable-xhdpi/bg_red.png new file mode 100644 index 00000000..433c776f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_red.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_yellow.png b/app/src/main/res/drawable-xhdpi/bg_yellow.png new file mode 100644 index 00000000..be4469df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_yellow.png differ diff --git a/app/src/main/res/drawable-xhdpi/green_mask.png b/app/src/main/res/drawable-xhdpi/green_mask.png new file mode 100644 index 00000000..c852459d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/green_mask.png differ diff --git a/app/src/main/res/drawable-xhdpi/red_mask.png b/app/src/main/res/drawable-xhdpi/red_mask.png new file mode 100644 index 00000000..c0d57a03 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/red_mask.png differ diff --git a/app/src/main/res/drawable-xhdpi/yellow_mask.png b/app/src/main/res/drawable-xhdpi/yellow_mask.png new file mode 100644 index 00000000..d81190fe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/yellow_mask.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_green.png b/app/src/main/res/drawable-xxhdpi/bg_green.png new file mode 100644 index 00000000..cd78d865 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_green.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_red.png b/app/src/main/res/drawable-xxhdpi/bg_red.png new file mode 100644 index 00000000..ffbcdb79 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_red.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_yellow.png b/app/src/main/res/drawable-xxhdpi/bg_yellow.png new file mode 100644 index 00000000..718e102f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_yellow.png differ diff --git a/app/src/main/res/drawable-xxhdpi/green_mask.png b/app/src/main/res/drawable-xxhdpi/green_mask.png new file mode 100644 index 00000000..32286177 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/green_mask.png differ diff --git a/app/src/main/res/drawable-xxhdpi/red_mask.png b/app/src/main/res/drawable-xxhdpi/red_mask.png new file mode 100644 index 00000000..ac560317 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/red_mask.png differ diff --git a/app/src/main/res/drawable-xxhdpi/yellow_mask.png b/app/src/main/res/drawable-xxhdpi/yellow_mask.png new file mode 100644 index 00000000..75cf3782 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/yellow_mask.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_green.png b/app/src/main/res/drawable-xxxhdpi/bg_green.png new file mode 100644 index 00000000..3c9d97b4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_green.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_red.png b/app/src/main/res/drawable-xxxhdpi/bg_red.png new file mode 100644 index 00000000..2503f135 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_red.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_yellow.png b/app/src/main/res/drawable-xxxhdpi/bg_yellow.png new file mode 100644 index 00000000..bff2004c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_yellow.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/green_mask.png b/app/src/main/res/drawable-xxxhdpi/green_mask.png new file mode 100644 index 00000000..f5a5adaf Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/green_mask.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/red_mask.png b/app/src/main/res/drawable-xxxhdpi/red_mask.png new file mode 100644 index 00000000..9e216955 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/red_mask.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/yellow_mask.png b/app/src/main/res/drawable-xxxhdpi/yellow_mask.png new file mode 100644 index 00000000..806dcbf4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/yellow_mask.png differ diff --git a/app/src/main/res/drawable/bg_green.png b/app/src/main/res/drawable/bg_green.png new file mode 100644 index 00000000..6da7878d Binary files /dev/null and b/app/src/main/res/drawable/bg_green.png differ diff --git a/app/src/main/res/drawable/bg_red.png b/app/src/main/res/drawable/bg_red.png new file mode 100644 index 00000000..de96be57 Binary files /dev/null and b/app/src/main/res/drawable/bg_red.png differ diff --git a/app/src/main/res/drawable/bg_yellow.png b/app/src/main/res/drawable/bg_yellow.png new file mode 100644 index 00000000..c371f3f0 Binary files /dev/null and b/app/src/main/res/drawable/bg_yellow.png differ diff --git a/app/src/main/res/drawable/green_mask.png b/app/src/main/res/drawable/green_mask.png new file mode 100644 index 00000000..e515f3f5 Binary files /dev/null and b/app/src/main/res/drawable/green_mask.png differ diff --git a/app/src/main/res/drawable/red_mask.png b/app/src/main/res/drawable/red_mask.png new file mode 100644 index 00000000..a4bd4a78 Binary files /dev/null and b/app/src/main/res/drawable/red_mask.png differ diff --git a/app/src/main/res/drawable/yellow_mask.png b/app/src/main/res/drawable/yellow_mask.png new file mode 100644 index 00000000..98dd7978 Binary files /dev/null and b/app/src/main/res/drawable/yellow_mask.png differ diff --git a/app/src/main/res/layout/v_location_button.xml b/app/src/main/res/layout/v_location_button.xml index d304d429..44a4c67e 100644 --- a/app/src/main/res/layout/v_location_button.xml +++ b/app/src/main/res/layout/v_location_button.xml @@ -39,31 +39,30 @@ android:visibility="gone" tools:visibility="visible" /> + + app:autoSizeMaxTextSize="24sp" + app:autoSizeMinTextSize="15sp" + app:autoSizeTextType="uniform" + tools:text="Seattle along message" /> #C78F00 #9FC17F #709152 + #CCFFFEFE + #CCCCCBCB + #EC6767 + #DB6F66 + #D05D59 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92229e44..722f10ed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,9 @@ Authentication failed Registration failed Initiating connection + Connecting VPN + Unsecured Connection + Secured Connection Cancel connection? There is a connection attempt in progress. Do you wish to cancel it? Turn off VPN connection? When the VPN is off, you may leak personal information to your Internet provider or local network. diff --git a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java index 2588f436..842cb38e 100644 --- a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java +++ b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java @@ -63,6 +63,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatTextView; +import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; @@ -71,10 +72,6 @@ import java.util.Observable; import java.util.Observer; import java.util.concurrent.atomic.AtomicBoolean; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Unbinder; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; @@ -84,13 +81,12 @@ import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.FragmentManagerEnhanced; import se.leap.bitmaskclient.base.MainActivity; -import se.leap.bitmaskclient.base.fragments.DonationReminderDialog; -import se.leap.bitmaskclient.base.fragments.GatewaySelectionFragment; 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.views.LocationButton; import se.leap.bitmaskclient.base.views.MainButton; +import se.leap.bitmaskclient.databinding.FEipBinding; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.GatewaysManager; @@ -110,22 +106,13 @@ public class EipFragment extends Fragment implements Observer { private SharedPreferences preferences; private Provider provider; - @BindView(R.id.background) AppCompatImageView background; - - @BindView(R.id.main_button) + AppCompatImageView stateView; MainButton mainButton; - - @BindView(R.id.gateway_location_button) LocationButton locationButton; - - @BindView(R.id.main_description) AppCompatTextView mainDescription; - - @BindView(R.id.sub_description) AppCompatTextView subDescription; - private Unbinder unbinder; private EipStatus eipStatus; private ProviderObservable providerObservable; private TorStatusObservable torStatusObservable; @@ -195,11 +182,18 @@ public class EipFragment extends Fragment implements Observer { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + FEipBinding binding = FEipBinding.inflate(LayoutInflater.from(getContext()), container, false); + background = binding.background; + mainButton = binding.mainButton; + locationButton = binding.gatewayLocationButton; + locationButton.setTextColor(R.color.black800); + mainDescription = binding.mainDescription; + subDescription = binding.subDescription; + stateView = binding.stateView; + eipStatus.addObserver(this); torStatusObservable.addObserver(this); providerObservable.addObserver(this); - View view = inflater.inflate(R.layout.f_eip, container, false); - unbinder = ButterKnife.bind(this, view); try { Bundle arguments = getArguments(); @@ -219,7 +213,11 @@ public class EipFragment extends Fragment implements Observer { Fragment fragment = new GatewaySelectionFragment(); fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); }); - return view; + + mainButton.setOnClickListener(v -> { + handleIcon(); + }); + return binding.getRoot(); } @Override @@ -273,18 +271,12 @@ public class EipFragment extends Fragment implements Observer { eipStatus.deleteObserver(this); providerObservable.deleteObserver(this); torStatusObservable.deleteObserver(this); - unbinder.unbind(); } private void saveStatus(boolean restartOnBoot) { preferences.edit().putBoolean(EIP_RESTART_ON_BOOT, restartOnBoot).apply(); } - @OnClick(R.id.main_button) - void onButtonClick() { - handleIcon(); - } - void handleIcon() { if (isOpenVpnRunningWithoutNetwork() || eipStatus.isConnected() || eipStatus.isConnecting() || eipStatus.isUpdatingVpnCert()) handleSwitchOff(); @@ -448,12 +440,15 @@ public class EipFragment extends Fragment implements Observer { Log.d(TAG, "eip fragment eipStatus state: " + eipStatus.getState() + " - level: " + eipStatus.getLevel() + " - is reconnecting: " + eipStatus.isReconnecting()); if (eipStatus.isUpdatingVpnCert()) { setMainButtonEnabled(true); - showConnectionTransitionLayout(true); - locationButton.setText(getString(R.string.eip_status_start_pending)); + String city = getPreferredCity(getContext()); + String locationName = VpnStatus.getCurrentlyConnectingVpnName() != null ? + VpnStatus.getCurrentlyConnectingVpnName() : + city == null ? getString(R.string.gateway_selection_recommended_location) : city; + locationButton.setText(locationName); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); + mainDescription.setText(R.string.eip_status_connecting); String torStatus = TorStatusObservable.getStringForCurrentStatus(getContext()); if (!TextUtils.isEmpty(torStatus)) { Spannable spannable = new SpannableString(torStatus); @@ -462,15 +457,25 @@ public class EipFragment extends Fragment implements Observer { } else { subDescription.setText(getString(R.string.updating_certificate_message)); } + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); + mainButton.updateState(false, true, false); } else if (eipStatus.isConnecting()) { setMainButtonEnabled(true); - showConnectionTransitionLayout(true); - locationButton.setText(getString(R.string.eip_status_start_pending)); + String city = getPreferredCity(getContext()); + String locationName = VpnStatus.getCurrentlyConnectingVpnName() != null ? + VpnStatus.getCurrentlyConnectingVpnName() : + city == null ? getString(R.string.gateway_selection_recommended_location) : city; + locationButton.setText(locationName); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); + mainDescription.setText(R.string.eip_status_connecting); subDescription.setText(null); + background.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.bg_yellow)); + stateView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.yellow_mask)); + mainButton.updateState(false, true, false); + } else if (eipStatus.isConnected()) { setMainButtonEnabled(true); mainButton.updateState(true, false, false); @@ -478,10 +483,11 @@ public class EipFragment extends Fragment implements Observer { locationButton.setLocationLoad(PreferenceHelper.useObfuscationPinning(getContext()) ? GatewaysManager.Load.UNKNOWN : gatewaysManager.getLoadForLocation(VpnStatus.getLastConnectedVpnName(), transportType)); locationButton.setText(VpnStatus.getLastConnectedVpnName()); locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); - locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); - mainDescription.setText(R.string.eip_state_connected); + locationButton.showRecommendedIndicator(getPreferredCity(getContext()) == null); + mainDescription.setText(R.string.eip_status_secured); subDescription.setText(null); - colorBackground(); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_green)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.green_mask)); } else if(isOpenVpnRunningWithoutNetwork()) { Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); setMainButtonEnabled(true); @@ -490,82 +496,47 @@ public class EipFragment extends Fragment implements Observer { locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); - colorBackgroundALittle(); mainDescription.setText(R.string.eip_state_connected); subDescription.setText(R.string.eip_state_no_network); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { - showConnectionTransitionLayout(true); - // showRetryToast(activity); - locationButton.setText(getString(R.string.eip_status_start_pending)); + locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); locationButton.showRecommendedIndicator(false); - mainDescription.setText(null); + mainDescription.setText(R.string.eip_status_connecting); subDescription.setText(R.string.reconnecting); } else if (eipStatus.isDisconnecting()) { setMainButtonEnabled(false); - showConnectionTransitionLayout(false); - mainDescription.setText(R.string.eip_state_insecure); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); + mainButton.updateState(false, false, false); + mainDescription.setText(R.string.eip_status_unsecured); } else if (eipStatus.isBlocking()) { setMainButtonEnabled(true); mainButton.updateState(true, false, true); - colorBackgroundALittle(); locationButton.setText(getString(R.string.no_location)); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_state_connected); subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); } else { - locationButton.setText(activity.getString(R.string.vpn_button_turn_on)); + locationButton.setText(getContext().getString(R.string.vpn_button_turn_on)); setMainButtonEnabled(true); mainButton.updateState(false, false, false); - greyscaleBackground(); locationButton.setLocationLoad(UNKNOWN); locationButton.showBridgeIndicator(false); String city = getPreferredCity(getContext()); locationButton.setText(city == null ? getString(R.string.gateway_selection_recommended_location) : city); locationButton.showRecommendedIndicator(false); - mainDescription.setText(R.string.eip_state_insecure); - subDescription.setText(R.string.connection_not_connected); - } - } - - private void showToast(Activity activity, String message, boolean vibrateLong) { - LayoutInflater inflater = getLayoutInflater(); - View layout = inflater.inflate(R.layout.custom_toast, - activity.findViewById(R.id.custom_toast_container)); - - AppCompatTextView text = layout.findViewById(R.id.text); - text.setText(message); - - Vibrator v = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); - if (vibrateLong) { - v.vibrate(100); - v.vibrate(200); - } else { - v.vibrate(100); - } - - Toast toast = new Toast(activity.getApplicationContext()); - toast.setGravity(Gravity.BOTTOM, 0, convertDimensionToPx(this.getContext(), R.dimen.stdpadding)); - toast.setDuration(Toast.LENGTH_LONG); - toast.setView(layout); - toast.show(); - } - - private void showRetryToast(Activity activity) { - int nClosestGateway = gatewayOrder(); - String message = String.format("Server number " + nClosestGateway + " not reachable. Trying next gateway."); - showToast(activity, message, true ); - } - - private void showConnectionTransitionLayout(boolean isConnecting) { - mainButton.updateState(true, isConnecting, false); - if (isConnecting) { - colorBackgroundALittle(); - } else { - greyscaleBackground(); + mainDescription.setText(R.string.eip_status_unsecured); + subDescription.setText(null); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); } } @@ -582,30 +553,6 @@ public class EipFragment extends Fragment implements Observer { return isRunning; } - private void greyscaleBackground() { - if (BuildConfig.use_color_filter) { - ColorMatrix matrix = new ColorMatrix(); - matrix.setSaturation(0); - ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); - background.setColorFilter(cf); - background.setImageAlpha(255); - } - } - - private void colorBackgroundALittle() { - if (BuildConfig.use_color_filter) { - background.setColorFilter(null); - background.setImageAlpha(144); - } - } - - private void colorBackground() { - if (BuildConfig.use_color_filter) { - background.setColorFilter(null); - background.setImageAlpha(210); - } - } - private void updateInvalidVpnCertificate() { eipStatus.setUpdatingVpnCert(true); ProviderAPICommand.execute(getContext(), UPDATE_INVALID_VPN_CERTIFICATE, provider); diff --git a/app/src/normal/res/color/button_tint_color.xml b/app/src/normal/res/color/button_tint_color.xml new file mode 100644 index 00000000..f15e571d --- /dev/null +++ b/app/src/normal/res/color/button_tint_color.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/normal/res/drawable/background_red.xml b/app/src/normal/res/drawable/background_red.xml new file mode 100644 index 00000000..0189357c --- /dev/null +++ b/app/src/normal/res/drawable/background_red.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/normal/res/drawable/cust_button_primary_rect.xml b/app/src/normal/res/drawable/cust_button_primary_rect.xml new file mode 100644 index 00000000..74ddccb0 --- /dev/null +++ b/app/src/normal/res/drawable/cust_button_primary_rect.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/normal/res/layout-port/f_eip.xml b/app/src/normal/res/layout-port/f_eip.xml index cb99a700..c068df66 100644 --- a/app/src/normal/res/layout-port/f_eip.xml +++ b/app/src/normal/res/layout-port/f_eip.xml @@ -5,7 +5,6 @@ android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/eipServiceFragment" - tools:viewBindingIgnore="true" > + + + + + + + app:srcCompat="@drawable/bg_red" + android:layout_marginTop="-100dp" + android:layout_marginRight="-100dp" + android:layout_marginBottom="-100dp" + android:layout_marginLeft="-100dp" + /> + - + + + + /> + + @@ -35,16 +40,13 @@ android:layout_width="0dp" android:layout_height="0dp" android:orientation="horizontal" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintGuide_percent="0.55" - app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintGuide_percent="0.45" /> @@ -53,9 +55,8 @@ android:layout_width="0dp" android:layout_height="0dp" android:orientation="horizontal" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintGuide_percent="0.98" - app:layout_constraintRight_toRightOf="parent" /> + /> + android:layout_margin="-100dp" + app:srcCompat="@drawable/bg_red" /> - - + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From c7a23493cb2efe079af9a79c5d7ab0f23a17f778 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 29 Nov 2022 15:20:29 +0100 Subject: scale background images --- app/src/normal/res/layout-port/f_eip.xml | 10 ++++++---- app/src/normal/res/layout/f_eip.xml | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/src/normal/res/layout-port/f_eip.xml b/app/src/normal/res/layout-port/f_eip.xml index c068df66..b17e300c 100644 --- a/app/src/normal/res/layout-port/f_eip.xml +++ b/app/src/normal/res/layout-port/f_eip.xml @@ -62,10 +62,12 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:srcCompat="@drawable/bg_red" - android:layout_marginTop="-100dp" - android:layout_marginRight="-100dp" - android:layout_marginBottom="-100dp" - android:layout_marginLeft="-100dp" + android:scaleType="fitXY" + android:layout_marginTop="-300dp" + android:layout_marginBottom="-300dp" + android:layout_marginLeft="-300dp" + android:layout_marginRight="-300dp" + /> diff --git a/app/src/normal/res/layout/f_eip.xml b/app/src/normal/res/layout/f_eip.xml index e1ea927d..cd636b25 100644 --- a/app/src/normal/res/layout/f_eip.xml +++ b/app/src/normal/res/layout/f_eip.xml @@ -71,7 +71,10 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" - android:layout_margin="-100dp" + android:layout_marginLeft="-300dp" + android:layout_marginRight="-300dp" + android:layout_marginTop="-300dp" + android:layout_marginBottom="-300dp" app:srcCompat="@drawable/bg_red" /> -- cgit v1.2.3 From 4f88dccaef982321e13856b3255534a6d260b8d2 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 15:44:42 +0100 Subject: new Bitmask EipFragment layout for xlarge screens, delete unused background drawable, for now we use scaled png images --- app/src/normal/res/drawable/background_red.xml | 26 ------ app/src/normal/res/layout-xlarge-port/f_eip.xml | 95 +++++++++++++++------- app/src/normal/res/layout-xlarge/f_eip.xml | 103 +++++++++++++++--------- 3 files changed, 134 insertions(+), 90 deletions(-) delete mode 100644 app/src/normal/res/drawable/background_red.xml diff --git a/app/src/normal/res/drawable/background_red.xml b/app/src/normal/res/drawable/background_red.xml deleted file mode 100644 index 0189357c..00000000 --- a/app/src/normal/res/drawable/background_red.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/normal/res/layout-xlarge-port/f_eip.xml b/app/src/normal/res/layout-xlarge-port/f_eip.xml index c3d3fd36..26a90403 100644 --- a/app/src/normal/res/layout-xlarge-port/f_eip.xml +++ b/app/src/normal/res/layout-xlarge-port/f_eip.xml @@ -7,79 +7,97 @@ android:id="@+id/eipServiceFragment" > + + + app:layout_constraintGuide_percent="0.025" + /> + + + + + android:layout_marginTop="-300dp" + android:layout_marginBottom="-300dp" + android:layout_marginLeft="-300dp" + android:layout_marginRight="-300dp" + + /> - @@ -91,18 +109,40 @@ app:layout_constraintTop_toBottomOf="@id/main_description" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toTopOf="@+id/gateway_location_button" android:padding="@dimen/activity_margin" android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large" android:textStyle="bold" android:textColor="@color/colorEipFragmentFont" app:layout_constraintDimensionRatio="1:1" - tools:text="A LONG TEXT WITH SEVERAL THINGS BLABLkk" + tools:text="A LONG TEXT WITH SEVERAL THINGS BLABLkk \n kdjfkj \n kjdfkjdf" android:gravity="center" android:maxLines="2" android:ellipsize="end" /> + + + + diff --git a/app/src/normal/res/layout-xlarge/f_eip.xml b/app/src/normal/res/layout-xlarge/f_eip.xml index 4042933e..e1ecf321 100644 --- a/app/src/normal/res/layout-xlarge/f_eip.xml +++ b/app/src/normal/res/layout-xlarge/f_eip.xml @@ -5,20 +5,20 @@ --> + + + app:layout_constraintGuide_percent="0.3" /> + + + + + app:layout_constraintGuide_percent="0.7" /> - + android:layout_marginLeft="-300dp" + android:layout_marginRight="-300dp" + android:layout_marginTop="-300dp" + android:layout_marginBottom="-300dp" + app:srcCompat="@drawable/bg_red" /> - + + + + -- cgit v1.2.3 From 617f4af8d8dfeae3a4a060de7d5552ef5da57436 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 15:45:29 +0100 Subject: we don't use a color filter in Bitmask anymore --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1e17f01d..630aefc0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,7 +46,7 @@ android { //allow manual gateway selection buildConfigField 'boolean', 'allow_manual_gateway_selection', 'true' // grey out background in EipFragment (main screen) if VPN is not running - buildConfigField 'boolean', 'use_color_filter', 'true' + buildConfigField 'boolean', 'use_color_filter', 'false' // decide if we use obfsvpn or shapeshifter as obfs4 lib buildConfigField 'boolean', 'use_obfsvpn', 'true' // obfsvpn Debugging config fields to pin and configure a particular proxy -- cgit v1.2.3 From 980a6986db013304e02589c41020cdfa67215854 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 18:43:12 +0100 Subject: tint action bar according to connection state --- .../se/leap/bitmaskclient/base/MainActivity.java | 46 +++++++++++++++++++++- .../base/fragments/NavigationDrawerFragment.java | 13 ++++++ .../leap/bitmaskclient/base/utils/ViewHelper.java | 37 +++++++++++++++++ app/src/main/res/values/colors.xml | 12 ++++-- .../EipFragment.java | 35 +++++++++++----- 5 files changed, 128 insertions(+), 15 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 e2fa0783..3b200fd1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -34,6 +34,7 @@ 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; @@ -47,12 +48,18 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; 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 androidx.annotation.ColorRes; import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; @@ -74,6 +81,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.eip.EIP; import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipSetupListener; @@ -82,7 +90,6 @@ import se.leap.bitmaskclient.providersetup.ProviderAPI; import se.leap.bitmaskclient.providersetup.activities.LoginActivity; import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; - public class MainActivity extends AppCompatActivity implements EipSetupListener, Observer { public final static String TAG = MainActivity.class.getSimpleName(); @@ -96,6 +103,8 @@ 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; + /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. */ @@ -227,6 +236,41 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } } + 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_dark_color : R.color.actionbar_light_color; + } else { + actionBarTextColor = textColor; + } + + ViewHelper.setActionBarTextColor(bar, actionBarTextColor); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); 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 cdfee7b2..fe36e00a 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,6 +38,9 @@ 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; @@ -45,12 +48,15 @@ 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; @@ -64,6 +70,7 @@ 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; @@ -443,6 +450,12 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen 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() { 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 7410172f..8076f99e 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,11 +1,18 @@ package se.leap.bitmaskclient.base.utils; +import android.app.Notification; import android.content.Context; +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import androidx.annotation.ColorRes; import androidx.annotation.DimenRes; import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; /** @@ -33,4 +40,34 @@ public class ViewHelper { } } + public static boolean isBrightColor(int color) { + if (android.R.color.transparent == color) + return true; + + boolean rtnValue = false; + + int[] rgb = { Color.red(color), Color.green(color), Color.blue(color) }; + + int brightness = (int) Math.sqrt(rgb[0] * rgb[0] * .241 + rgb[1] + * rgb[1] * .691 + rgb[2] * rgb[2] * .068); + + // color is light + if (brightness >= 200) { + rtnValue = true; + } + + return rtnValue; + } + + public static void setActionBarTextColor(ActionBar bar, @ColorRes int titleColor) { + CharSequence titleCharSequence = bar.getTitle(); + if (titleCharSequence == null) { + return; + } + String title = titleCharSequence.toString(); + Spannable spannableTitle = new SpannableString(title); + spannableTitle.setSpan(new ForegroundColorSpan(ContextCompat.getColor(bar.getThemedContext(), titleColor)), 0, spannableTitle.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + bar.setTitle(spannableTitle); + } + } diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7ec2e81a..b6971138 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -54,8 +54,12 @@ #709152 #CCFFFEFE #CCCCCBCB - #EC6767 - #DB6F66 - #D05D59 - + #EC6767 + #CCff9895 + #FADD85 + #CCffffb6 + #CCDCB8 + #ffffea + @color/black800 + @color/white diff --git a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java index 842cb38e..cccd6c23 100644 --- a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java +++ b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java @@ -29,8 +29,6 @@ import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PR import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; -import static se.leap.bitmaskclient.base.utils.ViewHelper.convertDimensionToPx; -import static se.leap.bitmaskclient.eip.EipSetupObserver.gatewayOrder; import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; import static se.leap.bitmaskclient.eip.GatewaysManager.Load.UNKNOWN; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; @@ -43,22 +41,18 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; import android.os.Bundle; import android.os.IBinder; -import android.os.Vibrator; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.RelativeSizeSpan; import android.util.Log; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; +import androidx.annotation.ColorRes; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatImageView; @@ -77,7 +71,6 @@ 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.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.FragmentManagerEnhanced; import se.leap.bitmaskclient.base.MainActivity; @@ -268,6 +261,10 @@ public class EipFragment extends Fragment implements Observer { @Override public void onDestroyView() { super.onDestroyView(); + Activity activity = getActivity(); + if (activity != null) { + ((MainActivity) activity).setDefaultActivityBarColor(); + } eipStatus.deleteObserver(this); providerObservable.deleteObserver(this); torStatusObservable.deleteObserver(this); @@ -430,6 +427,14 @@ 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_dark_color); + } + private void handleNewState() { Activity activity = getActivity(); if (activity == null) { @@ -460,6 +465,7 @@ public class EipFragment extends Fragment implements Observer { background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); mainButton.updateState(false, true, false); + setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); } else if (eipStatus.isConnecting()) { setMainButtonEnabled(true); String city = getPreferredCity(getContext()); @@ -475,7 +481,7 @@ public class EipFragment extends Fragment implements Observer { background.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.bg_yellow)); stateView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.yellow_mask)); mainButton.updateState(false, true, false); - + setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); } else if (eipStatus.isConnected()) { setMainButtonEnabled(true); mainButton.updateState(true, false, false); @@ -488,6 +494,7 @@ public class EipFragment extends Fragment implements Observer { subDescription.setText(null); background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_green)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.green_mask)); + setActivityBarColor(R.color.bg_green_top, R.color.bg_green_top_light_transparent); } else if(isOpenVpnRunningWithoutNetwork()) { Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); setMainButtonEnabled(true); @@ -500,6 +507,7 @@ public class EipFragment extends Fragment implements Observer { subDescription.setText(R.string.eip_state_no_network); background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); + setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); locationButton.setLocationLoad(UNKNOWN); @@ -507,12 +515,17 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_status_connecting); subDescription.setText(R.string.reconnecting); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); + setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); + } else if (eipStatus.isDisconnecting()) { setMainButtonEnabled(false); background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); - stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); + stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); mainButton.updateState(false, false, false); mainDescription.setText(R.string.eip_status_unsecured); + setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); } else if (eipStatus.isBlocking()) { setMainButtonEnabled(true); mainButton.updateState(true, false, true); @@ -524,6 +537,7 @@ public class EipFragment extends Fragment implements Observer { subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); + setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); } else { locationButton.setText(getContext().getString(R.string.vpn_button_turn_on)); setMainButtonEnabled(true); @@ -537,6 +551,7 @@ public class EipFragment extends Fragment implements Observer { subDescription.setText(null); background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); + setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); } } -- cgit v1.2.3 From bac19fcc3c430405440527d36400ecb8726f9e5c Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 22:29:00 +0100 Subject: clean up, null view references --- .../java/se.leap.bitmaskclient.base.fragments/EipFragment.java | 6 ++++++ .../normal/java/se/leap/bitmaskclient/base/views/MainButton.java | 9 +-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java index cccd6c23..2e291aad 100644 --- a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java +++ b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java @@ -268,6 +268,12 @@ public class EipFragment extends Fragment implements Observer { eipStatus.deleteObserver(this); providerObservable.deleteObserver(this); torStatusObservable.deleteObserver(this); + background = null; + mainButton = null; + locationButton = null; + mainDescription = null; + subDescription = null; + stateView = null; } private void saveStatus(boolean restartOnBoot) { diff --git a/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java b/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java index d8766e6b..715063b5 100644 --- a/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java +++ b/app/src/normal/java/se/leap/bitmaskclient/base/views/MainButton.java @@ -17,12 +17,6 @@ public class MainButton extends RelativeLayout { private static final String TAG = MainButton.class.getSimpleName(); AppCompatImageView button; - VMainButtonBinding binding; - - private boolean isOn = false; - private boolean isProcessing = false; - private boolean isError = true; - public MainButton(Context context) { super(context); @@ -47,7 +41,7 @@ public class MainButton extends RelativeLayout { } private void initLayout(Context context) { - binding = VMainButtonBinding.inflate(LayoutInflater.from(context), this, true); + VMainButtonBinding binding = VMainButtonBinding.inflate(LayoutInflater.from(context), this, true); button = binding.button; } @@ -60,5 +54,4 @@ public class MainButton extends RelativeLayout { isOn ? R.drawable.button_circle_stop : R.drawable.button_circle_start)); } } - } -- cgit v1.2.3 From 86ec8d8700a4bb9e0cec123e49ce408c46869f0e Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 23:48:37 +0100 Subject: rename progress animation image, fix missing resource in custom branded builds --- .../res/drawable/button_circle_cancel_pressed.xml | 2 +- .../res/drawable/button_circle_cancel_released.xml | 2 +- .../main/res/drawable/rotate_progress_image.xml | 12 +++ app/src/normal/res/drawable/rainbow_circle.xml | 103 --------------------- .../normal/res/drawable/rotate_progress_image.xml | 103 +++++++++++++++++++++ 5 files changed, 117 insertions(+), 105 deletions(-) create mode 100644 app/src/main/res/drawable/rotate_progress_image.xml delete mode 100644 app/src/normal/res/drawable/rainbow_circle.xml create mode 100644 app/src/normal/res/drawable/rotate_progress_image.xml 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 13970e9f..8d349770 100644 --- a/app/src/main/res/drawable/button_circle_cancel_pressed.xml +++ b/app/src/main/res/drawable/button_circle_cancel_pressed.xml @@ -13,7 +13,7 @@ android:bottom="-8dp" > + + + + \ No newline at end of file diff --git a/app/src/normal/res/drawable/rainbow_circle.xml b/app/src/normal/res/drawable/rainbow_circle.xml deleted file mode 100644 index 44a35ba9..00000000 --- a/app/src/normal/res/drawable/rainbow_circle.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/normal/res/drawable/rotate_progress_image.xml b/app/src/normal/res/drawable/rotate_progress_image.xml new file mode 100644 index 00000000..44a35ba9 --- /dev/null +++ b/app/src/normal/res/drawable/rotate_progress_image.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 87852092da522ccfe5feee29b43b92b72eca8d45 Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 23:49:39 +0100 Subject: fix missing location button view bindings for custom branded builds --- app/src/main/res/layout/v_location_button.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/layout/v_location_button.xml b/app/src/main/res/layout/v_location_button.xml index 44a4c67e..611ac3c4 100644 --- a/app/src/main/res/layout/v_location_button.xml +++ b/app/src/main/res/layout/v_location_button.xml @@ -8,7 +8,6 @@ android:padding="@dimen/stdpadding" android:background="@drawable/cust_button_primary_rect" android:layout_height="match_parent" - tools:viewBindingIgnore="true" > Date: Tue, 29 Nov 2022 23:50:33 +0100 Subject: avoid resource not found exception by initializing actionBarTextColor with default value --- app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3b200fd1..28b981be 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -103,7 +103,7 @@ 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; + private @ColorRes int actionBarTextColor = R.color.colorActionBarTitleFont; /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. -- cgit v1.2.3 From 90243a1ec25eb50d1c49e16465ae5dabf45e701e Mon Sep 17 00:00:00 2001 From: cyberta Date: Tue, 29 Nov 2022 23:51:05 +0100 Subject: clean up imports --- .../main/java/se/leap/bitmaskclient/base/views/LocationButton.java | 7 ------- 1 file changed, 7 deletions(-) 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 index 2118ecb5..7ad044bd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/LocationButton.java @@ -1,24 +1,17 @@ package se.leap.bitmaskclient.base.views; import android.content.Context; -import android.content.res.ColorStateList; -import android.graphics.drawable.ColorDrawable; import android.util.AttributeSet; import android.view.LayoutInflater; -import android.view.View; import android.widget.RelativeLayout; import androidx.annotation.ColorRes; -import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatTextView; import androidx.core.content.ContextCompat; -import androidx.core.view.LayoutInflaterCompat; -import androidx.core.view.ViewCompat; -import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.databinding.VLocationButtonBinding; import se.leap.bitmaskclient.eip.GatewaysManager; -- cgit v1.2.3 From a4fca14a9a1c33fc81c4687113e0751bc0859857 Mon Sep 17 00:00:00 2001 From: cyberta Date: Wed, 30 Nov 2022 01:07:48 +0100 Subject: delete unused color drawable --- app/src/normal/res/color/button_tint_color.xml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 app/src/normal/res/color/button_tint_color.xml diff --git a/app/src/normal/res/color/button_tint_color.xml b/app/src/normal/res/color/button_tint_color.xml deleted file mode 100644 index f15e571d..00000000 --- a/app/src/normal/res/color/button_tint_color.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file -- cgit v1.2.3 From acdee8421bcdc39151457dea72686c4a31b5cdbb Mon Sep 17 00:00:00 2001 From: cyberta Date: Wed, 30 Nov 2022 01:08:25 +0100 Subject: add raven drawables --- app/src/custom/res/drawable/crow.xml | 9 +++++++++ app/src/custom/res/drawable/ravens1.xml | 16 ++++++++++++++++ app/src/custom/res/drawable/ravens2.xml | 24 ++++++++++++++++++++++++ app/src/custom/res/drawable/ravens3.xml | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 app/src/custom/res/drawable/crow.xml create mode 100644 app/src/custom/res/drawable/ravens1.xml create mode 100644 app/src/custom/res/drawable/ravens2.xml create mode 100644 app/src/custom/res/drawable/ravens3.xml diff --git a/app/src/custom/res/drawable/crow.xml b/app/src/custom/res/drawable/crow.xml new file mode 100644 index 00000000..3d3660b8 --- /dev/null +++ b/app/src/custom/res/drawable/crow.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/custom/res/drawable/ravens1.xml b/app/src/custom/res/drawable/ravens1.xml new file mode 100644 index 00000000..d38b0c19 --- /dev/null +++ b/app/src/custom/res/drawable/ravens1.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/custom/res/drawable/ravens2.xml b/app/src/custom/res/drawable/ravens2.xml new file mode 100644 index 00000000..0a3cbb7e --- /dev/null +++ b/app/src/custom/res/drawable/ravens2.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/custom/res/drawable/ravens3.xml b/app/src/custom/res/drawable/ravens3.xml new file mode 100644 index 00000000..f97a3532 --- /dev/null +++ b/app/src/custom/res/drawable/ravens3.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From da824fa125a5583d07e8ac2f6585459956d87ac1 Mon Sep 17 00:00:00 2001 From: cyberta Date: Wed, 30 Nov 2022 01:37:33 +0100 Subject: rename drawables and colors according to the state they're representing --- app/src/main/res/drawable-hdpi/bg_connected.png | Bin 0 -> 190405 bytes app/src/main/res/drawable-hdpi/bg_connecting.png | Bin 0 -> 236571 bytes app/src/main/res/drawable-hdpi/bg_disconnected.png | Bin 0 -> 143331 bytes app/src/main/res/drawable-hdpi/bg_green.png | Bin 190405 -> 0 bytes app/src/main/res/drawable-hdpi/bg_red.png | Bin 143331 -> 0 bytes app/src/main/res/drawable-hdpi/bg_yellow.png | Bin 236571 -> 0 bytes app/src/main/res/drawable-xhdpi/bg_connected.png | Bin 0 -> 319429 bytes app/src/main/res/drawable-xhdpi/bg_connecting.png | Bin 0 -> 400307 bytes .../main/res/drawable-xhdpi/bg_disconnected.png | Bin 0 -> 220676 bytes app/src/main/res/drawable-xhdpi/bg_green.png | Bin 319429 -> 0 bytes app/src/main/res/drawable-xhdpi/bg_red.png | Bin 220676 -> 0 bytes app/src/main/res/drawable-xhdpi/bg_yellow.png | Bin 400307 -> 0 bytes app/src/main/res/drawable-xxhdpi/bg_connected.png | Bin 0 -> 701727 bytes app/src/main/res/drawable-xxhdpi/bg_connecting.png | Bin 0 -> 828368 bytes .../main/res/drawable-xxhdpi/bg_disconnected.png | Bin 0 -> 446155 bytes app/src/main/res/drawable-xxhdpi/bg_green.png | Bin 701727 -> 0 bytes app/src/main/res/drawable-xxhdpi/bg_red.png | Bin 446155 -> 0 bytes app/src/main/res/drawable-xxhdpi/bg_yellow.png | Bin 828368 -> 0 bytes app/src/main/res/drawable-xxxhdpi/bg_connected.png | Bin 0 -> 1228810 bytes .../main/res/drawable-xxxhdpi/bg_connecting.png | Bin 0 -> 1489207 bytes .../main/res/drawable-xxxhdpi/bg_disconnected.png | Bin 0 -> 745847 bytes app/src/main/res/drawable-xxxhdpi/bg_green.png | Bin 1228810 -> 0 bytes app/src/main/res/drawable-xxxhdpi/bg_red.png | Bin 745847 -> 0 bytes app/src/main/res/drawable-xxxhdpi/bg_yellow.png | Bin 1489207 -> 0 bytes app/src/main/res/drawable/bg_connected.png | Bin 0 -> 90299 bytes app/src/main/res/drawable/bg_connecting.png | Bin 0 -> 112042 bytes app/src/main/res/drawable/bg_disconnected.png | Bin 0 -> 143331 bytes app/src/main/res/drawable/bg_green.png | Bin 90299 -> 0 bytes app/src/main/res/drawable/bg_red.png | Bin 143331 -> 0 bytes app/src/main/res/drawable/bg_yellow.png | Bin 112042 -> 0 bytes .../res/drawable/button_circle_cancel_pressed.xml | 2 +- .../res/drawable/button_circle_cancel_released.xml | 2 +- .../res/drawable/button_circle_start_pressed.xml | 2 +- .../res/drawable/button_circle_start_released.xml | 2 +- .../res/drawable/button_circle_stop_pressed.xml | 2 +- .../res/drawable/button_circle_stop_released.xml | 2 +- .../main/res/drawable/cust_button_light_rect.xml | 79 +++++++++++++++++++++ app/src/main/res/layout/v_location_button.xml | 2 +- app/src/main/res/values/colors.xml | 43 ++++++----- .../EipFragment.java | 32 ++++----- .../res/drawable/cust_button_primary_rect.xml | 79 --------------------- app/src/normal/res/layout-port/f_eip.xml | 2 +- app/src/normal/res/layout-xlarge-port/f_eip.xml | 2 +- app/src/normal/res/layout-xlarge/f_eip.xml | 2 +- app/src/normal/res/layout/f_eip.xml | 2 +- app/src/normal/res/layout/v_location_button.xml | 2 +- 46 files changed, 133 insertions(+), 124 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/bg_connected.png create mode 100644 app/src/main/res/drawable-hdpi/bg_connecting.png create mode 100644 app/src/main/res/drawable-hdpi/bg_disconnected.png delete mode 100644 app/src/main/res/drawable-hdpi/bg_green.png delete mode 100644 app/src/main/res/drawable-hdpi/bg_red.png delete mode 100644 app/src/main/res/drawable-hdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_connected.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_connecting.png create mode 100644 app/src/main/res/drawable-xhdpi/bg_disconnected.png delete mode 100644 app/src/main/res/drawable-xhdpi/bg_green.png delete mode 100644 app/src/main/res/drawable-xhdpi/bg_red.png delete mode 100644 app/src/main/res/drawable-xhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_connected.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_connecting.png create mode 100644 app/src/main/res/drawable-xxhdpi/bg_disconnected.png delete mode 100644 app/src/main/res/drawable-xxhdpi/bg_green.png delete mode 100644 app/src/main/res/drawable-xxhdpi/bg_red.png delete mode 100644 app/src/main/res/drawable-xxhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_connected.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_connecting.png create mode 100644 app/src/main/res/drawable-xxxhdpi/bg_disconnected.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/bg_green.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/bg_red.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/bg_yellow.png create mode 100644 app/src/main/res/drawable/bg_connected.png create mode 100644 app/src/main/res/drawable/bg_connecting.png create mode 100644 app/src/main/res/drawable/bg_disconnected.png delete mode 100644 app/src/main/res/drawable/bg_green.png delete mode 100644 app/src/main/res/drawable/bg_red.png delete mode 100644 app/src/main/res/drawable/bg_yellow.png create mode 100644 app/src/main/res/drawable/cust_button_light_rect.xml delete mode 100644 app/src/normal/res/drawable/cust_button_primary_rect.xml diff --git a/app/src/main/res/drawable-hdpi/bg_connected.png b/app/src/main/res/drawable-hdpi/bg_connected.png new file mode 100644 index 00000000..0e98f705 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_connected.png differ diff --git a/app/src/main/res/drawable-hdpi/bg_connecting.png b/app/src/main/res/drawable-hdpi/bg_connecting.png new file mode 100644 index 00000000..24632712 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_connecting.png differ diff --git a/app/src/main/res/drawable-hdpi/bg_disconnected.png b/app/src/main/res/drawable-hdpi/bg_disconnected.png new file mode 100644 index 00000000..de96be57 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/bg_disconnected.png differ diff --git a/app/src/main/res/drawable-hdpi/bg_green.png b/app/src/main/res/drawable-hdpi/bg_green.png deleted file mode 100644 index 0e98f705..00000000 Binary files a/app/src/main/res/drawable-hdpi/bg_green.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/bg_red.png b/app/src/main/res/drawable-hdpi/bg_red.png deleted file mode 100644 index de96be57..00000000 Binary files a/app/src/main/res/drawable-hdpi/bg_red.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/bg_yellow.png b/app/src/main/res/drawable-hdpi/bg_yellow.png deleted file mode 100644 index 24632712..00000000 Binary files a/app/src/main/res/drawable-hdpi/bg_yellow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/bg_connected.png b/app/src/main/res/drawable-xhdpi/bg_connected.png new file mode 100644 index 00000000..915dff95 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_connected.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_connecting.png b/app/src/main/res/drawable-xhdpi/bg_connecting.png new file mode 100644 index 00000000..be4469df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_connecting.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_disconnected.png b/app/src/main/res/drawable-xhdpi/bg_disconnected.png new file mode 100644 index 00000000..433c776f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_disconnected.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_green.png b/app/src/main/res/drawable-xhdpi/bg_green.png deleted file mode 100644 index 915dff95..00000000 Binary files a/app/src/main/res/drawable-xhdpi/bg_green.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/bg_red.png b/app/src/main/res/drawable-xhdpi/bg_red.png deleted file mode 100644 index 433c776f..00000000 Binary files a/app/src/main/res/drawable-xhdpi/bg_red.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/bg_yellow.png b/app/src/main/res/drawable-xhdpi/bg_yellow.png deleted file mode 100644 index be4469df..00000000 Binary files a/app/src/main/res/drawable-xhdpi/bg_yellow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_connected.png b/app/src/main/res/drawable-xxhdpi/bg_connected.png new file mode 100644 index 00000000..cd78d865 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_connected.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_connecting.png b/app/src/main/res/drawable-xxhdpi/bg_connecting.png new file mode 100644 index 00000000..718e102f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_connecting.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_disconnected.png b/app/src/main/res/drawable-xxhdpi/bg_disconnected.png new file mode 100644 index 00000000..ffbcdb79 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_disconnected.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_green.png b/app/src/main/res/drawable-xxhdpi/bg_green.png deleted file mode 100644 index cd78d865..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/bg_green.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_red.png b/app/src/main/res/drawable-xxhdpi/bg_red.png deleted file mode 100644 index ffbcdb79..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/bg_red.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_yellow.png b/app/src/main/res/drawable-xxhdpi/bg_yellow.png deleted file mode 100644 index 718e102f..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/bg_yellow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_connected.png b/app/src/main/res/drawable-xxxhdpi/bg_connected.png new file mode 100644 index 00000000..3c9d97b4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_connected.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_connecting.png b/app/src/main/res/drawable-xxxhdpi/bg_connecting.png new file mode 100644 index 00000000..bff2004c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_connecting.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_disconnected.png b/app/src/main/res/drawable-xxxhdpi/bg_disconnected.png new file mode 100644 index 00000000..2503f135 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_disconnected.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_green.png b/app/src/main/res/drawable-xxxhdpi/bg_green.png deleted file mode 100644 index 3c9d97b4..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/bg_green.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_red.png b/app/src/main/res/drawable-xxxhdpi/bg_red.png deleted file mode 100644 index 2503f135..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/bg_red.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_yellow.png b/app/src/main/res/drawable-xxxhdpi/bg_yellow.png deleted file mode 100644 index bff2004c..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/bg_yellow.png and /dev/null differ diff --git a/app/src/main/res/drawable/bg_connected.png b/app/src/main/res/drawable/bg_connected.png new file mode 100644 index 00000000..6da7878d Binary files /dev/null and b/app/src/main/res/drawable/bg_connected.png differ diff --git a/app/src/main/res/drawable/bg_connecting.png b/app/src/main/res/drawable/bg_connecting.png new file mode 100644 index 00000000..c371f3f0 Binary files /dev/null and b/app/src/main/res/drawable/bg_connecting.png differ diff --git a/app/src/main/res/drawable/bg_disconnected.png b/app/src/main/res/drawable/bg_disconnected.png new file mode 100644 index 00000000..de96be57 Binary files /dev/null and b/app/src/main/res/drawable/bg_disconnected.png differ diff --git a/app/src/main/res/drawable/bg_green.png b/app/src/main/res/drawable/bg_green.png deleted file mode 100644 index 6da7878d..00000000 Binary files a/app/src/main/res/drawable/bg_green.png and /dev/null differ diff --git a/app/src/main/res/drawable/bg_red.png b/app/src/main/res/drawable/bg_red.png deleted file mode 100644 index de96be57..00000000 Binary files a/app/src/main/res/drawable/bg_red.png and /dev/null differ diff --git a/app/src/main/res/drawable/bg_yellow.png b/app/src/main/res/drawable/bg_yellow.png deleted file mode 100644 index c371f3f0..00000000 Binary files a/app/src/main/res/drawable/bg_yellow.png and /dev/null differ 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 8d349770..690baa0c 100644 --- a/app/src/main/res/drawable/button_circle_cancel_pressed.xml +++ b/app/src/main/res/drawable/button_circle_cancel_pressed.xml @@ -26,7 +26,7 @@ android:bottom="12dp" > - + 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 e6d5948d..833a9076 100644 --- a/app/src/main/res/drawable/button_circle_cancel_released.xml +++ b/app/src/main/res/drawable/button_circle_cancel_released.xml @@ -27,7 +27,7 @@ android:top="15dp" > - + 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 ce8eb8e1..4157ffe0 100644 --- a/app/src/main/res/drawable/button_circle_start_pressed.xml +++ b/app/src/main/res/drawable/button_circle_start_pressed.xml @@ -11,7 +11,7 @@ android:bottom="12dp" > - + 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 ce1ba997..671d06dc 100644 --- a/app/src/main/res/drawable/button_circle_start_released.xml +++ b/app/src/main/res/drawable/button_circle_start_released.xml @@ -11,7 +11,7 @@ android:top="15dp" > - + 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 0561455a..ce7583f1 100644 --- a/app/src/main/res/drawable/button_circle_stop_pressed.xml +++ b/app/src/main/res/drawable/button_circle_stop_pressed.xml @@ -11,7 +11,7 @@ android:bottom="12dp" > - + 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 2e168c2d..ed786ee0 100644 --- a/app/src/main/res/drawable/button_circle_stop_released.xml +++ b/app/src/main/res/drawable/button_circle_stop_released.xml @@ -11,7 +11,7 @@ android:top="15dp" > - + diff --git a/app/src/main/res/drawable/cust_button_light_rect.xml b/app/src/main/res/drawable/cust_button_light_rect.xml new file mode 100644 index 00000000..dd66c739 --- /dev/null +++ b/app/src/main/res/drawable/cust_button_light_rect.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/v_location_button.xml b/app/src/main/res/layout/v_location_button.xml index 611ac3c4..aa4af10c 100644 --- a/app/src/main/res/layout/v_location_button.xml +++ b/app/src/main/res/layout/v_location_button.xml @@ -6,7 +6,7 @@ android:layout_width="match_parent" android:layout_gravity="center_vertical" android:padding="@dimen/stdpadding" - android:background="@drawable/cust_button_primary_rect" + android:background="@drawable/cust_button_light_rect" android:layout_height="match_parent" > diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index b6971138..c3a519cf 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -32,34 +32,43 @@ #ffe082 #ffcc80 #ffab91 - #ffffff #20ffffff #20000000 #05000000 - @color/white - @color/black800 + @color/black800 @color/black800 @color/white @color/black800 @color/black800_high_transparent #B33A3A - #FF7D7D - #c84c51 - #FFBF00 - #C78F00 - #9FC17F - #709152 - #CCFFFEFE - #CCCCCBCB - #EC6767 - #CCff9895 - #FADD85 - #CCffffb6 - #CCDCB8 - #ffffea + + + #FF7D7D + #c84c51 + #FFBF00 + #C78F00 + #9FC17F + #709152 + + + #CCFFFEFE + #CCCCCBCB + + + #EC6767 + #CCff9895 + #FADD85 + #CCffffb6 + #CCDCB8 + #ffffea + + @color/black800 @color/white + + @color/white + @color/black800 diff --git a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java index 2e291aad..0210077c 100644 --- a/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java +++ b/app/src/normal/java/se.leap.bitmaskclient.base.fragments/EipFragment.java @@ -468,10 +468,10 @@ public class EipFragment extends Fragment implements Observer { } else { subDescription.setText(getString(R.string.updating_certificate_message)); } - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_connecting)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); mainButton.updateState(false, true, false); - setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); + setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isConnecting()) { setMainButtonEnabled(true); String city = getPreferredCity(getContext()); @@ -484,10 +484,10 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_status_connecting); subDescription.setText(null); - background.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.bg_yellow)); + background.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.bg_connecting)); stateView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.yellow_mask)); mainButton.updateState(false, true, false); - setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); + setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isConnected()) { setMainButtonEnabled(true); mainButton.updateState(true, false, false); @@ -498,9 +498,9 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(getPreferredCity(getContext()) == null); mainDescription.setText(R.string.eip_status_secured); subDescription.setText(null); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_green)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_connected)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.green_mask)); - setActivityBarColor(R.color.bg_green_top, R.color.bg_green_top_light_transparent); + setActivityBarColor(R.color.bg_running_top, R.color.bg_running_top_light_transparent); } else if(isOpenVpnRunningWithoutNetwork()) { Log.d(TAG, "eip fragment eipStatus - isOpenVpnRunningWithoutNetwork"); setMainButtonEnabled(true); @@ -511,9 +511,9 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); mainDescription.setText(R.string.eip_state_connected); subDescription.setText(R.string.eip_state_no_network); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_connecting)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); - setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); + setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isDisconnected() && reconnectingWithDifferentGateway()) { locationButton.setText(VpnStatus.getCurrentlyConnectingVpnName()); locationButton.setLocationLoad(UNKNOWN); @@ -521,17 +521,17 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_status_connecting); subDescription.setText(R.string.reconnecting); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_yellow)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_connecting)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.yellow_mask)); - setActivityBarColor(R.color.bg_yellow_top, R.color.bg_yellow_top_light_transparent); + setActivityBarColor(R.color.bg_connecting_top, R.color.bg_connecting_top_light_transparent); } else if (eipStatus.isDisconnecting()) { setMainButtonEnabled(false); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_disconnected)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); mainButton.updateState(false, false, false); mainDescription.setText(R.string.eip_status_unsecured); - setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); + setActivityBarColor(R.color.bg_disconnected_top, R.color.bg_disconnected_top_light_transparent); } else if (eipStatus.isBlocking()) { setMainButtonEnabled(true); mainButton.updateState(true, false, true); @@ -541,9 +541,9 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_state_connected); subDescription.setText(getString(R.string.eip_state_blocking, getString(R.string.app_name))); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_disconnected)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); - setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); + setActivityBarColor(R.color.bg_disconnected_top, R.color.bg_disconnected_top_light_transparent); } else { locationButton.setText(getContext().getString(R.string.vpn_button_turn_on)); setMainButtonEnabled(true); @@ -555,9 +555,9 @@ public class EipFragment extends Fragment implements Observer { locationButton.showRecommendedIndicator(false); mainDescription.setText(R.string.eip_status_unsecured); subDescription.setText(null); - background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_red)); + background.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.bg_disconnected)); stateView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.red_mask)); - setActivityBarColor(R.color.bg_red_top, R.color.bg_red_top_light_transparent); + setActivityBarColor(R.color.bg_disconnected_top, R.color.bg_disconnected_top_light_transparent); } } diff --git a/app/src/normal/res/drawable/cust_button_primary_rect.xml b/app/src/normal/res/drawable/cust_button_primary_rect.xml deleted file mode 100644 index 74ddccb0..00000000 --- a/app/src/normal/res/drawable/cust_button_primary_rect.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/normal/res/layout-port/f_eip.xml b/app/src/normal/res/layout-port/f_eip.xml index b17e300c..eed5fde6 100644 --- a/app/src/normal/res/layout-port/f_eip.xml +++ b/app/src/normal/res/layout-port/f_eip.xml @@ -61,7 +61,7 @@ android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" - app:srcCompat="@drawable/bg_red" + app:srcCompat="@drawable/bg_disconnected" android:scaleType="fitXY" android:layout_marginTop="-300dp" android:layout_marginBottom="-300dp" diff --git a/app/src/normal/res/layout-xlarge-port/f_eip.xml b/app/src/normal/res/layout-xlarge-port/f_eip.xml index 26a90403..ae548c82 100644 --- a/app/src/normal/res/layout-xlarge-port/f_eip.xml +++ b/app/src/normal/res/layout-xlarge-port/f_eip.xml @@ -69,7 +69,7 @@ android:id="@+id/background" android:layout_width="match_parent" android:layout_height="match_parent" - app:srcCompat="@drawable/bg_red" + app:srcCompat="@drawable/bg_disconnected" android:scaleType="fitXY" android:layout_marginTop="-300dp" android:layout_marginBottom="-300dp" diff --git a/app/src/normal/res/layout-xlarge/f_eip.xml b/app/src/normal/res/layout-xlarge/f_eip.xml index e1ecf321..a4d94394 100644 --- a/app/src/normal/res/layout-xlarge/f_eip.xml +++ b/app/src/normal/res/layout-xlarge/f_eip.xml @@ -69,7 +69,7 @@ android:layout_marginRight="-300dp" android:layout_marginTop="-300dp" android:layout_marginBottom="-300dp" - app:srcCompat="@drawable/bg_red" /> + app:srcCompat="@drawable/bg_disconnected" /> + app:srcCompat="@drawable/bg_disconnected" />