diff --git a/app/build.gradle b/app/build.gradle index 27215aa..73ee07b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,6 +37,7 @@ dependencies { } compile 'com.google.zxing:core:3.1.0' compile 'com.google.zxing:android-integration:3.1.0' + compile 'com.androidplot:androidplot-core:0.6.1' } dependencyVerification { diff --git a/app/src/main/java/i2p/bote/android/NetworkInfoFragment.java b/app/src/main/java/i2p/bote/android/NetworkInfoFragment.java index 4b88d6a..711a5a4 100644 --- a/app/src/main/java/i2p/bote/android/NetworkInfoFragment.java +++ b/app/src/main/java/i2p/bote/android/NetworkInfoFragment.java @@ -1,14 +1,6 @@ package i2p.bote.android; -import java.util.Collection; -import java.util.Set; - -import net.i2p.data.Destination; -import i2p.bote.I2PBote; -import i2p.bote.Util; -import i2p.bote.network.BannedPeer; -import i2p.bote.network.DhtPeerStats; -import i2p.bote.network.RelayPeer; +import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -16,7 +8,30 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import com.androidplot.pie.PieChart; +import com.androidplot.pie.Segment; +import com.androidplot.pie.SegmentFormatter; + +import net.i2p.data.Destination; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import i2p.bote.I2PBote; +import i2p.bote.Util; +import i2p.bote.network.BannedPeer; +import i2p.bote.network.DhtPeerStats; +import i2p.bote.network.RelayPeer; + +import static i2p.bote.Util._; + public class NetworkInfoFragment extends Fragment { + private PieChart mKademliaPie; + private TextView mKademliaPeers; + private PieChart mRelayPie; + private TextView mRelayPeers; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -27,19 +42,18 @@ public class NetworkInfoFragment extends Fragment { public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mKademliaPie = (PieChart) view.findViewById(R.id.kademlia_peers_pie); + mKademliaPeers = (TextView) view.findViewById(R.id.kademlia_peers); + mRelayPie = (PieChart) view.findViewById(R.id.relay_peers_pie); + mRelayPeers = (TextView) view.findViewById(R.id.relay_peers); + Destination dest = I2PBote.getInstance().getLocalDestination(); if (dest != null) ((TextView) view.findViewById(R.id.local_destination)).setText( Util.toBase32(dest)); - DhtPeerStats dhtStats = I2PBote.getInstance().getDhtStats(); - if (dhtStats != null) - ((TextView) view.findViewById(R.id.kademlia_peers)).setText( - "" + dhtStats.getData().size()); - - Set relayPeers = I2PBote.getInstance().getRelayPeers(); - ((TextView) view.findViewById(R.id.relay_peers)).setText( - "" + relayPeers.size()); + setupKademliaPeers(); + setupRelayPeers(); Collection bannedPeers = I2PBote.getInstance().getBannedPeers(); ((TextView) view.findViewById(R.id.banned_peers)).setText( @@ -49,4 +63,114 @@ public class NetworkInfoFragment extends Fragment { if (e != null) ((TextView) view.findViewById(R.id.error)).setText(e.toString()); } + + private void setupSegmentFormatter(SegmentFormatter sf) { + sf.getLabelPaint().setTextSize(20); + } + + private void setupKademliaPeers() { + DhtPeerStats dhtStats = I2PBote.getInstance().getDhtStats(); + if (dhtStats != null) { + if (dhtStats.getData().size() == 0) { + Segment n = new Segment("", 100); + + SegmentFormatter nf = new SegmentFormatter(); + setupSegmentFormatter(nf); + nf.getFillPaint().setColor(getResources().getColor(android.R.color.darker_gray)); + + mKademliaPie.addSeries(n, nf); + } else { + int reachable = 0; + for (List row : dhtStats.getData()) { + if (_("No").equals(row.get(4))) + reachable += 1; + } + int unreachable = dhtStats.getData().size() - reachable; + + mKademliaPeers.setText("" + dhtStats.getData().size()); + + if (reachable > 0) { + Segment r = new Segment("Reachable", reachable); + + SegmentFormatter rf = new SegmentFormatter(); + setupSegmentFormatter(rf); + rf.getFillPaint().setColor(getResources().getColor(R.color.green)); + + mKademliaPie.addSeries(r, rf); + } + + if (unreachable > 0) { + Segment u = new Segment("Unreachable", dhtStats.getData().size() - reachable); + + SegmentFormatter uf = new SegmentFormatter(); + setupSegmentFormatter(uf); + uf.getFillPaint().setColor(getResources().getColor(R.color.error_color)); + + mKademliaPie.addSeries(u, uf); + } + } + } + + mKademliaPie.getBorderPaint().setColor(Color.TRANSPARENT); + mKademliaPie.getBackgroundPaint().setColor(Color.TRANSPARENT); + } + + private void setupRelayPeers() { + Set relayPeers = I2PBote.getInstance().getRelayPeers(); + mRelayPeers.setText("" + relayPeers.size()); + + if (relayPeers.size() == 0) { + Segment n = new Segment("", 100); + + SegmentFormatter nf = new SegmentFormatter(); + setupSegmentFormatter(nf); + nf.getFillPaint().setColor(getResources().getColor(android.R.color.darker_gray)); + + mRelayPie.addSeries(n, nf); + } else { + int good = 0; + int untested = 0; + for (RelayPeer relayPeer : relayPeers) { + int reachability = relayPeer.getReachability(); + if (reachability == 0) + untested += 1; + else if (reachability > 80) + good += 1; + } + int bad = relayPeers.size() - good - untested; + + if (good > 0) { + Segment g = new Segment("Good", good); + + SegmentFormatter gf = new SegmentFormatter(); + setupSegmentFormatter(gf); + gf.getFillPaint().setColor(getResources().getColor(R.color.green)); + + mRelayPie.addSeries(g, gf); + } + + if (bad > 0) { + Segment b = new Segment("Unreliable", bad); + + SegmentFormatter bf = new SegmentFormatter(); + setupSegmentFormatter(bf); + bf.getFillPaint().setColor(getResources().getColor(R.color.red)); + + mRelayPie.addSeries(b, bf); + } + + if (untested > 0) { + Segment u = new Segment("Untested", untested); + + SegmentFormatter uf = new SegmentFormatter(); + setupSegmentFormatter(uf); + uf.getFillPaint().setColor(getResources().getColor(R.color.accent)); + + mRelayPie.addSeries(u, uf); + } + } + + mRelayPie.getBorderPaint().setColor(Color.TRANSPARENT); + mRelayPie.getBackgroundPaint().setColor(Color.TRANSPARENT); + } } diff --git a/app/src/main/res/layout/fragment_network_info.xml b/app/src/main/res/layout/fragment_network_info.xml index 8818d6b..58e3c45 100644 --- a/app/src/main/res/layout/fragment_network_info.xml +++ b/app/src/main/res/layout/fragment_network_info.xml @@ -1,60 +1,102 @@ - + android:layout_height="match_parent"> - + android:orientation="vertical" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin"> - + - + - + - + - + - + + - + - + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7f094ae..dc779f7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -12,4 +12,7 @@ #111 #f00 + #4caf50 + #f44336 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b8d09fc..9247f32 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -30,4 +30,6 @@ 8dp 12dp 16dp + + 300dp