summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java284
-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
4 files changed, 192 insertions, 108 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..be4bdf99 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,24 +96,28 @@ 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();
+ public static final int TWO_SECONDS = 2000;
+ public static final int THREE_SECONDS = 3500;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
- private ActionBarDrawerToggle mDrawerToggle;
+ private ActionBarDrawerToggle drawerToggle;
- private DrawerLayout mDrawerLayout;
- private View mDrawerView;
- private ListView mDrawerSettingsListView;
- private ListView mDrawerAccountsListView;
- private View mFragmentContainerView;
+ private DrawerLayout drawerLayout;
+ private View drawerView;
+ private ListView drawerAccountsListView;
+ private View fragmentContainerView;
private ArrayAdapter<String> accountListAdapter;
private DrawerSettingsAdapter settingsListAdapter;
+ private Toolbar toolbar;
- private boolean mFromSavedInstanceState;
- private boolean mUserLearnedDrawer;
+ private boolean userLearnedDrawer;
+ private volatile boolean wasPaused;
+ private volatile boolean shouldCloseOnResume;
- private String mTitle;
+ private String title;
private SharedPreferences preferences;
@@ -119,38 +125,48 @@ public class NavigationDrawerFragment extends Fragment {
private boolean showEnableExperimentalFeature = false;
AlertDialog alertDialog;
- public NavigationDrawerFragment() {
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Read in the flag indicating whether or not the user has demonstrated awareness of the
+ // Reads in the flag indicating whether or not the user has demonstrated awareness of the
// 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;
- }
+ userLearnedDrawer = preferences.getBoolean(PREF_USER_LEARNED_DRAWER, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- // Indicate that this fragment would like to influence the set of actions in the action bar.
+ // Indicates that this fragment would like to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- mDrawerView = inflater.inflate(R.layout.f_drawer_main, container, false);
+ drawerView = inflater.inflate(R.layout.f_drawer_main, container, false);
restoreFromSavedInstance(savedInstanceState);
- return mDrawerView;
+ return drawerView;
}
public boolean isDrawerOpen() {
- return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
+ return drawerLayout != null && drawerLayout.isDrawerOpen(fragmentContainerView);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ wasPaused = false;
+ if (shouldCloseOnResume) {
+ closeDrawerWithDelay();
+ showDottedIconWithDelay();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ wasPaused = true;
}
/**
@@ -160,70 +176,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();
+ fragmentContainerView = activity.findViewById(fragmentId);
+ this.drawerLayout = drawerLayout;
+ // set a custom shadow that overlays the main content when the drawer opens
+ this.drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+ toolbar = this.drawerLayout.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 (!userLearnedDrawer) {
+ 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.
+ this.drawerLayout.post(new Runnable() {
+ @Override
+ public void run() {
+ drawerToggle.syncState();
+ }
+ });
+ this.drawerLayout.addDrawerListener(drawerToggle);
+ }
- 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(),
- mDrawerLayout,
- (Toolbar) drawerLayout.findViewById(R.id.toolbar),
+ drawerToggle = new ActionBarDrawerToggle(
+ activity,
+ drawerLayout,
+ toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
) {
@@ -233,8 +223,7 @@ public class NavigationDrawerFragment extends Fragment {
if (!isAdded()) {
return;
}
-
- getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ activity.invalidateOptionsMenu();
}
@Override
@@ -244,40 +233,120 @@ public class NavigationDrawerFragment extends Fragment {
return;
}
- if (!mUserLearnedDrawer) {
+ if (!userLearnedDrawer) {
// The user manually opened the drawer; store this flag to prevent auto-showing
// the navigation drawer automatically in the future.
- mUserLearnedDrawer = true;
+ userLearnedDrawer = true;
preferences.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
+ toolbar.setNavigationIcon(R.drawable.ic_menu_default);
}
-
- getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
+ activity.invalidateOptionsMenu();
}
};
+ }
+
+ private void setupAccountsListView() {
+ drawerAccountsListView = drawerView.findViewById(R.id.accountList);
+ drawerAccountsListView.setAdapter(accountListAdapter);
+ drawerAccountsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectItem(parent, position);
+ }
+ });
+ }
- // 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 setupSettingsListView() {
+ ListView drawerSettingsListView = drawerView.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));
+ }
- // Defer code dependent on restoration of previous instance state.
- mDrawerLayout.post(new Runnable() {
+ private ActionBar setupActionBar() {
+ AppCompatActivity activity = (AppCompatActivity) getActivity();
+ activity.setSupportActionBar(toolbar);
+ final ActionBar actionBar = activity.getSupportActionBar();
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setHomeButtonEnabled(true);
+ return actionBar;
+ }
+
+ private void openNavigationDrawerForFirstTimeUsers() {
+ if (userLearnedDrawer) {
+ return;
+ }
+
+ drawerLayout.openDrawer(fragmentContainerView, false);
+ closeDrawerWithDelay();
+ showDottedIconWithDelay();
+
+ }
+
+ private void showDottedIconWithDelay() {
+ final Handler navigationDrawerHandler = new Handler();
+ navigationDrawerHandler.postDelayed(new Runnable() {
@Override
public void run() {
- mDrawerToggle.syncState();
+ if (!wasPaused) {
+ toolbar.setNavigationIcon(R.drawable.ic_menu_color_point);
+ toolbar.playSoundEffect(android.view.SoundEffectConstants.CLICK);
+ }
+
}
- });
- mDrawerLayout.addDrawerListener(mDrawerToggle);
+ }, THREE_SECONDS);
+ }
+ @NonNull
+ private void closeDrawerWithDelay() {
+ final Handler navigationDrawerHandler = new Handler();
+ navigationDrawerHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!wasPaused) {
+ drawerLayout.closeDrawer(fragmentContainerView, true);
+ } else {
+ shouldCloseOnResume = true;
+ }
+
+ }
+ }, TWO_SECONDS);
}
private void selectItem(AdapterView<?> list, int position) {
if (list != null) {
((ListView) list).setItemChecked(position, true);
}
- if (mDrawerLayout != null) {
- mDrawerLayout.closeDrawer(mFragmentContainerView);
+ if (drawerLayout != null) {
+ drawerLayout.closeDrawer(fragmentContainerView);
}
onTextItemSelected(list, position);
}
@@ -356,12 +425,12 @@ public class NavigationDrawerFragment extends Fragment {
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
- mDrawerToggle.onConfigurationChanged(newConfig);
+ drawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (mDrawerLayout != null && isDrawerOpen()) {
+ if (drawerLayout != null && isDrawerOpen()) {
showGlobalContextActionBar();
}
super.onCreateOptionsMenu(menu, inflater);
@@ -369,10 +438,9 @@ public class NavigationDrawerFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (mDrawerToggle.onOptionsItemSelected(item)) {
+ if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
-
return super.onOptionsItemSelected(item);
}
@@ -427,8 +495,8 @@ public class NavigationDrawerFragment extends Fragment {
Fragment fragment = null;
String fragmentTag = null;
- if (parent == mDrawerAccountsListView) {
- mTitle = getString(R.string.vpn_fragment_title);
+ if (parent == drawerAccountsListView) {
+ title = getString(R.string.vpn_fragment_title);
fragment = new EipFragment();
fragmentTag = EipFragment.TAG;
Bundle arguments = new Bundle();
@@ -436,18 +504,18 @@ 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:
getActivity().startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
break;
case LOG:
- mTitle = getString(log_fragment_title);
+ title = getString(log_fragment_title);
fragment = new LogFragment();
break;
case ABOUT:
- mTitle = getString(about_fragment_title);
+ title = getString(about_fragment_title);
fragment = new AboutFragment();
break;
case ALWAYS_ON:
@@ -481,18 +549,18 @@ public class NavigationDrawerFragment extends Fragment {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(true);
- actionBar.setSubtitle(mTitle);
+ actionBar.setSubtitle(title);
}
}
public void refresh() {
- createListAdapterData();
+ refreshAccountListAdapter();
accountListAdapter.notifyDataSetChanged();
- mDrawerAccountsListView.setAdapter(accountListAdapter);
+ drawerAccountsListView.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