Skip to content
This repository has been archived by the owner on Mar 27, 2020. It is now read-only.

Commit

Permalink
show all Panic Responder apps so the user can enable/disable them
Browse files Browse the repository at this point in the history
This shows all apps that will responder to the panic trigger, and provides
a switch each app so the user can enable/disable which apps should receive
the trigger.
  • Loading branch information
eighthave committed Mar 14, 2016
1 parent 64e775b commit b8b1091
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 25 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
compile 'com.google.code.gson:gson:2.3'
compile 'com.android.support:support-v4:23.1.+'
compile 'com.android.support:preference-v7:23.1.0'
compile 'info.guardianproject.panic:panic:0.5'
testCompile "org.robolectric:robolectric:3.0"
testCompile "org.robolectric:shadows-support-v4:3.0"
testCompile 'junit:junit:4.12'
Expand All @@ -47,6 +48,7 @@ dependencyVerification {
'com.android.support:appcompat-v7:b5783b390d1440769c9b8a7b42290523a4ff058ef2d3fb90c983973934ca115b',
'com.android.support:recyclerview-v7:464ec6e5004400a4fe0310f35343da9e5a2912386a3606db3585f7cf987c444a',
'com.crashlytics.sdk.android:answers:5af101ef6b58a26dd32cfc13f53c63c33fb2fdcdf6990241eca22e7a8c842847',
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
'io.fabric.sdk.android:fabric:15465f60ee6a2bb53dcf84e8dd939ce92dffbffc73bfdd3432b63fa6ee2f7bae',
'com.crashlytics.sdk.android:crashlytics-core:2f35df62420723d4a8e58f58a376fb640d11e1660656a9aa2959bb041b5b1d15',
'com.crashlytics.sdk.android:beta:6d7dce749fd70fa20adcf089aaed5d52f9e8e2a08f6666336e90a7555cee9718',
Expand Down
172 changes: 172 additions & 0 deletions app/src/main/java/org/iilab/pb/fragment/PanicRespondersFragment.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package org.iilab.pb.fragment;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;

import org.iilab.pb.R;
Expand All @@ -16,9 +29,16 @@
import org.iilab.pb.data.PBDatabase;
import org.iilab.pb.model.Page;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import info.guardianproject.panic.Panic;
import info.guardianproject.panic.PanicTrigger;

public class PanicRespondersFragment extends Fragment {
public static final String TAG = "PanicRespondersFragment";

private static final String PAGE_ID = "page_id";
private static final String PARENT_ACTIVITY = "parent_activity";
Expand All @@ -28,6 +48,16 @@ public class PanicRespondersFragment extends Fragment {
Page currentPage;
PageItemAdapter pageItemAdapter;

private static final int CONNECT_RESULT = 0x01;

private String responders[];
private Set<String> enabledResponders;
private Set<String> respondersThatCanConnect;
private ArrayList<CharSequence> appLabelList;
private ArrayList<Drawable> iconList;

private String requestPackageName;

public static PanicRespondersFragment newInstance(String pageId, int parentActivity) {
PanicRespondersFragment f = new PanicRespondersFragment();
Bundle args = new Bundle();
Expand All @@ -47,6 +77,63 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
return view;
}

@Override
public void onResume() {
super.onResume();

enabledResponders = PanicTrigger.getEnabledResponders(activity);
respondersThatCanConnect = PanicTrigger.getRespondersThatCanConnect(activity);

// sort enabled first, then disabled
LinkedHashSet<String> a = new LinkedHashSet<String>(enabledResponders);
LinkedHashSet<String> b = new LinkedHashSet<String>(PanicTrigger.getAllResponders(activity));
b.removeAll(enabledResponders);
a.addAll(b);
responders = a.toArray(new String[a.size()]);

PackageManager pm = getActivity().getPackageManager();
appLabelList = new ArrayList<CharSequence>(responders.length);
iconList = new ArrayList<Drawable>(responders.length);
for (String packageName : responders) {
try {
appLabelList.add(pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)));
iconList.add(pm.getApplicationIcon(packageName));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}

RecyclerView recyclerView = (RecyclerView) activity.findViewById(R.id.recycler_view);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(activity));
recyclerView.setHasFixedSize(true); // does not change, except in onResume()
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(new RecyclerView.Adapter<AppRowHolder>() {
@Override
public AppRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.responder_row, parent, false);
return new AppRowHolder(view);
}

@Override
public void onBindViewHolder(AppRowHolder holder, int position) {
String packageName = responders[position];
boolean canConnect = respondersThatCanConnect.contains(packageName);
holder.setupForApp(
packageName,
iconList.get(position),
appLabelList.get(position),
canConnect);
}

@Override
public int getItemCount() {
return appLabelList.size();
}
});
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Expand Down Expand Up @@ -87,4 +174,89 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
}
}

