summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java221
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/views/VpnStateImage.java16
-rw-r--r--app/src/main/res/drawable/ic_menu_color_point.pngbin0 -> 2454 bytes
-rw-r--r--app/src/main/res/drawable/ic_menu_default.pngbin0 -> 2454 bytes
-rw-r--r--docker/android-ndk/Dockerfile1
5 files changed, 163 insertions, 75 deletions
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 14c2eacf..050da415 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -25,6 +25,8 @@ import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
@@ -51,13 +53,13 @@ import android.widget.ListView;
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.FragmentManagerEnhanced;
import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.ProviderListActivity;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.fragments.AboutFragment;
+import se.leap.bitmaskclient.fragments.AlwaysOnDialog;
import se.leap.bitmaskclient.fragments.LogFragment;
import static android.content.Context.MODE_PRIVATE;
@@ -94,6 +96,7 @@ public class NavigationDrawerFragment extends Fragment {
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
+ private static final String TAG = NavigationDrawerFragment.class.getName();
/**
* Helper component that ties the action bar to the navigation drawer.
@@ -102,14 +105,15 @@ public class NavigationDrawerFragment extends Fragment {
private DrawerLayout mDrawerLayout;
private View mDrawerView;
- private ListView mDrawerSettingsListView;
private ListView mDrawerAccountsListView;
private View mFragmentContainerView;
private ArrayAdapter<String> accountListAdapter;
private DrawerSettingsAdapter settingsListAdapter;
+ private Toolbar mToolbar;
- private boolean mFromSavedInstanceState;
private boolean mUserLearnedDrawer;
+ private volatile boolean wasPaused;
+ private volatile boolean shouldCloseOnResume;
private String mTitle;
@@ -129,9 +133,6 @@ public class NavigationDrawerFragment extends Fragment {
// drawer. See PREF_USER_LEARNED_DRAWER for details.
preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
mUserLearnedDrawer = preferences.getBoolean(PREF_USER_LEARNED_DRAWER, false);
- if (savedInstanceState != null) {
- mFromSavedInstanceState = true;
- }
}
@Override
@@ -153,6 +154,22 @@ public class NavigationDrawerFragment extends Fragment {
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ wasPaused = false;
+ if (shouldCloseOnResume) {
+ closeDrawerWithDelay(2000);
+ showDottedIconWithDelay(3000);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ wasPaused = true;
+ }
+
/**
* Users of this fragment must call this method to set up the navigation drawer interactions.
*
@@ -160,70 +177,44 @@ public class NavigationDrawerFragment extends Fragment {
* @param drawerLayout The DrawerLayout containing this fragment's UI.
*/
public void setUp(int fragmentId, DrawerLayout drawerLayout) {
- AppCompatActivity activity = (AppCompatActivity) getActivity();
- ActionBar actionBar = activity.getSupportActionBar();
-
- mDrawerSettingsListView = mDrawerView.findViewById(R.id.settingsList);
- mDrawerSettingsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- selectItem(parent, position);
- }
- });
- settingsListAdapter = new DrawerSettingsAdapter(getLayoutInflater());
- if (getContext() != null) {
- settingsListAdapter.addItem(getSwitchInstance(getString(R.string.save_battery),
- getSaveBattery(getContext()),
- BATTERY_SAVER,
- new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean newStateIsChecked) {
- onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked);
- }
- }));
- }
- 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));
- if (ENABLE_DONATION) {
- settingsListAdapter.addItem(getSimpleTextInstance(getString(donate_title), DONATE));
- }
-
- mDrawerSettingsListView.setAdapter(settingsListAdapter);
-
- mDrawerAccountsListView = mDrawerView.findViewById(R.id.accountList);
- mDrawerAccountsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- selectItem(parent, position);
- }
- });
+ final AppCompatActivity activity = (AppCompatActivity) getActivity();
+ mFragmentContainerView = activity.findViewById(fragmentId);
+ mDrawerLayout = drawerLayout;
+ // set a custom shadow that overlays the main content when the drawer opens
+ mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+ mToolbar = mDrawerLayout.findViewById(R.id.toolbar);
+ final ActionBar actionBar = setupActionBar();
+ setupSettingsListAdapter();
+ setupSettingsListView();
accountListAdapter = new ArrayAdapter<>(actionBar.getThemedContext(),
R.layout.v_single_list_item,
android.R.id.text1);
+ refreshAccountListAdapter();
+ setupAccountsListView();
+ setupActionBarDrawerToggle(activity);
- createListAdapterData();
-
- mDrawerAccountsListView.setAdapter(accountListAdapter);
-
- mFragmentContainerView = activity.findViewById(fragmentId);
- mDrawerLayout = drawerLayout;
+ if (!mUserLearnedDrawer) {
+ openNavigationDrawerForFirstTimeUsers();
+ }
- // set a custom shadow that overlays the main content when the drawer opens
- mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+ // Defer code dependent on restoration of previous instance state.
+ mDrawerLayout.post(new Runnable() {
+ @Override
+ public void run() {
+ mDrawerToggle.syncState();
+ }
+ });
+ mDrawerLayout.addDrawerListener(mDrawerToggle);
+ }
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setHomeButtonEnabled(true);
+ private void setupActionBarDrawerToggle(final AppCompatActivity activity) {
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
mDrawerToggle = new ActionBarDrawerToggle(
- getActivity(),
+ activity,
mDrawerLayout,
- (Toolbar) drawerLayout.findViewById(R.id.toolbar),
+ mToolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
) {
@@ -234,7 +225,7 @@ public class NavigationDrawerFragment extends Fragment {
return;
}
- getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ activity.invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
@Override
@@ -249,27 +240,108 @@ public class NavigationDrawerFragment extends Fragment {
// the navigation drawer automatically in the future.
mUserLearnedDrawer = true;
preferences.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
+ mToolbar.setNavigationIcon(R.drawable.ic_menu_default);
}
- getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ activity.invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
};
+ }
+
+ private void setupAccountsListView() {
+ mDrawerAccountsListView = mDrawerView.findViewById(R.id.accountList);
+ mDrawerAccountsListView.setAdapter(accountListAdapter);
+ mDrawerAccountsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectItem(parent, position);
+ }
+ });
+ }
+
+ private void setupSettingsListView() {
+ ListView drawerSettingsListView = mDrawerView.findViewById(R.id.settingsList);
+ drawerSettingsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectItem(parent, position);
+ }
+ });
+ drawerSettingsListView.setAdapter(settingsListAdapter);
+ }
+
+ private void setupSettingsListAdapter() {
+ settingsListAdapter = new DrawerSettingsAdapter(getLayoutInflater());
+ if (getContext() != null) {
+ settingsListAdapter.addItem(getSwitchInstance(getString(R.string.save_battery),
+ getSaveBattery(getContext()),
+ BATTERY_SAVER,
+ new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean newStateIsChecked) {
+ onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked);
+ }
+ }));
+ }
+ 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));
+ if (ENABLE_DONATION) {
+ settingsListAdapter.addItem(getSimpleTextInstance(getString(donate_title), DONATE));
+ }
+ settingsListAdapter.addItem(getSimpleTextInstance(getString(about_fragment_title), ABOUT));
+ }
+
+ private ActionBar setupActionBar() {
+ AppCompatActivity activity = (AppCompatActivity) getActivity();
+ activity.setSupportActionBar(mToolbar);
+ final ActionBar actionBar = activity.getSupportActionBar();
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setHomeButtonEnabled(true);
+ return actionBar;
+ }
- // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
- // per the navigation drawer design guidelines.
- if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
- mDrawerLayout.openDrawer(mFragmentContainerView);
+ private void openNavigationDrawerForFirstTimeUsers() {
+ if (mUserLearnedDrawer) {
+ return;
}
- // Defer code dependent on restoration of previous instance state.
- mDrawerLayout.post(new Runnable() {
+ mDrawerLayout.openDrawer(mFragmentContainerView, false);
+ closeDrawerWithDelay(2000);
+ showDottedIconWithDelay(3000);
+
+ }
+
+ private void showDottedIconWithDelay(long delay) {
+ final Handler navigationDrawerHandler = new Handler();
+ navigationDrawerHandler.postDelayed(new Runnable() {
@Override
public void run() {
- mDrawerToggle.syncState();
+ if (!wasPaused) {
+ mToolbar.setNavigationIcon(R.drawable.ic_menu_color_point);
+ mToolbar.playSoundEffect(android.view.SoundEffectConstants.CLICK);
+ }
+
}
- });
- mDrawerLayout.addDrawerListener(mDrawerToggle);
+ }, delay);
+ }
+
+ @NonNull
+ private void closeDrawerWithDelay(long delay) {
+ final Handler navigationDrawerHandler = new Handler();
+ navigationDrawerHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!wasPaused) {
+ mDrawerLayout.closeDrawer(mFragmentContainerView, true);
+ } else {
+ shouldCloseOnResume = true;
+ }
+ }
+ }, delay);
}
private void selectItem(AdapterView<?> list, int position) {
@@ -372,7 +444,6 @@ public class NavigationDrawerFragment extends Fragment {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
-
return super.onOptionsItemSelected(item);
}
@@ -436,7 +507,7 @@ public class NavigationDrawerFragment extends Fragment {
arguments.putParcelable(PROVIDER_KEY, currentProvider);
fragment.setArguments(arguments);
} else {
- Log.d("Drawer", String.format("Selected position %d", position));
+ Log.d(TAG, String.format("Selected position %d", position));
DrawerSettingsItem settingsItem = settingsListAdapter.getItem(position);
switch (settingsItem.getItemType()) {
case SWITCH_PROVIDER:
@@ -487,12 +558,12 @@ public class NavigationDrawerFragment extends Fragment {
public void refresh() {
- createListAdapterData();
+ refreshAccountListAdapter();
accountListAdapter.notifyDataSetChanged();
mDrawerAccountsListView.setAdapter(accountListAdapter);
}
- private void createListAdapterData() {
+ private void refreshAccountListAdapter() {
accountListAdapter.clear();
String providerName = ConfigHelper.getProviderName(preferences);
if (providerName == null) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/views/VpnStateImage.java b/app/src/main/java/se/leap/bitmaskclient/views/VpnStateImage.java
index 2efd83d6..86761642 100644
--- a/app/src/main/java/se/leap/bitmaskclient/views/VpnStateImage.java
+++ b/app/src/main/java/se/leap/bitmaskclient/views/VpnStateImage.java
@@ -1,3 +1,19 @@
+/**
+ * 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 <http://www.gnu.org/licenses/>.
+ */
package se.leap.bitmaskclient.views;
import android.content.Context;
diff --git a/app/src/main/res/drawable/ic_menu_color_point.png b/app/src/main/res/drawable/ic_menu_color_point.png
new file mode 100644
index 00000000..ef4b0e51
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_color_point.png
Binary files differ
diff --git a/app/src/main/res/drawable/ic_menu_default.png b/app/src/main/res/drawable/ic_menu_default.png
new file mode 100644
index 00000000..e0d29163
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_default.png
Binary files differ
diff --git a/docker/android-ndk/Dockerfile b/docker/android-ndk/Dockerfile
index 2872d98f..8e7a124b 100644
--- a/docker/android-ndk/Dockerfile
+++ b/docker/android-ndk/Dockerfile
@@ -37,3 +37,4 @@ ENV PATH ${PATH}:${ANDROID_NDK_HOME}
# Accept all licenses
RUN yes | sdkmanager --licenses
RUN sdkmanager --list
+