summaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2018-05-12 01:58:20 +0200
committercyBerta <cyberta@riseup.net>2018-05-12 01:58:20 +0200
commit974a1d28fce969489c0cd4a401f1b51ce0b9cd94 (patch)
tree17b9c90bed8b3cbb02a56be5b84675f8094e30f0 /app/src/main/java
parentc5f445fabcbfa6f045aa5f3e5341909468259aed (diff)
parent5122945a6860caeb46359540ae2a1382f8aab415 (diff)
Merge branch 'master' into #8889_revise_NavigationDrawer
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java22
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/MainActivity.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java17
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java48
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/fragments/AboutFragment.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/fragments/AlwaysOnDialog.java71
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/views/IconTextView.java96
13 files changed, 272 insertions, 26 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
index 6738a6bb..6349cb15 100644
--- a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
@@ -55,7 +55,7 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
options.setAdapter(new ArrayAdapter<>(
this,
- R.layout.single_list_item,
+ R.layout.v_single_list_item,
android.R.id.text1,
optionsList.toArray(new String[optionsList.size()])
));
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index f07a2a23..aaff9ebc 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -58,12 +58,14 @@ import java.util.Map;
import java.util.Set;
import static android.R.attr.name;
+import static se.leap.bitmaskclient.Constants.ALWAYS_ON_SHOW_DIALOG;
import static se.leap.bitmaskclient.Constants.DEFAULT_SHARED_PREFS_BATTERY_SAVER;
import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION;
import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
/**
* Stores constants, and implements auxiliary methods used across all Bitmask Android classes.
@@ -417,9 +419,27 @@ public class ConfigHelper {
preferences.edit().putBoolean(DEFAULT_SHARED_PREFS_BATTERY_SAVER, isEnabled).apply();
}
- public static boolean getSaveBattery(@NonNull Context context) {
+ public static boolean getSaveBattery(Context context) {
+ if (context == null) {
+ return false;
+ }
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getBoolean(DEFAULT_SHARED_PREFS_BATTERY_SAVER, false);
}
+ public static void saveShowAlwaysOnDialog(Context context, boolean showAlwaysOnDialog) {
+ if (context == null) {
+ return;
+ }
+ SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ preferences.edit().putBoolean(ALWAYS_ON_SHOW_DIALOG, showAlwaysOnDialog).apply();
+ }
+
+ public static boolean getShowAlwaysOnDialog(Context context) {
+ if (context == null) {
+ return true;
+ }
+ SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ return preferences.getBoolean(ALWAYS_ON_SHOW_DIALOG, true);
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index 58145015..d719e8d3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -8,6 +8,7 @@ public interface Constants {
String SHARED_PREFERENCES = "LEAPPreferences";
String PREFERENCES_APP_VERSION = "bitmask version";
+ String ALWAYS_ON_SHOW_DIALOG = "DIALOG.ALWAYS_ON_SHOW_DIALOG";
//////////////////////////////////////////////
diff --git a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
index 867f3d48..8238df55 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
@@ -39,6 +39,7 @@ public class DrawerSettingsAdapter extends BaseAdapter {
public static final int LOG = 1;
public static final int ABOUT = 2;
public static final int BATTERY_SAVER = 3;
+ public static final int ALWAYS_ON = 4;
//view types
public final static int VIEW_SIMPLE_TEXT = 0;
@@ -175,14 +176,14 @@ public class DrawerSettingsAdapter extends BaseAdapter {
@NonNull
private View initSwitchBinding(ViewHolder holder) {
- View convertView = mInflater.inflate(R.layout.switch_list_item, null);
+ View convertView = mInflater.inflate(R.layout.v_switch_list_item, null);
holder.switchView = convertView.findViewById(android.R.id.text1);
return convertView;
}
@NonNull
private View initTextViewBinding(ViewHolder holder) {
- View convertView = mInflater.inflate(R.layout.single_list_item, null);
+ View convertView = mInflater.inflate(R.layout.v_single_list_item, null);
holder.textView = convertView.findViewById(android.R.id.text1);
return convertView;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index 34120859..9fcdcac9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -38,7 +38,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.TextView;
import java.util.Observable;
import java.util.Observer;
@@ -145,7 +144,7 @@ public class EipFragment extends Fragment implements Observer {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
eipStatus.addObserver(this);
- View view = inflater.inflate(R.layout.eip_service_fragment, container, false);
+ View view = inflater.inflate(R.layout.f_eip, container, false);
ButterKnife.inject(this, view);
Bundle arguments = getArguments();
diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
index 19294618..d9917799 100644
--- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
@@ -113,7 +113,7 @@ public class MainActivity extends AppCompatActivity implements Observer {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ setContentView(R.layout.a_main);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
mainActivityBroadcastReceiver = new MainActivityBroadcastReceiver();
@@ -141,6 +141,22 @@ public class MainActivity extends AppCompatActivity implements Observer {
}
@Override
+ public void onBackPressed() {
+ FragmentManagerEnhanced fragmentManagerEnhanced = new FragmentManagerEnhanced(getSupportFragmentManager());
+ if (fragmentManagerEnhanced.findFragmentByTag(EipFragment.TAG) == null) {
+ Fragment fragment = new EipFragment();
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(PROVIDER_KEY, provider);
+ fragment.setArguments(bundle);
+ fragmentManagerEnhanced.beginTransaction()
+ .replace(R.id.container, fragment, EipFragment.TAG)
+ .commit();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
@@ -152,10 +168,12 @@ public class MainActivity extends AppCompatActivity implements Observer {
return;
}
+ String fragmentTag = null;
Fragment fragment = null;
switch (intent.getAction()) {
case ACTION_SHOW_VPN_FRAGMENT:
fragment = new EipFragment();
+ fragmentTag = EipFragment.TAG;
Bundle bundle = new Bundle();
if (intent.hasExtra(ASK_TO_CANCEL_VPN)) {
bundle.putBoolean(ASK_TO_CANCEL_VPN, true);
@@ -175,7 +193,7 @@ public class MainActivity extends AppCompatActivity implements Observer {
if (fragment != null) {
new FragmentManagerEnhanced(getSupportFragmentManager()).beginTransaction()
- .replace(R.id.container, fragment)
+ .replace(R.id.container, fragment, fragmentTag)
.commit();
}
}
@@ -214,7 +232,7 @@ public class MainActivity extends AppCompatActivity implements Observer {
arguments.putParcelable(PROVIDER_KEY, provider);
fragment.setArguments(arguments);
new FragmentManagerEnhanced(getSupportFragmentManager()).beginTransaction()
- .replace(R.id.container, fragment)
+ .replace(R.id.container, fragment, EipFragment.TAG)
.commit();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
index 75fffaf7..e0d6e27d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
@@ -28,7 +28,6 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
-import android.view.Menu;
import android.widget.ListView;
import com.pedrogomez.renderers.Renderer;
@@ -47,7 +46,6 @@ import butterknife.InjectView;
import butterknife.OnItemClick;
import se.leap.bitmaskclient.fragments.AboutFragment;
-import static se.leap.bitmaskclient.Constants.APP_ACTION_QUIT;
import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT;
import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
@@ -167,7 +165,7 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
}
private void setUpInitialUI() {
- setContentView(R.layout.provider_list_activity);
+ setContentView(R.layout.a_provider_list);
setProviderHeaderText(R.string.setup_provider);
hideProgressBar();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
index 5b3e5728..795c8e82 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
@@ -25,7 +25,7 @@ public class ProviderRenderer extends Renderer<Provider> {
@Override
protected View inflate(LayoutInflater inflater, ViewGroup parent) {
- View view = inflater.inflate(R.layout.provider_list_item, parent, false);
+ View view = inflater.inflate(R.layout.v_provider_list_item, parent, false);
ButterKnife.inject(this, view);
return view;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
index 459f337b..f4c7f682 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java
@@ -111,8 +111,21 @@ public class VpnNotificationManager {
* @param when
*/
public void buildOpenVpnNotification(String profileName, final String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) {
+ String cancelString;
+ switch (status) {
+ // show cancel if no connection
+ case LEVEL_START:
+ case LEVEL_NONETWORK:
+ case LEVEL_CONNECTING_SERVER_REPLIED:
+ case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
+ cancelString = context.getString(R.string.cancel);
+ break;
+ // show disconnect if connection exists
+ default:
+ cancelString = context.getString(R.string.cancel_connection);
+ }
NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.
- Builder(R.drawable.ic_menu_close_clear_cancel, context.getString(R.string.cancel_connection), getDisconnectIntent());
+ Builder(R.drawable.ic_menu_close_clear_cancel, cancelString, getDisconnectIntent());
String title;
if (isEmpty(profileName)) {
title = context.getString(R.string.app_name);
@@ -200,7 +213,7 @@ public class VpnNotificationManager {
*/
private RemoteViews getKitkatCustomRemoteView(ConnectionStatus status, String title, String message) {
int iconResource = getIconByConnectionStatus(status);
- RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
+ RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.v_custom_notification);
remoteViews.setImageViewResource(R.id.image_icon, iconResource);
remoteViews.setTextViewText(R.id.message, message);
remoteViews.setTextViewText(R.id.title, title);
diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
index 28925efc..f9adede7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -22,10 +22,13 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
@@ -49,6 +52,8 @@ import android.widget.Toast;
import se.leap.bitmaskclient.ConfigHelper;
import se.leap.bitmaskclient.DrawerSettingsAdapter;
import se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem;
+import se.leap.bitmaskclient.FragmentManagerEnhanced;
+import se.leap.bitmaskclient.fragments.AlwaysOnDialog;
import se.leap.bitmaskclient.EipFragment;
import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.ProviderListActivity;
@@ -59,10 +64,12 @@ import se.leap.bitmaskclient.fragments.LogFragment;
import static android.content.Context.MODE_PRIVATE;
import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher;
import static se.leap.bitmaskclient.ConfigHelper.getSaveBattery;
+import static se.leap.bitmaskclient.ConfigHelper.getShowAlwaysOnDialog;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.ABOUT;
+import static se.leap.bitmaskclient.DrawerSettingsAdapter.ALWAYS_ON;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.BATTERY_SAVER;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSimpleTextInstance;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSwitchInstance;
@@ -135,7 +142,7 @@ public class NavigationDrawerFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- mDrawerView = inflater.inflate(R.layout.drawer_main, container, false);
+ mDrawerView = inflater.inflate(R.layout.f_drawer_main, container, false);
restoreFromSavedInstance(savedInstanceState);
return mDrawerView;
}
@@ -180,6 +187,9 @@ public class NavigationDrawerFragment extends Fragment {
}
}));
}
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ settingsListAdapter.addItem(getSimpleTextInstance(getString(R.string.always_on_vpn), ALWAYS_ON));
+ }
settingsListAdapter.addItem(getSimpleTextInstance(getString(switch_provider_menu_option), SWITCH_PROVIDER));
settingsListAdapter.addItem(getSimpleTextInstance(getString(log_fragment_title), LOG));
settingsListAdapter.addItem(getSimpleTextInstance(getString(about_fragment_title), ABOUT));
@@ -194,7 +204,7 @@ public class NavigationDrawerFragment extends Fragment {
});
accountListAdapter = new ArrayAdapter<>(actionBar.getThemedContext(),
- R.layout.single_list_item,
+ R.layout.v_single_list_item,
android.R.id.text1);
createListAdapterData();
@@ -317,7 +327,8 @@ public class NavigationDrawerFragment extends Fragment {
try {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
showEnableExperimentalFeature = true;
- alertDialog = alertBuilder.setTitle(activity.getString(R.string.save_battery))
+ alertDialog = alertBuilder
+ .setTitle(activity.getString(R.string.save_battery))
.setMessage(activity.getString(R.string.save_battery_message))
.setPositiveButton((android.R.string.yes), new DialogInterface.OnClickListener() {
@Override
@@ -347,6 +358,19 @@ public class NavigationDrawerFragment extends Fragment {
} catch (IllegalStateException e) {
e.printStackTrace();
}
+ }
+
+ public void showAlwaysOnDialog() {
+ try {
+
+ FragmentTransaction fragmentTransaction = new FragmentManagerEnhanced(
+ getActivity().getSupportFragmentManager()).removePreviousFragment(
+ AlwaysOnDialog.TAG);
+ DialogFragment newFragment = new AlwaysOnDialog();
+ newFragment.show(fragmentTransaction, AlwaysOnDialog.TAG);
+ } catch (IllegalStateException | NullPointerException e) {
+ e.printStackTrace();
+ }
}
@@ -371,11 +395,6 @@ public class NavigationDrawerFragment extends Fragment {
return true;
}
- if (item.getItemId() == R.id.action_example) {
- Toast.makeText(getActivity(), "Example action.", Toast.LENGTH_SHORT).show();
- return true;
- }
-
return super.onOptionsItemSelected(item);
}
@@ -428,10 +447,12 @@ public class NavigationDrawerFragment extends Fragment {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = null;
+ String fragmentTag = null;
if (parent == mDrawerAccountsListView) {
mTitle = getString(R.string.vpn_fragment_title);
fragment = new EipFragment();
+ fragmentTag = EipFragment.TAG;
Bundle arguments = new Bundle();
Provider currentProvider = ConfigHelper.getSavedProviderFromSharedPreferences(preferences);
arguments.putParcelable(PROVIDER_KEY, currentProvider);
@@ -451,6 +472,15 @@ public class NavigationDrawerFragment extends Fragment {
mTitle = getString(about_fragment_title);
fragment = new AboutFragment();
break;
+ case ALWAYS_ON:
+ if (getShowAlwaysOnDialog(getContext())) {
+ showAlwaysOnDialog();
+ } else {
+ Intent intent = new Intent("android.net.vpn.SETTINGS");
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+ break;
default:
break;
}
@@ -458,7 +488,7 @@ public class NavigationDrawerFragment extends Fragment {
if (fragment != null) {
fragmentManager.beginTransaction()
- .replace(R.id.container, fragment)
+ .replace(R.id.container, fragment, fragmentTag)
.commit();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/fragments/AboutFragment.java b/app/src/main/java/se/leap/bitmaskclient/fragments/AboutFragment.java
index 113ce397..2f37f5b0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/fragments/AboutFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/fragments/AboutFragment.java
@@ -3,7 +3,6 @@ package se.leap.bitmaskclient.fragments;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -24,7 +23,7 @@ public class AboutFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.about, container, false);
+ View view = inflater.inflate(R.layout.f_about, container, false);
ButterKnife.inject(this, view);
return view;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/fragments/AlwaysOnDialog.java b/app/src/main/java/se/leap/bitmaskclient/fragments/AlwaysOnDialog.java
new file mode 100644
index 00000000..3558f378
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/fragments/AlwaysOnDialog.java
@@ -0,0 +1,71 @@
+package se.leap.bitmaskclient.fragments;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatDialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.views.IconTextView;
+
+import static se.leap.bitmaskclient.ConfigHelper.saveShowAlwaysOnDialog;
+
+/**
+ * Created by cyberta on 25.02.18.
+ */
+
+
+
+public class AlwaysOnDialog extends AppCompatDialogFragment {
+
+ public final static String TAG = AlwaysOnDialog.class.getName();
+
+ @InjectView(R.id.do_not_show_again)
+ CheckBox doNotShowAgainCheckBox;
+
+ @InjectView(R.id.user_message)
+ IconTextView userMessage;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View view = inflater.inflate(R.layout.d_checkbox_confirm, null);
+ ButterKnife.inject(this, view);
+
+ userMessage.setIcon(R.drawable.ic_settings);
+ userMessage.setText(getString(R.string.always_on_vpn_user_message));
+ builder.setView(view)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if (doNotShowAgainCheckBox.isChecked()) {
+ saveShowAlwaysOnDialog(getContext(), false);
+ }
+ Intent intent = new Intent("android.net.vpn.SETTINGS");
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+ return builder.create();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconTextView.java b/app/src/main/java/se/leap/bitmaskclient/views/IconTextView.java
new file mode 100644
index 00000000..0af33c68
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/views/IconTextView.java
@@ -0,0 +1,96 @@
+package se.leap.bitmaskclient.views;
+
+
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.AppCompatTextView;
+import android.text.Spannable;
+import android.text.style.ImageSpan;
+import android.util.AttributeSet;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class IconTextView extends AppCompatTextView {
+
+ private int imageResource = 0;
+ /**
+ * Regex pattern that looks for embedded images of the format: [img src=imageName/]
+ */
+ public static final String PATTERN = "\\Q[img src]\\E";
+
+ public IconTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public IconTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public IconTextView(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void setText(CharSequence text, BufferType type) {
+ final Spannable spannable = getTextWithImages(getContext(), text, getLineHeight(), getCurrentTextColor());
+ super.setText(spannable, BufferType.SPANNABLE);
+ }
+
+ public void setIcon(int imageResource) {
+ this.imageResource = imageResource;
+ }
+
+ private Spannable getTextWithImages(Context context, CharSequence text, int lineHeight, int colour) {
+ final Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
+ addImages(context, spannable, lineHeight, colour);
+ return spannable;
+ }
+
+ private void addImages(Context context, Spannable spannable, int lineHeight, int colour) {
+ final Pattern refImg = Pattern.compile(PATTERN);
+
+ final Matcher matcher = refImg.matcher(spannable);
+ while (matcher.find()) {
+ boolean set = true;
+ for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) {
+ if (spannable.getSpanStart(span) >= matcher.start()
+ && spannable.getSpanEnd(span) <= matcher.end()) {
+ spannable.removeSpan(span);
+ } else {
+ set = false;
+ break;
+ }
+ }
+ if (set && imageResource != 0) {
+ spannable.setSpan(makeImageSpan(context, imageResource, lineHeight, colour),
+ matcher.start(),
+ matcher.end(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ );
+ }
+ }
+ }
+
+ /**
+ * Create an ImageSpan for the given icon drawable. This also sets the image size and colour.
+ * Works best with a white, square icon because of the colouring and resizing.
+ *
+ * @param context The Android Context.
+ * @param drawableResId A drawable resource Id.
+ * @param size The desired size (i.e. width and height) of the image icon in pixels.
+ * Use the lineHeight of the TextView to make the image inline with the
+ * surrounding text.
+ * @param colour The colour (careful: NOT a resource Id) to apply to the image.
+ * @return An ImageSpan, aligned with the bottom of the text.
+ */
+ private ImageSpan makeImageSpan(Context context, int drawableResId, int size, int colour) {
+ final Drawable drawable = context.getResources().getDrawable(drawableResId);
+ drawable.mutate();
+ drawable.setColorFilter(colour, PorterDuff.Mode.MULTIPLY);
+ drawable.setBounds(0, 0, size, size);
+ return new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
+ }
+
+} \ No newline at end of file