class AppRowHolder extends RecyclerView.ViewHolder {

private final View.OnClickListener onClickListener;
private final Switch onSwitch;
private final TextView editableLabel;
private final ImageView iconView;
private final TextView appLabelView;
private String rowPackageName;

AppRowHolder(final View row) {
super(row);

iconView = (ImageView) row.findViewById(R.id.iconView);
appLabelView = (TextView) row.findViewById(R.id.appLabel);
editableLabel = (TextView) row.findViewById(R.id.editableLabel);
onSwitch = (Switch) row.findViewById(R.id.on_switch);
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
requestPackageName = rowPackageName;
Intent intent = new Intent(Panic.ACTION_CONNECT);
intent.setPackage(requestPackageName);
startActivityForResult(intent, CONNECT_RESULT);
}
};

onSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean enabled) {
setEnabled(enabled);
if (enabled) {
PanicTrigger.enableResponder(activity, rowPackageName);
} else {
PanicTrigger.disableResponder(activity, rowPackageName);
}
}
});
}

void setEnabled(boolean enabled) {
if (enabled) {
editableLabel.setVisibility(View.VISIBLE);
appLabelView.setEnabled(true);
iconView.setEnabled(true);
iconView.setColorFilter(null);
} else {
editableLabel.setVisibility(View.GONE);
appLabelView.setEnabled(false);
iconView.setEnabled(false);
// grey out app icon when disabled
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
iconView.setColorFilter(filter);
}
}

void setupForApp(String packageName, Drawable icon, CharSequence appLabel, boolean editable) {
this.rowPackageName = packageName;
iconView.setImageDrawable(icon);
appLabelView.setText(appLabel);
if (editable) {
iconView.setOnClickListener(onClickListener);
appLabelView.setOnClickListener(onClickListener);
editableLabel.setOnClickListener(onClickListener);
editableLabel.setText(R.string.edit);
editableLabel.setTypeface(null, Typeface.BOLD);
if (Build.VERSION.SDK_INT >= 14)
editableLabel.setAllCaps(true);
} else {
iconView.setOnClickListener(null);
appLabelView.setOnClickListener(null);
editableLabel.setOnClickListener(null);
editableLabel.setText(R.string.app_hides);
editableLabel.setTypeface(null, Typeface.NORMAL);
if (Build.VERSION.SDK_INT >= 14)
editableLabel.setAllCaps(false);
}
boolean enabled = enabledResponders.contains(packageName);
if (Build.VERSION.SDK_INT >= 14)
onSwitch.setChecked(enabled);
setEnabled(enabled);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.iilab.pb.fragment;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import org.iilab.pb.R;

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
private final Drawable mDivider;

public SimpleDividerItemDecoration(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.responder_line_divider);
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();

int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);

RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();

mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/responder_line_divider.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<size
android:width="1dp"
android:height="1dp" />

<solid android:color="@color/gray" />

</shape>
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ScrollView
android:id="@+id/wizard_start_root"
<LinearLayout
style="@style/wizard_static_panel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
android:orientation="vertical">

<RelativeLayout
android:layout_width="fill_parent"
<TextView
android:id="@+id/fragment_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wizard_static_panel">
android:gravity="center_horizontal"
android:paddingBottom="5dp"
android:text="@string/page_title_text"
android:textSize="32sp" />

<TextView
android:id="@+id/fragment_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/page_title_text"
android:textSize="32sp"
android:paddingBottom="5dp"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/fragment_intro"
style="@style/wizard_intro_style"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/fragment_intro"
style="@style/wizard_intro_style"
android:layout_below="@+id/fragment_title" />
</LinearLayout>

</RelativeLayout>
</ScrollView>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>
51 changes: 51 additions & 0 deletions app/src/main/res/layout/responder_row.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/iconView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:gravity="center"
android:padding="20dp"
android:src="@android:drawable/ic_dialog_alert"/>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/iconView"
android:layout_toLeftOf="@+id/on_switch"
android:layout_toRightOf="@+id/iconView"
android:layout_toStartOf="@+id/on_switch"
android:orientation="vertical">

<TextView
android:id="@+id/appLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
android:id="@+id/editableLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_hides"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/darker_gray" />
</LinearLayout>

<Switch
android:id="@+id/on_switch"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:padding="20dp" />

</RelativeLayout>
Loading

0 comments on commit b8b1091

Please sign in to comment.