mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-12-27 13:21:30 +00:00
Use Gson for connections
This commit is contained in:
parent
a201cd8789
commit
dcdb6e1129
7 changed files with 78 additions and 102 deletions
|
@ -1,10 +1,8 @@
|
|||
package com.nutomic.syncthingandroid.test;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.nutomic.syncthingandroid.model.Connection;
|
||||
import com.nutomic.syncthingandroid.model.Connections;
|
||||
import com.nutomic.syncthingandroid.model.Device;
|
||||
import com.nutomic.syncthingandroid.model.Folder;
|
||||
import com.nutomic.syncthingandroid.model.Model;
|
||||
|
@ -12,7 +10,6 @@ import com.nutomic.syncthingandroid.model.SystemInfo;
|
|||
import com.nutomic.syncthingandroid.service.RestApi;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -54,7 +51,7 @@ public class MockRestApi extends RestApi {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getConnections(OnResultListener1<Map<String, Connection>> listener) {
|
||||
public void getConnections(OnResultListener1<Map<String, Connections>> listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@ import android.text.Editable;
|
|||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.*;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
@ -22,7 +24,7 @@ import com.google.gson.Gson;
|
|||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.model.Connection;
|
||||
import com.nutomic.syncthingandroid.model.Connections;
|
||||
import com.nutomic.syncthingandroid.model.Device;
|
||||
import com.nutomic.syncthingandroid.service.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.util.Compression;
|
||||
|
@ -32,7 +34,6 @@ import com.nutomic.syncthingandroid.util.Util;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static android.view.View.GONE;
|
||||
|
@ -218,13 +219,13 @@ public class DeviceActivity extends SyncthingActivity implements View.OnClickLis
|
|||
* NOTE: This is only called once on startup, should be called more often to properly display
|
||||
* version/address changes.
|
||||
*/
|
||||
public void onReceiveConnections(Map<String, Connection> connections) {
|
||||
public void onReceiveConnections(Connections connections) {
|
||||
boolean viewsExist = mSyncthingVersionView != null && mCurrentAddressView != null;
|
||||
if (viewsExist && connections.containsKey(mDevice.deviceID)) {
|
||||
if (viewsExist && connections.connections.containsKey(mDevice.deviceID)) {
|
||||
mCurrentAddressView.setVisibility(VISIBLE);
|
||||
mSyncthingVersionView.setVisibility(VISIBLE);
|
||||
mCurrentAddressView.setText(connections.get(mDevice.deviceID).address);
|
||||
mSyncthingVersionView.setText(connections.get(mDevice.deviceID).clientVersion);
|
||||
mCurrentAddressView.setText(connections.connections.get(mDevice.deviceID).address);
|
||||
mSyncthingVersionView.setText(connections.connections.get(mDevice.deviceID).clientVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import com.nutomic.syncthingandroid.R;
|
|||
import com.nutomic.syncthingandroid.activities.MainActivity;
|
||||
import com.nutomic.syncthingandroid.activities.SettingsActivity;
|
||||
import com.nutomic.syncthingandroid.activities.WebGuiActivity;
|
||||
import com.nutomic.syncthingandroid.model.Connection;
|
||||
import com.nutomic.syncthingandroid.model.Connections;
|
||||
import com.nutomic.syncthingandroid.model.SystemInfo;
|
||||
import com.nutomic.syncthingandroid.model.SystemVersion;
|
||||
import com.nutomic.syncthingandroid.service.RestApi;
|
||||
|
@ -187,8 +187,8 @@ public class DrawerFragment extends Fragment implements View.OnClickListener {
|
|||
/**
|
||||
* Populates views with status received via {@link RestApi#getConnections}.
|
||||
*/
|
||||
private void onReceiveConnections(Map<String, Connection> connections) {
|
||||
Connection c = connections.get(RestApi.TOTAL_STATS);
|
||||
private void onReceiveConnections(Connections connections) {
|
||||
Connections.Connection c = connections.total;
|
||||
mDownload.setText(Util.readableTransferRate(mActivity, c.inBits));
|
||||
mUpload.setText(Util.readableTransferRate(mActivity, c.outBits));
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package com.nutomic.syncthingandroid.model;
|
||||
|
||||
public class Connection {
|
||||
public String at;
|
||||
public long inBytesTotal;
|
||||
public long outBytesTotal;
|
||||
public long inBits;
|
||||
public long outBits;
|
||||
public String address;
|
||||
public String clientVersion;
|
||||
public int completion;
|
||||
public boolean connected;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.nutomic.syncthingandroid.model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Connections {
|
||||
|
||||
public Connection total;
|
||||
public Map<String, Connection> connections;
|
||||
|
||||
public static class Connection {
|
||||
public boolean paused;
|
||||
public String clientVersion;
|
||||
public String at;
|
||||
public boolean connected;
|
||||
public long inBytesTotal;
|
||||
public long outBytesTotal;
|
||||
public String type;
|
||||
public String address;
|
||||
|
||||
// These fields are not sent from Syncthing, but are populated on the client side.
|
||||
public int completion;
|
||||
public long inBits;
|
||||
public long outBits;
|
||||
|
||||
public void setTransferRate(Connection previous, long msElapsed) {
|
||||
long secondsElapsed = msElapsed / 1000;
|
||||
long inBytes = 8 * (inBytesTotal - previous.inBytesTotal) / secondsElapsed;
|
||||
long outBytes = 8 * (outBytesTotal - previous.outBytesTotal) / secondsElapsed;
|
||||
inBits = Math.max(0, inBytes);
|
||||
outBits = Math.max(0, outBytes);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import android.content.Intent;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
|
@ -21,7 +22,7 @@ import com.nutomic.syncthingandroid.http.GetTask;
|
|||
import com.nutomic.syncthingandroid.http.PostConfigTask;
|
||||
import com.nutomic.syncthingandroid.http.PostScanTask;
|
||||
import com.nutomic.syncthingandroid.model.Config;
|
||||
import com.nutomic.syncthingandroid.model.Connection;
|
||||
import com.nutomic.syncthingandroid.model.Connections;
|
||||
import com.nutomic.syncthingandroid.model.Device;
|
||||
import com.nutomic.syncthingandroid.model.Event;
|
||||
import com.nutomic.syncthingandroid.model.Folder;
|
||||
|
@ -31,10 +32,6 @@ import com.nutomic.syncthingandroid.model.SystemInfo;
|
|||
import com.nutomic.syncthingandroid.model.SystemVersion;
|
||||
import com.nutomic.syncthingandroid.util.FolderObserver;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
@ -51,12 +48,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
|||
|
||||
private static final String TAG = "RestApi";
|
||||
|
||||
/**
|
||||
* Key of the map element containing connection info for the local device, in the return
|
||||
* value of {@link #getConnections}
|
||||
*/
|
||||
public static final String TOTAL_STATS = "total";
|
||||
|
||||
public interface OnConfigChangedListener {
|
||||
void onConfigChanged();
|
||||
}
|
||||
|
@ -83,7 +74,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
|||
* Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS},
|
||||
* or an empty Map.
|
||||
*/
|
||||
private Map<String, Connection> mPreviousConnections = new HashMap<>();
|
||||
private Optional<Connections> mPreviousConnections = Optional.absent();
|
||||
|
||||
/**
|
||||
* Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}.
|
||||
|
@ -342,62 +333,31 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
|||
|
||||
/**
|
||||
* Returns connection info for the local device and all connected devices.
|
||||
* <p/>
|
||||
* Use the key {@link #TOTAL_STATS} to get connection info for the local device.
|
||||
*
|
||||
* The result is cached internally. Do not modify it or any of its contents.
|
||||
*/
|
||||
public void getConnections(final OnResultListener1<Map<String, Connection>> listener) {
|
||||
public void getConnections(final OnResultListener1<Connections> listener) {
|
||||
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, null, result -> {
|
||||
Long now = System.currentTimeMillis();
|
||||
Long timeElapsed = (now - mPreviousConnectionTime) / 1000;
|
||||
if (timeElapsed < 1) {
|
||||
listener.onResult(mPreviousConnections);
|
||||
Long msElapsed = now - mPreviousConnectionTime;
|
||||
if (msElapsed < SyncthingService.GUI_UPDATE_INTERVAL) {
|
||||
listener.onResult(deepCopy(mPreviousConnections.get(), Connections.class));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject json = new JSONObject(result);
|
||||
Map<String, JSONObject> jsonConnections = new HashMap<>();
|
||||
jsonConnections.put(TOTAL_STATS, json.getJSONObject(TOTAL_STATS));
|
||||
JSONArray extConnections = json.getJSONObject("connections").names();
|
||||
if (extConnections != null) {
|
||||
for (int i = 0; i < extConnections.length(); i++) {
|
||||
String deviceId = extConnections.get(i).toString();
|
||||
jsonConnections.put(deviceId, json.getJSONObject("connections").getJSONObject(deviceId));
|
||||
}
|
||||
}
|
||||
Map<String, Connection> connections = new HashMap<>();
|
||||
for (Map.Entry<String, JSONObject> jsonConnection : jsonConnections.entrySet()) {
|
||||
String deviceId = jsonConnection.getKey();
|
||||
Connection c = new Connection();
|
||||
JSONObject conn = jsonConnection.getValue();
|
||||
c.address = deviceId;
|
||||
c.at = conn.getString("at");
|
||||
c.inBytesTotal = conn.getLong("inBytesTotal");
|
||||
c.outBytesTotal = conn.getLong("outBytesTotal");
|
||||
c.address = conn.getString("address");
|
||||
c.clientVersion = conn.getString("clientVersion");
|
||||
c.completion = getDeviceCompletion(deviceId);
|
||||
c.connected = conn.getBoolean("connected");
|
||||
mPreviousConnectionTime = now;
|
||||
Connections connections = new Gson().fromJson(result, Connections.class);
|
||||
for (Map.Entry<String, Connections.Connection> e : connections.connections.entrySet()) {
|
||||
e.getValue().completion = getDeviceCompletion(e.getKey());
|
||||
|
||||
Connection prev = (mPreviousConnections.containsKey(deviceId))
|
||||
? mPreviousConnections.get(deviceId)
|
||||
: new Connection();
|
||||
mPreviousConnectionTime = now;
|
||||
c.inBits = Math.max(0, 8 *
|
||||
(conn.getLong("inBytesTotal") - prev.inBytesTotal) / timeElapsed);
|
||||
c.outBits = Math.max(0, 8 *
|
||||
(conn.getLong("outBytesTotal") - prev.outBytesTotal) / timeElapsed);
|
||||
|
||||
connections.put(deviceId, c);
|
||||
|
||||
}
|
||||
mPreviousConnections = connections;
|
||||
listener.onResult(mPreviousConnections);
|
||||
} catch (JSONException e) {
|
||||
Log.w(TAG, "Failed to parse connections", e);
|
||||
Connections.Connection prev = mPreviousConnections
|
||||
.transform(c -> c.connections.get(e.getKey()))
|
||||
.or(new Connections.Connection());
|
||||
e.getValue().setTransferRate(prev, msElapsed);
|
||||
}
|
||||
Connections.Connection prev =
|
||||
mPreviousConnections.transform(c -> c.total).or(new Connections.Connection());
|
||||
connections.total.setTransferRate(prev, msElapsed);
|
||||
mPreviousConnections = Optional.of(connections);
|
||||
listener.onResult(deepCopy(connections, Connections.class));
|
||||
}).execute();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,22 +10,19 @@ import android.view.ViewGroup;
|
|||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.model.Connection;
|
||||
import com.nutomic.syncthingandroid.model.Connections;
|
||||
import com.nutomic.syncthingandroid.model.Device;
|
||||
import com.nutomic.syncthingandroid.service.RestApi;
|
||||
import com.nutomic.syncthingandroid.util.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Generates item views for device items.
|
||||
*/
|
||||
public class DevicesAdapter extends ArrayAdapter<Device> {
|
||||
|
||||
private Map<String, Connection> mConnections =
|
||||
new HashMap<>();
|
||||
private Optional<Connections> mConnections = Optional.absent();
|
||||
|
||||
public DevicesAdapter(Context context) {
|
||||
super(context, R.layout.item_device_list);
|
||||
|
@ -46,21 +43,21 @@ public class DevicesAdapter extends ArrayAdapter<Device> {
|
|||
TextView upload = (TextView) convertView.findViewById(R.id.upload);
|
||||
|
||||
String deviceId = getItem(position).deviceID;
|
||||
Connection conn = mConnections.get(deviceId);
|
||||
Optional<Connections.Connection> conn = mConnections.transform(a -> a.connections.get(deviceId));
|
||||
|
||||
name.setText(getItem(position).getDisplayName());
|
||||
Resources r = getContext().getResources();
|
||||
if (conn != null && conn.connected) {
|
||||
if (conn.completion == 100) {
|
||||
if (conn.isPresent() && conn.get().connected) {
|
||||
if (conn.get().completion == 100) {
|
||||
status.setText(r.getString(R.string.device_up_to_date));
|
||||
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_green));
|
||||
}
|
||||
else {
|
||||
status.setText(r.getString(R.string.device_syncing, conn.completion));
|
||||
status.setText(r.getString(R.string.device_syncing, conn.get().completion));
|
||||
status.setTextColor(ContextCompat.getColor(getContext(), R.color.text_blue));
|
||||
}
|
||||
download.setText(Util.readableTransferRate(getContext(), conn.inBits));
|
||||
upload.setText(Util.readableTransferRate(getContext(), conn.outBits));
|
||||
download.setText(Util.readableTransferRate(getContext(), conn.get().inBits));
|
||||
upload.setText(Util.readableTransferRate(getContext(), conn.get().outBits));
|
||||
}
|
||||
else {
|
||||
download.setText(Util.readableTransferRate(getContext(), 0));
|
||||
|
@ -81,8 +78,8 @@ public class DevicesAdapter extends ArrayAdapter<Device> {
|
|||
}
|
||||
}
|
||||
|
||||
public void onReceiveConnections(Map<String, Connection> connections) {
|
||||
mConnections = connections;
|
||||
public void onReceiveConnections(Connections connections) {
|
||||
mConnections = Optional.of(connections);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue