From 264285ecf7f06af6b20795f1a4a2faecfeb2a72d Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Wed, 16 Dec 2015 18:49:57 -0200
Subject: [PATCH] Show all transports on the dashboard

and indicate which transports are currently available.
The icons have been chosen from the official material icons and might be
replaced later with icons that better represent the given transport.

Please note that I used vector drawables which will be automatically
converted at build time to raster graphics.

Closes #96
---
 briar-android/res/drawable/transport_bt.xml   |   5 +
 briar-android/res/drawable/transport_lan.xml  |   6 +
 briar-android/res/drawable/transport_tor.xml  |   5 +
 .../res/layout/list_item_transport.xml        |  27 ++++
 briar-android/res/layout/transports_list.xml  |  20 +++
 briar-android/res/values/strings.xml          |   4 +-
 .../android/DashboardActivity.java            | 137 +++++++++++++++++-
 7 files changed, 198 insertions(+), 6 deletions(-)
 create mode 100644 briar-android/res/drawable/transport_bt.xml
 create mode 100644 briar-android/res/drawable/transport_lan.xml
 create mode 100644 briar-android/res/drawable/transport_tor.xml
 create mode 100644 briar-android/res/layout/list_item_transport.xml
 create mode 100644 briar-android/res/layout/transports_list.xml

diff --git a/briar-android/res/drawable/transport_bt.xml b/briar-android/res/drawable/transport_bt.xml
new file mode 100644
index 0000000000..d221708690
--- /dev/null
+++ b/briar-android/res/drawable/transport_bt.xml
@@ -0,0 +1,5 @@
+<vector android:alpha="0.54" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41V22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59V5.83zm1.88,10.46L13,18.17v-3.76l1.88,1.88z"/>
+</vector>
diff --git a/briar-android/res/drawable/transport_lan.xml b/briar-android/res/drawable/transport_lan.xml
new file mode 100644
index 0000000000..d2cc9189e6
--- /dev/null
+++ b/briar-android/res/drawable/transport_lan.xml
@@ -0,0 +1,6 @@
+<vector android:alpha="0.54" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillAlpha=".3" android:fillColor="#FF000000" android:pathData="M12.01,21.49L23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4C5.28,3 0.81,6.66 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01z"/>
+    <path android:fillColor="#FF000000" android:pathData="M3.53,10.95l8.46,10.54 0.01,0.01 0.01,-0.01 8.46,-10.54C20.04,10.62 16.81,8 12,8c-4.81,0 -8.04,2.62 -8.47,2.95z"/>
+</vector>
diff --git a/briar-android/res/drawable/transport_tor.xml b/briar-android/res/drawable/transport_tor.xml
new file mode 100644
index 0000000000..fe462b2f73
--- /dev/null
+++ b/briar-android/res/drawable/transport_tor.xml
@@ -0,0 +1,5 @@
+<vector android:alpha="0.54" android:height="24dp"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zm6.93,6h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2H4.26zm0.82,2h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zm2.95,-8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zm0.25,5.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
+</vector>
diff --git a/briar-android/res/layout/list_item_transport.xml b/briar-android/res/layout/list_item_transport.xml
new file mode 100644
index 0000000000..11c3d5e4de
--- /dev/null
+++ b/briar-android/res/layout/list_item_transport.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:tools="http://schemas.android.com/tools"
+	android:orientation="horizontal"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:padding="@dimen/margin_small"
+	android:gravity="center_horizontal">
+
+	<ImageView
+		android:id="@+id/imageView"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:padding="@dimen/margin_small"
+		tools:src="@drawable/transport_tor"/>
+
+	<TextView
+		android:id="@+id/textView"
+		android:layout_width="wrap_content"
+		android:layout_height="match_parent"
+		android:gravity="center_vertical"
+		android:padding="@dimen/margin_small"
+		android:textColor="@android:color/tertiary_text_light"
+		tools:text="@string/transport_tor"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/transports_list.xml b/briar-android/res/layout/transports_list.xml
new file mode 100644
index 0000000000..02c05e74df
--- /dev/null
+++ b/briar-android/res/layout/transports_list.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical"
+	android:layout_width="wrap_content"
+	android:layout_height="wrap_content">
+
+	<View
+		android:layout_width="match_parent"
+		android:layout_height="1px"
+		android:background="@color/horizontal_border"/>
+
+	<GridView
+		android:id="@+id/transportsView"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:padding="@dimen/margin_medium"
+		android:numColumns="3"/>
+
+</LinearLayout>
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 85fe74090e..bdcf261047 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -117,9 +117,9 @@
     <string name="offline">Offline</string>
     <string name="send">Send</string>
     <string name="data_transports">Data Transports</string>
