Skip to content

Commit 46895ab

Browse files
committed
Add a stats view similar to transmission-web
1 parent 498ac08 commit 46895ab

File tree

7 files changed

+246
-0
lines changed

7 files changed

+246
-0
lines changed

app/src/main/java/net/yupol/transmissionremote/app/MainActivity.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public class MainActivity extends BaseSpiceActivity implements TorrentUpdater.To
137137
private static final String TAG_OPEN_TORRENT_DIALOG = "tag_open_torrent_dialog";
138138
private static final String TAG_OPEN_TORRENT_BY_ADDRESS_DIALOG = "tag_open_torrent_by_address_dialog";
139139
private static final String TAG_DOWNLOAD_LOCATION_DIALOG = "tag_download_location_dialog";
140+
private static final String TAG_SERVER_STATS_DIALOG = "tag_server_stats_dialog";
140141

141142
private static final String MIME_TYPE_TORRENT = "application/x-bittorrent";
142143
private static final String SCHEME_MAGNET = "magnet";
@@ -762,6 +763,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
762763
case R.id.action_pause_all_torrents:
763764
pauseAllTorrents();
764765
return true;
766+
case R.id.action_open_stats:
767+
new StatsDialogFragment().show(getSupportFragmentManager(), TAG_SERVER_STATS_DIALOG);
765768
default:
766769
return super.onOptionsItemSelected(item);
767770
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package net.yupol.transmissionremote.app
2+
3+
import android.app.Dialog
4+
import android.os.Bundle
5+
import android.util.Log
6+
import androidx.appcompat.app.AlertDialog
7+
import androidx.databinding.DataBindingUtil
8+
import androidx.fragment.app.DialogFragment
9+
import com.octo.android.robospice.persistence.exception.SpiceException
10+
import com.octo.android.robospice.request.listener.RequestListener
11+
import net.yupol.transmissionremote.app.databinding.StatsBinding
12+
import net.yupol.transmissionremote.app.model.json.ServerStats
13+
import net.yupol.transmissionremote.app.opentorrent.DownloadLocationDialogFragment
14+
import net.yupol.transmissionremote.app.transport.BaseSpiceActivity
15+
import net.yupol.transmissionremote.app.transport.TransportManager
16+
import net.yupol.transmissionremote.app.transport.request.StatsGetRequest
17+
import android.text.format.Formatter
18+
19+
class StatsDialogFragment : DialogFragment() {
20+
21+
private val TAG: String = StatsDialogFragment::class.java.simpleName
22+
23+
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
24+
25+
return activity?.let {
26+
val builder = AlertDialog.Builder(it)
27+
val inflater = requireActivity().layoutInflater
28+
val binding = DataBindingUtil.inflate<StatsBinding>(inflater, R.layout.stats, null, false)
29+
binding.loadingInProgress = true
30+
31+
builder.setView(binding.root)
32+
.setNegativeButton(R.string.material_drawer_close,
33+
{dialog, id -> getDialog()?.cancel()})
34+
35+
getTransportManager().doRequest(StatsGetRequest(), object : RequestListener<ServerStats> {
36+
override fun onRequestFailure(spiceException: SpiceException?) {
37+
Log.e(TAG, "error fetching server stats")
38+
}
39+
40+
override fun onRequestSuccess(result: ServerStats?) {
41+
binding.statsTotalUploaded.text =
42+
Formatter.formatFileSize(it, result?.cumulativeStats?.uploadedBytes!!)
43+
binding.statsTotalDownloaded.text =
44+
Formatter.formatFileSize(it, result.cumulativeStats?.downloadedBytes!!)
45+
46+
binding.statsSessionUploaded.text =
47+
Formatter.formatFileSize(it, result.currentStats?.uploadedBytes!!)
48+
binding.statsSessionDownloaded.text =
49+
Formatter.formatFileSize(it, result.currentStats?.downloadedBytes!!)
50+
51+
binding.loadingInProgress = false
52+
}
53+
54+
})
55+
56+
builder.create()
57+
} ?: throw IllegalStateException("Activity cannot be null")
58+
}
59+
60+
private fun getTransportManager(): TransportManager {
61+
return (activity as BaseSpiceActivity).getTransportManager()
62+
}
63+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package net.yupol.transmissionremote.app.model.json;
2+
3+
import com.google.api.client.util.Key;
4+
5+
public class ServerStats {
6+
@Key("cumulative-stats") public TransferStats cumulativeStats;
7+
@Key("current-stats") public TransferStats currentStats;
8+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.yupol.transmissionremote.app.model.json;
2+
3+
import com.google.api.client.util.Key;
4+
5+
public class TransferStats {
6+
7+
@Key private long downloadedBytes;
8+
@Key private long secondActive;
9+
@Key private long uploadedBytes;
10+
11+
public long getDownloadedBytes() {
12+
return downloadedBytes;
13+
}
14+
15+
public long getUploadedBytes() {
16+
return uploadedBytes;
17+
}
18+
19+
public long getSecondActive() {
20+
return secondActive;
21+
}
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.yupol.transmissionremote.app.transport.request;
2+
3+
import net.yupol.transmissionremote.app.model.json.ServerSettings;
4+
import net.yupol.transmissionremote.app.model.json.ServerStats;
5+
6+
import org.json.JSONObject;
7+
8+
public class StatsGetRequest extends Request<ServerStats>{
9+
public StatsGetRequest() { super(ServerStats.class); }
10+
11+
@Override
12+
protected String getMethod() {
13+
return "session-stats";
14+
}
15+
16+
@Override
17+
protected JSONObject getArguments() {
18+
return null;
19+
}
20+
}

app/src/main/res/layout/stats.xml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<data>
5+
<import type="android.view.View" />
6+
<variable
7+
name="loadingInProgress"
8+
type="boolean" />
9+
</data>
10+
11+
<FrameLayout
12+
android:layout_width="match_parent"
13+
android:layout_height="match_parent">
14+
15+
<LinearLayout
16+
android:layout_width="match_parent"
17+
android:layout_height="match_parent"
18+
android:layout_marginTop="10dp"
19+
android:orientation="vertical"
20+
android:visibility="@{loadingInProgress ? View.GONE : View.VISIBLE}">
21+
22+
<TextView
23+
android:id="@+id/textView7"
24+
android:layout_width="match_parent"
25+
android:layout_height="wrap_content"
26+
android:layout_marginStart="10dp"
27+
android:text="@string/stats_total"
28+
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
29+
30+
<TableLayout
31+
android:layout_width="wrap_content"
32+
android:layout_height="wrap_content"
33+
android:layout_marginStart="15dp">
34+
35+
<TableRow
36+
android:layout_width="fill_parent"
37+
android:layout_height="match_parent">
38+
39+
<TextView
40+
android:layout_width="wrap_content"
41+
android:layout_height="match_parent"
42+
android:layout_marginEnd="50dp"
43+
android:text="@string/stats_uploaded" />
44+
45+
<TextView
46+
android:id="@+id/stats_total_uploaded"
47+
android:layout_width="wrap_content"
48+
android:layout_height="wrap_content"
49+
android:layout_gravity="end" />
50+
</TableRow>
51+
52+
<TableRow
53+
android:layout_width="match_parent"
54+
android:layout_height="match_parent">
55+
56+
<TextView
57+
android:layout_width="wrap_content"
58+
android:layout_height="wrap_content"
59+
android:text="@string/stats_downloaded" />
60+
61+
<TextView
62+
android:id="@+id/stats_total_downloaded"
63+
android:layout_width="wrap_content"
64+
android:layout_height="match_parent"
65+
android:layout_gravity="end" />
66+
</TableRow>
67+
</TableLayout>
68+
69+
<TextView
70+
android:layout_width="match_parent"
71+
android:layout_height="wrap_content"
72+
android:layout_marginStart="10dp"
73+
android:text="@string/stats_current_session"
74+
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
75+
76+
<TableLayout
77+
android:layout_width="match_parent"
78+
android:layout_height="match_parent"
79+
android:layout_marginStart="15dp">
80+
81+
<TableRow
82+
android:layout_width="fill_parent"
83+
android:layout_height="match_parent">
84+
85+
<TextView
86+
android:layout_width="wrap_content"
87+
android:layout_height="match_parent"
88+
android:layout_marginEnd="50dp"
89+
android:text="@string/stats_uploaded" />
90+
91+
<TextView
92+
android:id="@+id/stats_session_uploaded"
93+
android:layout_width="wrap_content"
94+
android:layout_height="wrap_content"
95+
android:layout_gravity="end" />
96+
</TableRow>
97+
98+
<TableRow
99+
android:layout_width="match_parent"
100+
android:layout_height="match_parent">
101+
102+
<TextView
103+
android:layout_width="wrap_content"
104+
android:layout_height="wrap_content"
105+
android:text="@string/stats_downloaded" />
106+
107+
<TextView
108+
android:id="@+id/stats_session_downloaded"
109+
android:layout_width="wrap_content"
110+
android:layout_height="match_parent"
111+
android:layout_gravity="end" />
112+
</TableRow>
113+
</TableLayout>
114+
115+
116+
</LinearLayout>
117+
<ProgressBar
118+
android:layout_width="wrap_content"
119+
android:layout_height="wrap_content"
120+
android:layout_gravity="center"
121+
android:visibility="@{loadingInProgress ? View.VISIBLE : View.GONE}" />
122+
</FrameLayout>
123+
124+
</layout>

app/src/main/res/values/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<string name="action_set_location">Set location</string>
2020
<string name="action_rename">Rename</string>
2121
<string name="action_share_magnet">Share Magnet Link</string>
22+
<string name="action_open_stats">Statistics</string>
2223

2324
<!-- Filters -->
2425
<string name="filters">Filters</string>
@@ -316,4 +317,9 @@
316317

317318
<string name="notification_channel_name">Torrent Downloading Finished</string>
318319

320+
<string name="stats_current_session">Current Session</string>
321+
<string name="stats_total">Total</string>
322+
<string name="stats_uploaded">Uploaded</string>
323+
<string name="stats_downloaded">Downloaded</string>
324+
319325
</resources>

0 commit comments

Comments
 (0)