set up Panic preference to choose apps to uninstall on trigger
This commit is contained in:
parent
3812331166
commit
515b5b08f0
@ -104,6 +104,10 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".views.panic.SelectInstalledAppsActivity"
|
||||||
|
android:parentActivityName=".views.panic.PanicPreferencesActivity"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".views.panic.PanicResponderActivity"
|
android:name=".views.panic.PanicResponderActivity"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
|
@ -8,6 +8,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.LightingColorFilter;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -20,15 +21,18 @@ import android.support.v7.app.AlertDialog;
|
|||||||
import android.support.v7.preference.CheckBoxPreference;
|
import android.support.v7.preference.CheckBoxPreference;
|
||||||
import android.support.v7.preference.ListPreference;
|
import android.support.v7.preference.ListPreference;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.PreferenceCategory;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import info.guardianproject.panic.Panic;
|
import info.guardianproject.panic.Panic;
|
||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||||
import org.fdroid.fdroid.views.hiding.HidingManager;
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class PanicPreferencesFragment extends PreferenceFragment
|
public class PanicPreferencesFragment extends PreferenceFragment
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
@ -39,6 +43,7 @@ public class PanicPreferencesFragment extends PreferenceFragment
|
|||||||
private ListPreference prefApp;
|
private ListPreference prefApp;
|
||||||
private CheckBoxPreference prefExit;
|
private CheckBoxPreference prefExit;
|
||||||
private CheckBoxPreference prefHide;
|
private CheckBoxPreference prefHide;
|
||||||
|
private PreferenceCategory categoryAppsToUninstall;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
@ -49,6 +54,7 @@ public class PanicPreferencesFragment extends PreferenceFragment
|
|||||||
prefApp = (ListPreference) findPreference(PREF_APP);
|
prefApp = (ListPreference) findPreference(PREF_APP);
|
||||||
prefHide = (CheckBoxPreference) findPreference(Preferences.PREF_PANIC_HIDE);
|
prefHide = (CheckBoxPreference) findPreference(Preferences.PREF_PANIC_HIDE);
|
||||||
prefHide.setTitle(getString(R.string.panic_hide_title, getString(R.string.app_name)));
|
prefHide.setTitle(getString(R.string.panic_hide_title, getString(R.string.app_name)));
|
||||||
|
categoryAppsToUninstall = (PreferenceCategory) findPreference("pref_panic_apps_to_uninstall");
|
||||||
|
|
||||||
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
||||||
// the necessary action should have been performed by the check already
|
// the necessary action should have been performed by the check already
|
||||||
@ -86,6 +92,48 @@ public class PanicPreferencesFragment extends PreferenceFragment
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
if (!PrivilegedInstaller.isDefault(getActivity())) {
|
||||||
|
getPreferenceScreen().removePreference(categoryAppsToUninstall);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showWipeList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showWipeList() {
|
||||||
|
Intent intent = new Intent(getActivity(), SelectInstalledAppsActivity.class);
|
||||||
|
intent.setAction(Intent.ACTION_MAIN);
|
||||||
|
Set<String> wipeSet = Preferences.get().getPanicWipeSet();
|
||||||
|
categoryAppsToUninstall.removeAll();
|
||||||
|
if (Panic.PACKAGE_NAME_NONE.equals(prefApp.getValue())) {
|
||||||
|
categoryAppsToUninstall.setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
categoryAppsToUninstall.setEnabled(true);
|
||||||
|
if (wipeSet.size() > 0) {
|
||||||
|
for (String packageName : wipeSet) {
|
||||||
|
Preference preference = new Preference(getActivity());
|
||||||
|
preference.setSingleLineTitle(true);
|
||||||
|
preference.setIntent(intent);
|
||||||
|
categoryAppsToUninstall.addPreference(preference);
|
||||||
|
try {
|
||||||
|
preference.setTitle(pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)));
|
||||||
|
preference.setIcon(pm.getApplicationIcon(packageName));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
preference.setTitle(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Preference preference = new Preference(getActivity());
|
||||||
|
preference.setIntent(intent);
|
||||||
|
Drawable icon = getResources().getDrawable(R.drawable.ic_add_circle_outline_white);
|
||||||
|
icon.setColorFilter(new LightingColorFilter(0, getResources().getColor(R.color.swap_light_grey_icon)));
|
||||||
|
preference.setSingleLineTitle(true);
|
||||||
|
preference.setTitle(R.string.panic_add_apps_to_uninstall);
|
||||||
|
preference.setIcon(icon);
|
||||||
|
categoryAppsToUninstall.addPreference(preference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -156,6 +204,7 @@ public class PanicPreferencesFragment extends PreferenceFragment
|
|||||||
|
|
||||||
// disable destructive panic actions
|
// disable destructive panic actions
|
||||||
prefHide.setEnabled(false);
|
prefHide.setEnabled(false);
|
||||||
|
showWipeList();
|
||||||
} else {
|
} else {
|
||||||
// try to display connected panic app
|
// try to display connected panic app
|
||||||
try {
|
try {
|
||||||
@ -163,6 +212,7 @@ public class PanicPreferencesFragment extends PreferenceFragment
|
|||||||
prefApp.setSummary(pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)));
|
prefApp.setSummary(pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)));
|
||||||
prefApp.setIcon(pm.getApplicationIcon(packageName));
|
prefApp.setIcon(pm.getApplicationIcon(packageName));
|
||||||
prefHide.setEnabled(true);
|
prefHide.setEnabled(true);
|
||||||
|
showWipeList();
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
// revert back to no app, just to be safe
|
// revert back to no app, just to be safe
|
||||||
PanicResponder.setTriggerPackageName(getActivity(), Panic.PACKAGE_NAME_NONE);
|
PanicResponder.setTriggerPackageName(getActivity(), Panic.PACKAGE_NAME_NONE);
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.fdroid.fdroid.views.panic;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||||
|
import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SelectInstalledAppListAdapter extends InstalledAppListAdapter {
|
||||||
|
private final Set<String> selectedApps;
|
||||||
|
|
||||||
|
SelectInstalledAppListAdapter(Activity activity) {
|
||||||
|
super(activity);
|
||||||
|
Preferences prefs = Preferences.get();
|
||||||
|
selectedApps = prefs.getPanicWipeSet();
|
||||||
|
prefs.setPanicTmpSelectedSet(selectedApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public InstalledAppListItemController onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = activity.getLayoutInflater().inflate(R.layout.installed_app_list_item, parent, false);
|
||||||
|
return new SelectInstalledAppListItemController(activity, view, selectedApps);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package org.fdroid.fdroid.views.panic;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.View;
|
||||||
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
|
import org.fdroid.fdroid.data.App;
|
||||||
|
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||||
|
import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the currently installed apps as a selectable list.
|
||||||
|
*/
|
||||||
|
public class SelectInstalledAppListItemController extends InstalledAppListItemController {
|
||||||
|
|
||||||
|
private final Set<String> selectedApps;
|
||||||
|
|
||||||
|
public SelectInstalledAppListItemController(Activity activity, View itemView, Set<String> selectedApps) {
|
||||||
|
super(activity, itemView);
|
||||||
|
this.selectedApps = selectedApps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected AppListItemState getCurrentViewState(
|
||||||
|
@NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) {
|
||||||
|
return new AppListItemState(app).setCheckBoxStatus(selectedApps.contains(app.packageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActionButtonPressed(App app) {
|
||||||
|
super.onActionButtonPressed(app);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
|
||||||
|
* Copyright (C) 2009 Roberto Jacinto, roberto.jacinto@caixamagica.pt
|
||||||
|
*
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.fdroid.fdroid.views.panic;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.LightingColorFilter;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.LoaderManager;
|
||||||
|
import android.support.v4.content.CursorLoader;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
|
import org.fdroid.fdroid.data.Schema;
|
||||||
|
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||||
|
|
||||||
|
public class SelectInstalledAppsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
|
private InstalledAppListAdapter adapter;
|
||||||
|
private RecyclerView appList;
|
||||||
|
private TextView emptyState;
|
||||||
|
private int checkId;
|
||||||
|
|
||||||
|
private Preferences prefs;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
((FDroidApp) getApplication()).applyTheme(this);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.installed_apps_layout);
|
||||||
|
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
toolbar.setTitle(getString(R.string.panic_add_apps_to_uninstall));
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
adapter = new SelectInstalledAppListAdapter(this);
|
||||||
|
|
||||||
|
appList = findViewById(R.id.app_list);
|
||||||
|
appList.setHasFixedSize(true);
|
||||||
|
appList.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
appList.setAdapter(adapter);
|
||||||
|
|
||||||
|
emptyState = findViewById(R.id.empty_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
prefs = Preferences.get();
|
||||||
|
|
||||||
|
// Starts a new or restarts an existing Loader in this manager
|
||||||
|
getSupportLoaderManager().restartLoader(0, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
|
return new CursorLoader(
|
||||||
|
this,
|
||||||
|
AppProvider.getInstalledUri(),
|
||||||
|
Schema.AppMetadataTable.Cols.ALL,
|
||||||
|
null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
|
||||||
|
adapter.setApps(cursor);
|
||||||
|
|
||||||
|
if (adapter.getItemCount() == 0) {
|
||||||
|
appList.setVisibility(View.GONE);
|
||||||
|
emptyState.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
appList.setVisibility(View.VISIBLE);
|
||||||
|
emptyState.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
|
||||||
|
adapter.setApps(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuItem menuItem = menu.add(R.string.menu_select_for_wipe);
|
||||||
|
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||||
|
checkId = menuItem.getItemId();
|
||||||
|
if (FDroidApp.isAppThemeLight()) {
|
||||||
|
Resources resources = getResources();
|
||||||
|
Drawable icon = resources.getDrawable(R.drawable.check);
|
||||||
|
icon.setColorFilter(new LightingColorFilter(0xffffffff, resources.getColor(android.R.color.white)));
|
||||||
|
menuItem.setIcon(icon);
|
||||||
|
} else {
|
||||||
|
menuItem.setIcon(R.drawable.check);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ApplySharedPref")
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
finish();
|
||||||
|
if (item.getItemId() == checkId) {
|
||||||
|
prefs.setPanicWipeSet(prefs.getPanicTmpSelectedSet());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
8
app/src/full/res/drawable/check.xml
Normal file
8
app/src/full/res/drawable/check.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<!-- drawable/check.xml -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" />
|
||||||
|
</vector>
|
@ -28,4 +28,10 @@
|
|||||||
|
|
||||||
</android.support.v7.preference.PreferenceCategory>
|
</android.support.v7.preference.PreferenceCategory>
|
||||||
|
|
||||||
|
<android.support.v7.preference.PreferenceCategory
|
||||||
|
android:key="pref_panic_apps_to_uninstall"
|
||||||
|
android:title="@string/panic_apps_to_uninstall">
|
||||||
|
|
||||||
|
</android.support.v7.preference.PreferenceCategory>
|
||||||
|
|
||||||
</android.support.v7.preference.PreferenceScreen>
|
</android.support.v7.preference.PreferenceScreen>
|
@ -35,10 +35,12 @@ import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
|||||||
import org.fdroid.fdroid.net.ConnectivityMonitorService;
|
import org.fdroid.fdroid.net.ConnectivityMonitorService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +109,8 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
public static final String PREF_PREVENT_SCREENSHOTS = "preventScreenshots";
|
public static final String PREF_PREVENT_SCREENSHOTS = "preventScreenshots";
|
||||||
public static final String PREF_PANIC_EXIT = "pref_panic_exit";
|
public static final String PREF_PANIC_EXIT = "pref_panic_exit";
|
||||||
public static final String PREF_PANIC_HIDE = "pref_panic_hide";
|
public static final String PREF_PANIC_HIDE = "pref_panic_hide";
|
||||||
|
public static final String PREF_PANIC_WIPE_SET = "panicWipeSet";
|
||||||
|
public static final String PREF_PANIC_TMP_SELECTED_SET = "panicTmpSelectedSet";
|
||||||
public static final String PREF_HIDE_ON_LONG_PRESS_SEARCH = "hideOnLongPressSearch";
|
public static final String PREF_HIDE_ON_LONG_PRESS_SEARCH = "hideOnLongPressSearch";
|
||||||
public static final String PREF_HIDE_ALL_NOTIFICATIONS = "hideAllNotifications";
|
public static final String PREF_HIDE_ALL_NOTIFICATIONS = "hideAllNotifications";
|
||||||
public static final String PREF_SEND_VERSION_AND_UUID_TO_SERVERS = "sendVersionAndUUIDToServers";
|
public static final String PREF_SEND_VERSION_AND_UUID_TO_SERVERS = "sendVersionAndUUIDToServers";
|
||||||
@ -515,6 +519,22 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
return preferences.getBoolean(PREF_HIDE_ON_LONG_PRESS_SEARCH, IGNORED_B);
|
return preferences.getBoolean(PREF_HIDE_ON_LONG_PRESS_SEARCH, IGNORED_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getPanicTmpSelectedSet() {
|
||||||
|
return preferences.getStringSet(Preferences.PREF_PANIC_TMP_SELECTED_SET, Collections.<String>emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanicTmpSelectedSet(Set<String> selectedSet) {
|
||||||
|
preferences.edit().putStringSet(Preferences.PREF_PANIC_TMP_SELECTED_SET, selectedSet).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getPanicWipeSet() {
|
||||||
|
return preferences.getStringSet(Preferences.PREF_PANIC_WIPE_SET, Collections.<String>emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPanicWipeSet(Set<String> selectedSet) {
|
||||||
|
preferences.edit().putStringSet(Preferences.PREF_PANIC_WIPE_SET, selectedSet).apply();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference for whitelabel builds that are meant to be entirely controlled
|
* Preference for whitelabel builds that are meant to be entirely controlled
|
||||||
* by the server, without user interaction, e.g. "appliances".
|
* by the server, without user interaction, e.g. "appliances".
|
||||||
|
@ -22,15 +22,15 @@ import android.text.TextUtils;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewOutlineProvider;
|
import android.view.ViewOutlineProvider;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
|
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
@ -45,6 +45,7 @@ import org.fdroid.fdroid.views.updates.UpdatesAdapter;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supports the following layouts:
|
* Supports the following layouts:
|
||||||
@ -64,6 +65,8 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
private static final String TAG = "AppListItemController";
|
private static final String TAG = "AppListItemController";
|
||||||
|
|
||||||
|
private static Preferences prefs;
|
||||||
|
|
||||||
protected final Activity activity;
|
protected final Activity activity;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -97,6 +100,9 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final Button secondaryButton;
|
private final Button secondaryButton;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final CheckBox checkBox;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private App currentApp;
|
private App currentApp;
|
||||||
|
|
||||||
@ -107,6 +113,9 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
public AppListItemController(final Activity activity, View itemView) {
|
public AppListItemController(final Activity activity, View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
|
if (prefs == null) {
|
||||||
|
prefs = Preferences.get();
|
||||||
|
}
|
||||||
|
|
||||||
installButton = (ImageView) itemView.findViewById(R.id.install);
|
installButton = (ImageView) itemView.findViewById(R.id.install);
|
||||||
if (installButton != null) {
|
if (installButton != null) {
|
||||||
@ -145,6 +154,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
cancelButton = (ImageButton) itemView.findViewById(R.id.cancel_button);
|
cancelButton = (ImageButton) itemView.findViewById(R.id.cancel_button);
|
||||||
actionButton = (Button) itemView.findViewById(R.id.action_button);
|
actionButton = (Button) itemView.findViewById(R.id.action_button);
|
||||||
secondaryButton = (Button) itemView.findViewById(R.id.secondary_button);
|
secondaryButton = (Button) itemView.findViewById(R.id.secondary_button);
|
||||||
|
checkBox = itemView.findViewById(R.id.checkbox);
|
||||||
|
|
||||||
if (actionButton != null) {
|
if (actionButton != null) {
|
||||||
actionButton.setEnabled(true);
|
actionButton.setEnabled(true);
|
||||||
@ -220,9 +230,9 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Override to respond to the user swiping an app to dismiss it from the list.
|
* Override to respond to the user swiping an app to dismiss it from the list.
|
||||||
|
*
|
||||||
* @param app The app that was swiped away
|
* @param app The app that was swiped away
|
||||||
* @param updatesAdapter The adapter. Can be used for refreshing the adapter with adapter.refreshStatuses().
|
* @param updatesAdapter The adapter. Can be used for refreshing the adapter with adapter.refreshStatuses().
|
||||||
*
|
|
||||||
* @see #canDismiss() This must also be overridden and should return true.
|
* @see #canDismiss() This must also be overridden and should return true.
|
||||||
*/
|
*/
|
||||||
protected void onDismissApp(@NonNull App app, UpdatesAdapter updatesAdapter) {
|
protected void onDismissApp(@NonNull App app, UpdatesAdapter updatesAdapter) {
|
||||||
@ -328,6 +338,18 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
secondaryStatus.setText(statusText);
|
secondaryStatus.setText(statusText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkBox != null) {
|
||||||
|
if (viewState.shouldShowCheckBox()) {
|
||||||
|
itemView.setOnClickListener(selectInstalledAppListener);
|
||||||
|
checkBox.setChecked(viewState.isCheckBoxChecked());
|
||||||
|
checkBox.setVisibility(View.VISIBLE);
|
||||||
|
status.setVisibility(View.GONE);
|
||||||
|
secondaryStatus.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
checkBox.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -533,4 +555,18 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
InstallManagerService.cancel(activity, currentStatus.getCanonicalUrl());
|
InstallManagerService.cancel(activity, currentStatus.getCanonicalUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final View.OnClickListener selectInstalledAppListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Set<String> wipeSet = prefs.getPanicTmpSelectedSet();
|
||||||
|
checkBox.toggle();
|
||||||
|
if (checkBox.isChecked()) {
|
||||||
|
wipeSet.add(currentApp.packageName);
|
||||||
|
} else {
|
||||||
|
wipeSet.remove(currentApp.packageName);
|
||||||
|
}
|
||||||
|
prefs.setPanicTmpSelectedSet(wipeSet);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package org.fdroid.fdroid.views.apps;
|
|||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dumb model which is used to specify what should/should not be shown in an {@link AppListItemController}.
|
* A dumb model which is used to specify what should/should not be shown in an {@link AppListItemController}.
|
||||||
|
*
|
||||||
* @see AppListItemController and its subclasses.
|
* @see AppListItemController and its subclasses.
|
||||||
*/
|
*/
|
||||||
public class AppListItemState {
|
public class AppListItemState {
|
||||||
@ -20,6 +20,8 @@ public class AppListItemState {
|
|||||||
private int progressCurrent = -1;
|
private int progressCurrent = -1;
|
||||||
private int progressMax = -1;
|
private int progressMax = -1;
|
||||||
private boolean showInstallButton;
|
private boolean showInstallButton;
|
||||||
|
private boolean showCheckBox;
|
||||||
|
private boolean isCheckBoxChecked;
|
||||||
|
|
||||||
public AppListItemState(@NonNull App app) {
|
public AppListItemState(@NonNull App app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@ -63,6 +65,9 @@ public class AppListItemState {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public CharSequence getMainText() {
|
public CharSequence getMainText() {
|
||||||
|
if (showCheckBox) {
|
||||||
|
return app.name;
|
||||||
|
}
|
||||||
return mainText != null
|
return mainText != null
|
||||||
? mainText
|
? mainText
|
||||||
: Utils.formatAppNameAndSummary(app.name, app.summary);
|
: Utils.formatAppNameAndSummary(app.name, app.summary);
|
||||||
@ -113,4 +118,23 @@ public class AppListItemState {
|
|||||||
public CharSequence getSecondaryStatusText() {
|
public CharSequence getSecondaryStatusText() {
|
||||||
return secondaryStatusText;
|
return secondaryStatusText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean shouldShowCheckBox() {
|
||||||
|
return showCheckBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCheckBoxChecked() {
|
||||||
|
return isCheckBoxChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the {@link android.widget.CheckBox} display and set the on/off status
|
||||||
|
* e.g. {@link android.widget.CheckBox#isChecked()}
|
||||||
|
*/
|
||||||
|
public AppListItemState setCheckBoxStatus(boolean checked) {
|
||||||
|
this.showCheckBox = true;
|
||||||
|
this.isCheckBoxChecked = checked;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,14 @@ import org.fdroid.fdroid.R;
|
|||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
import org.fdroid.fdroid.data.Schema;
|
import org.fdroid.fdroid.data.Schema;
|
||||||
|
|
||||||
class InstalledAppListAdapter extends RecyclerView.Adapter<InstalledAppListItemController> {
|
public class InstalledAppListAdapter extends RecyclerView.Adapter<InstalledAppListItemController> {
|
||||||
|
|
||||||
private final Activity activity;
|
protected final Activity activity;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Cursor cursor;
|
private Cursor cursor;
|
||||||
|
|
||||||
InstalledAppListAdapter(Activity activity) {
|
protected InstalledAppListAdapter(Activity activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
setHasStableIds(true);
|
setHasStableIds(true);
|
||||||
}
|
}
|
||||||
|
@ -71,4 +71,14 @@
|
|||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp" />
|
android:layout_marginLeft="8dp" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/checkbox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/icon"
|
||||||
|
android:clickable="false"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
@ -206,6 +206,7 @@ This often occurs with apps installed via Google Play or other sources, if they
|
|||||||
<string name="menu_install">Install</string>
|
<string name="menu_install">Install</string>
|
||||||
<!-- This is a button label, it must be the right size, or the layout gets messed up. It should ideally be 10-20 characters. -->
|
<!-- This is a button label, it must be the right size, or the layout gets messed up. It should ideally be 10-20 characters. -->
|
||||||
<string name="menu_uninstall">Uninstall</string>
|
<string name="menu_uninstall">Uninstall</string>
|
||||||
|
<string name="menu_select_for_wipe">Select for wipe</string>
|
||||||
<string name="menu_ignore_all">Ignore All Updates</string>
|
<string name="menu_ignore_all">Ignore All Updates</string>
|
||||||
<string name="menu_ignore_this">Ignore This Update</string>
|
<string name="menu_ignore_this">Ignore This Update</string>
|
||||||
<string name="menu_website">Website</string>
|
<string name="menu_website">Website</string>
|
||||||
@ -323,9 +324,12 @@ This often occurs with apps installed via Google Play or other sources, if they
|
|||||||
<!-- "panic button" is a well known concept in English, it is good to find a similar metaphor in your language -->
|
<!-- "panic button" is a well known concept in English, it is good to find a similar metaphor in your language -->
|
||||||
<string name="panic_settings">Panic button settings</string>
|
<string name="panic_settings">Panic button settings</string>
|
||||||
<string name="panic_settings_summary">Actions to be taken in case of emergency</string>
|
<string name="panic_settings_summary">Actions to be taken in case of emergency</string>
|
||||||
<string name="panic_exit_title">Exit App</string>
|
<string name="panic_exit_title">Exit app</string>
|
||||||
<string name="panic_exit_summary">App will be closed </string>
|
<string name="panic_exit_summary">This app will be closed</string>
|
||||||
<string name="panic_destructive_actions">Destructive Actions</string>
|
<string name="panic_destructive_actions">Destructive Actions</string>
|
||||||
|
<string name="panic_will_be_wiped">Will be uninstalled and all data deleted</string>
|
||||||
|
<string name="panic_apps_to_uninstall">Apps to be uninstalled and all data wiped</string>
|
||||||
|
<string name="panic_add_apps_to_uninstall">Add apps to be uninstalled and wiped</string>
|
||||||
<string name="panic_hide_title">Hide %s</string>
|
<string name="panic_hide_title">Hide %s</string>
|
||||||
<string name="panic_hide_summary">App will hide itself</string>
|
<string name="panic_hide_summary">App will hide itself</string>
|
||||||
<string name="panic_hide_warning_title">Remember how to restore</string>
|
<string name="panic_hide_warning_title">Remember how to restore</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user