-    <string name="transport_tor">Internet via Tor</string>
+    <string name="transport_tor">Internet</string>
     <string name="transport_bt">Bluetooth</string>
-    <string name="transport_lan">Local Area Network</string>
+    <string name="transport_lan">Wi-Fi</string>
 
     <!-- Dialogs -->
     <string name="dialog_title_lost_password">Lost password</string>
diff --git a/briar-android/src/org/briarproject/android/DashboardActivity.java b/briar-android/src/org/briarproject/android/DashboardActivity.java
index b499c6794f..6e08cd2170 100644
--- a/briar-android/src/org/briarproject/android/DashboardActivity.java
+++ b/briar-android/src/org/briarproject/android/DashboardActivity.java
@@ -1,17 +1,21 @@
 package org.briarproject.android;
 
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.Button;
 import android.widget.GridView;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.ProgressBar;
+import android.widget.TextView;
 
 import org.briarproject.R;
 import org.briarproject.android.contact.ContactListActivity;
@@ -25,10 +29,8 @@ import org.briarproject.api.db.DbException;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportAddedEvent;
 import org.briarproject.api.event.TransportDisabledEvent;
 import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.event.TransportRemovedEvent;
 import org.briarproject.api.plugins.Plugin;
 import org.briarproject.api.plugins.PluginManager;
 
@@ -40,6 +42,7 @@ import javax.inject.Inject;
 
 import static android.view.Gravity.CENTER;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
@@ -49,6 +52,9 @@ public class DashboardActivity extends BriarActivity implements EventListener {
 	private static final Logger LOG =
 			Logger.getLogger(DashboardActivity.class.getName());
 
+	private List<Transport> transports;
+	private BaseAdapter transportsAdapter;
+
 	@Inject private ReferenceManager referenceManager;
 	@Inject private PluginManager pluginManager;
 
@@ -89,11 +95,13 @@ public class DashboardActivity extends BriarActivity implements EventListener {
 			if (LOG.isLoggable(INFO)) {
 				LOG.info("TransportEnabledEvent: " + id.getString());
 			}
+			setTransport(id, true);
 		} else if (e instanceof TransportDisabledEvent) {
 			TransportId id = ((TransportDisabledEvent) e).getTransportId();
 			if (LOG.isLoggable(INFO)) {
 				LOG.info("TransportDisabledEvent: " + id.getString());
 			}
+			setTransport(id, false);
 		}
 	}
 
@@ -185,8 +193,14 @@ public class DashboardActivity extends BriarActivity implements EventListener {
 
 		int pad = LayoutUtils.getPadding(this);
 
+		LinearLayout layout = new LinearLayout(this);
+		layout.setLayoutParams(MATCH_MATCH);
+		layout.setOrientation(LinearLayout.VERTICAL);
+
 		GridView grid = new GridView(this);
-		grid.setLayoutParams(matchMatch);
+		LinearLayout.LayoutParams params =
+				new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f);
+		grid.setLayoutParams(params);
 		grid.setGravity(CENTER);
 		grid.setPadding(pad, pad, pad, pad);
 		Resources res = getResources();
@@ -211,7 +225,21 @@ public class DashboardActivity extends BriarActivity implements EventListener {
 				return buttons.get(position);
 			}
 		});
-		setContentView(grid);
+		layout.addView(grid);
+
+		// inflate transports layout
+		LayoutInflater inflater = (LayoutInflater) getSystemService
+				(Context.LAYOUT_INFLATER_SERVICE);
+		ViewGroup transportsLayout = (ViewGroup) inflater.
+				inflate(R.layout.transports_list, layout);
+
+		initializeTransports();
+
+		GridView transportsView = (GridView) transportsLayout.findViewById(
+				R.id.transportsView);
+		transportsView.setAdapter(transportsAdapter);
+
+		setContentView(layout);
 	}
 
 	private void showSpinner() {
@@ -247,4 +275,105 @@ public class DashboardActivity extends BriarActivity implements EventListener {
 			}
 		});
 	}
+
+	private void initializeTransports() {
+		transports = new ArrayList<Transport>(3);
+
+		Transport tor = new Transport();
+		tor.id = new TransportId("tor");
+		Plugin torPlugin = pluginManager.getPlugin(tor.id);
+		if (torPlugin == null) tor.enabled = false;
+		else tor.enabled = torPlugin.isRunning();
+		tor.iconId = R.drawable.transport_tor;
+		tor.textId = R.string.transport_tor;
+		transports.add(tor);
+
+		Transport bt = new Transport();
+		bt.id = new TransportId("bt");
+		Plugin btPlugin = pluginManager.getPlugin(bt.id);
+		if (btPlugin == null) bt.enabled = false;
+		else bt.enabled = btPlugin.isRunning();
+		bt.iconId = R.drawable.transport_bt;
+		bt.textId = R.string.transport_bt;
+		transports.add(bt);
+
+		Transport lan = new Transport();
+		lan.id = new TransportId("lan");
+		Plugin lanPlugin = pluginManager.getPlugin(lan.id);
+		if (lanPlugin == null) lan.enabled = false;
+		else lan.enabled = lanPlugin.isRunning();
+		lan.iconId = R.drawable.transport_lan;
+		lan.textId = R.string.transport_lan;
+		transports.add(lan);
+
+		transportsAdapter = new BaseAdapter() {
+			@Override
+			public int getCount() {
+				return transports.size();
+			}
+
+			@Override
+			public Transport getItem(int position) {
+				return transports.get(position);
+			}
+
+			@Override
+			public long getItemId(int position) {
+				return 0;
+			}
+
+			@Override
+			public View getView(int position, View convertView,
+					ViewGroup parent) {
+				LayoutInflater inflater = (LayoutInflater) getSystemService(
+						Context.LAYOUT_INFLATER_SERVICE);
+				ViewGroup view = (ViewGroup) inflater
+						.inflate(R.layout.list_item_transport, parent, false);
+
+				Transport t = getItem(position);
+				Resources r = getResources();
+
+				int c;
+				if (t.enabled) {
+					c = r.getColor(R.color.briar_green_light);
+				} else {
+					c = r.getColor(android.R.color.tertiary_text_light);
+				}
+
+				ImageView icon = (ImageView) view.findViewById(R.id.imageView);
+				icon.setImageDrawable(r.getDrawable(t.iconId));
+				icon.setColorFilter(c);
+
+				TextView text = (TextView) view.findViewById(R.id.textView);
+				text.setText(getString(t.textId));
+				text.setTextColor(c);
+
+				return view;
+			}
+		};
+	}
+
+	private void setTransport(final TransportId id, final boolean enabled) {
+		runOnUiThread(new Runnable() {
+			public void run() {
+				if (transports == null || transportsAdapter == null) return;
+
+				for (Transport t : transports) {
+					if (t.id.equals(id)) {
+						t.enabled = enabled;
+						break;
+					}
+				}
+
+				transportsAdapter.notifyDataSetChanged();
+			}
+		});
+	}
+
+	private static class Transport {
+		TransportId id;
+		boolean enabled;
+		int iconId;
+		int textId;
+	}
 }
-- 
GitLab