mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-22 12:21:15 +00:00
Added more info to repo/node list items.
This commit is contained in:
parent
8e8de14ef5
commit
2ceca738ea
13 changed files with 436 additions and 44 deletions
|
@ -1,20 +1,29 @@
|
|||
package com.nutomic.syncthingandroid;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Generates item views for node items.
|
||||
*/
|
||||
public class NodeAdapter extends ArrayAdapter<RestApi.Node> {
|
||||
public class NodeAdapter extends ArrayAdapter<RestApi.Node>
|
||||
implements RestApi.OnReceiveConnectionsListener {
|
||||
|
||||
private Map<String, RestApi.Connection> mConnections =
|
||||
new HashMap<String, RestApi.Connection>();
|
||||
|
||||
public NodeAdapter(Context context) {
|
||||
super(context, R.layout.node_list_item);
|
||||
|
@ -27,12 +36,39 @@ public class NodeAdapter extends ArrayAdapter<RestApi.Node> {
|
|||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = inflater.inflate(R.layout.node_list_item, parent, false);
|
||||
}
|
||||
|
||||
TextView name = (TextView) convertView.findViewById(R.id.name);
|
||||
TextView status = (TextView) convertView.findViewById(R.id.status);
|
||||
TextView download = (TextView) convertView.findViewById(R.id.download);
|
||||
TextView upload = (TextView) convertView.findViewById(R.id.upload);
|
||||
|
||||
name.setText(getItem(position).Name);
|
||||
final String nodeId = getItem(position).NodeID;
|
||||
|
||||
RestApi.Connection conn = mConnections.get(nodeId);
|
||||
Resources res = getContext().getResources();
|
||||
if (conn != null) {
|
||||
if (conn.Completion == 100) {
|
||||
status.setText(res.getString(R.string.node_up_to_date));
|
||||
status.setTextColor(res.getColor(R.color.text_green));
|
||||
}
|
||||
else {
|
||||
status.setText(res.getString(R.string.node_syncing, conn.Completion));
|
||||
status.setTextColor(res.getColor(R.color.text_blue));
|
||||
}
|
||||
download.setText(RestApi.readableTransferRate(getContext(), conn.InBits));
|
||||
upload.setText(RestApi.readableTransferRate(getContext(), conn.OutBits));
|
||||
}
|
||||
else {
|
||||
download.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
||||
upload.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
||||
status.setText(res.getString(R.string.node_disconnected));
|
||||
status.setTextColor(res.getColor(R.color.text_red));
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replacement for addAll, which is not implemented on lower API levels.
|
||||
*/
|
||||
|
@ -42,4 +78,21 @@ public class NodeAdapter extends ArrayAdapter<RestApi.Node> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests new connection info for all nodes visible in listView.
|
||||
*/
|
||||
public void updateConnections(RestApi api, ListView listView) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
if ( i >= listView.getFirstVisiblePosition() &&
|
||||
i <= listView.getLastVisiblePosition()) {
|
||||
api.getConnections(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
||||
mConnections = connections;
|
||||
notifyDataSetInvalidated();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,21 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Generates item views for repository items.
|
||||
*/
|
||||
public class RepositoryAdapter extends ArrayAdapter<RestApi.Repository> {
|
||||
public class RepositoryAdapter extends ArrayAdapter<RestApi.Repository>
|
||||
implements RestApi.OnReceiveModelListener {
|
||||
|
||||
private HashMap<String, RestApi.Model> mModels = new HashMap<String, RestApi.Model>();
|
||||
|
||||
public RepositoryAdapter(Context context) {
|
||||
super(context, R.layout.node_list_item);
|
||||
|
@ -27,12 +32,37 @@ public class RepositoryAdapter extends ArrayAdapter<RestApi.Repository> {
|
|||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = inflater.inflate(R.layout.repository_list_item, parent, false);
|
||||
}
|
||||
|
||||
TextView id = (TextView) convertView.findViewById(R.id.id);
|
||||
|
||||
TextView state = (TextView) convertView.findViewById(R.id.state);
|
||||
TextView folder = (TextView) convertView.findViewById(R.id.folder);
|
||||
TextView progress = (TextView) convertView.findViewById(R.id.progress);
|
||||
TextView invalid = (TextView) convertView.findViewById(R.id.invalid);
|
||||
|
||||
id.setText(getItem(position).ID);
|
||||
state.setTextColor(getContext().getResources().getColor(R.color.text_green));
|
||||
folder.setText((getItem(position).Directory));
|
||||
RestApi.Model model = mModels.get(getItem(position).ID);
|
||||
if (model != null) {
|
||||
state.setText(getContext().getString(R.string.repo_progress_format, model.state,
|
||||
(model.globalBytes <= 0)
|
||||
? 100
|
||||
: (int) ((model.localBytes / (float) model.globalBytes) * 100)));
|
||||
progress.setText(
|
||||
RestApi.readableFileSize(getContext(), model.localBytes) + " / " +
|
||||
RestApi.readableFileSize(getContext(), model.globalBytes)
|
||||
);
|
||||
invalid.setText(model.invalid);
|
||||
invalid.setVisibility((model.invalid.equals("")) ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
invalid.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replacement for addAll, which is not implemented on lower API levels.
|
||||
*/
|
||||
|
@ -42,4 +72,21 @@ public class RepositoryAdapter extends ArrayAdapter<RestApi.Repository> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests updated model info from the api for all visible items.
|
||||
*/
|
||||
public void updateModel(RestApi api, ListView listView) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
if ( i >= listView.getFirstVisiblePosition() &&
|
||||
i <= listView.getLastVisiblePosition()) {
|
||||
api.getModel(getItem(i).ID, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveModel(String repoId, RestApi.Model model) {
|
||||
mModels.put(repoId, model);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ package com.nutomic.syncthingandroid.gui;
|
|||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
|
@ -117,8 +117,10 @@ public abstract class LoadingListFragment extends Fragment implements RestApi.On
|
|||
|
||||
/**
|
||||
* Called when the list adapter should be set.
|
||||
* @param activity
|
||||
*/
|
||||
public abstract void onInitAdapter(MainActivity activity);
|
||||
|
||||
public ListView getListView() {
|
||||
return mListFragment.getListView();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.os.Bundle;
|
|||
import android.support.v4.app.ActionBarDrawerToggle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -119,14 +118,14 @@ public class LocalNodeInfoFragment extends Fragment
|
|||
public void onReceiveSystemInfo(RestApi.SystemInfo info) {
|
||||
mNodeId.setText(info.myID);
|
||||
mCpuUsage.setText(new DecimalFormat("0.00").format(info.cpuPercent) + "%");
|
||||
mRamUsage.setText(mActivity.getApi().readableFileSize(info.sys));
|
||||
mRamUsage.setText(RestApi.readableFileSize(mActivity, info.sys));
|
||||
if (info.extAnnounceOK) {
|
||||
mAnnounceServer.setText("Online");
|
||||
mAnnounceServer.setTextColor(getResources().getColor(android.R.color.holo_green_light));
|
||||
mAnnounceServer.setTextColor(getResources().getColor(R.color.text_green));
|
||||
}
|
||||
else {
|
||||
mAnnounceServer.setText("Offline");
|
||||
mAnnounceServer.setTextColor(getResources().getColor(android.R.color.holo_red_light));
|
||||
mAnnounceServer.setTextColor(getResources().getColor(R.color.text_red));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,8 +135,8 @@ public class LocalNodeInfoFragment extends Fragment
|
|||
@Override
|
||||
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
||||
RestApi.Connection c = connections.get(RestApi.LOCAL_NODE_CONNECTIONS);
|
||||
mDownload.setText(mActivity.getApi().readableTransferRate(c.InBytesTotal));
|
||||
mUpload.setText(mActivity.getApi().readableTransferRate(c.OutBytesTotal));
|
||||
mDownload.setText(RestApi.readableTransferRate(mActivity, c.InBits));
|
||||
mUpload.setText(RestApi.readableTransferRate(mActivity, c.OutBits));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,10 @@ package com.nutomic.syncthingandroid.gui;
|
|||
import com.nutomic.syncthingandroid.NodeAdapter;
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Displays a list of all existing nodes.
|
||||
|
@ -10,11 +14,48 @@ import com.nutomic.syncthingandroid.syncthing.RestApi;
|
|||
public class NodesFragment extends LoadingListFragment implements
|
||||
RestApi.OnApiAvailableListener {
|
||||
|
||||
private NodeAdapter mAdapter;
|
||||
|
||||
private Timer mTimer;
|
||||
|
||||
private boolean mInitialized = false;
|
||||
|
||||
@Override
|
||||
public void onInitAdapter(MainActivity activity) {
|
||||
NodeAdapter adapter = new NodeAdapter(activity);
|
||||
adapter.add(activity.getApi().getNodes());
|
||||
setListAdapter(adapter, R.string.nodes_list_empty);
|
||||
mAdapter = new NodeAdapter(activity);
|
||||
mAdapter.add(activity.getApi().getNodes());
|
||||
setListAdapter(mAdapter, R.string.nodes_list_empty);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
if (!mInitialized)
|
||||
return;
|
||||
|
||||
MainActivity activity = (MainActivity) getActivity();
|
||||
if (activity != null) {
|
||||
mAdapter.updateConnections(activity.getApi(), getListView());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
|
||||
if (isVisibleToUser) {
|
||||
mTimer = new Timer();
|
||||
mTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateList();
|
||||
}
|
||||
|
||||
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
||||
}
|
||||
else if (mTimer != null) {
|
||||
mTimer.cancel();
|
||||
mTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ package com.nutomic.syncthingandroid.gui;
|
|||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.RepositoryAdapter;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Displays a list of all existing repositories.
|
||||
|
@ -10,11 +14,48 @@ import com.nutomic.syncthingandroid.syncthing.RestApi;
|
|||
public class RepositoriesFragment extends LoadingListFragment implements
|
||||
RestApi.OnApiAvailableListener {
|
||||
|
||||
private RepositoryAdapter mAdapter;
|
||||
|
||||
private Timer mTimer;
|
||||
|
||||
private boolean mInitialized = false;
|
||||
|
||||
@Override
|
||||
public void onInitAdapter(MainActivity activity) {
|
||||
RepositoryAdapter adapter = new RepositoryAdapter(activity);
|
||||
adapter.add(activity.getApi().getRepositories());
|
||||
setListAdapter(adapter, R.string.repositories_list_empty);
|
||||
mAdapter = new RepositoryAdapter(activity);
|
||||
mAdapter.add(activity.getApi().getRepositories());
|
||||
setListAdapter(mAdapter, R.string.repositories_list_empty);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
if (!mInitialized)
|
||||
return;
|
||||
|
||||
MainActivity activity = (MainActivity) getActivity();
|
||||
if (activity != null) {
|
||||
mAdapter.updateModel(activity.getApi(), getListView());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
|
||||
if (isVisibleToUser) {
|
||||
mTimer = new Timer();
|
||||
mTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateList();
|
||||
}
|
||||
|
||||
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
||||
}
|
||||
else if (mTimer != null) {
|
||||
mTimer.cancel();
|
||||
mTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@ import android.util.Log;
|
|||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Performs a GET request with no parameters to the URL in uri[0] with the path in uri[1] and
|
||||
|
@ -31,16 +35,24 @@ public class GetTask extends AsyncTask<String, Void, String> {
|
|||
|
||||
public static final String URI_CONNECTIONS = "/rest/connections";
|
||||
|
||||
public static final String URI_MODEL = "/rest/model";
|
||||
|
||||
/**
|
||||
* params[0] Syncthing hostname
|
||||
* params[1] URI to call
|
||||
* params[2] Syncthing API key
|
||||
* params[3] optional parameter key
|
||||
* params[4] optional parameter value
|
||||
*/
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
String fullUri = params[0] + params[1];
|
||||
Log.i(TAG, "Sending GET request to " + fullUri);
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
if (params.length == 5) {
|
||||
LinkedList<NameValuePair> urlParams = new LinkedList<NameValuePair>();
|
||||
urlParams.add(new BasicNameValuePair(params[2], params[3]));
|
||||
fullUri += "?" + URLEncodedUtils.format(urlParams, "utf-8");
|
||||
}
|
||||
HttpGet get = new HttpGet(fullUri);
|
||||
get.addHeader(new BasicHeader("X-API-Key", params[2]));
|
||||
|
||||
|
|
|
@ -94,9 +94,26 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
public String At;
|
||||
public long InBytesTotal;
|
||||
public long OutBytesTotal;
|
||||
public long InBits;
|
||||
public long OutBits;
|
||||
public String Address;
|
||||
public String ClientVersion;
|
||||
public double Completion;
|
||||
public int Completion;
|
||||
}
|
||||
|
||||
public static class Model {
|
||||
public long globalBytes;
|
||||
public long globalDeleted;
|
||||
public long globalFiles;
|
||||
public long localBytes;
|
||||
public long localDeleted;
|
||||
public long localFiles;
|
||||
public long inSyncBytes;
|
||||
public long inSyncFiles;
|
||||
public long needBytes;
|
||||
public long needFiles;
|
||||
public String state;
|
||||
public String invalid;
|
||||
}
|
||||
|
||||
public interface OnApiAvailableListener {
|
||||
|
@ -122,6 +139,17 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
|
||||
private final NotificationManager mNotificationManager;
|
||||
|
||||
/**
|
||||
* Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS},
|
||||
* or an empty HashMap.
|
||||
*/
|
||||
private HashMap<String, Connection> mPreviousConnections = new HashMap<String, Connection>();
|
||||
|
||||
/**
|
||||
* Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}.
|
||||
*/
|
||||
private long mPreviousConnectionTime = 0;
|
||||
|
||||
public RestApi(Context context, String url, String apiKey) {
|
||||
mContext = context;
|
||||
mUrl = url;
|
||||
|
@ -420,8 +448,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
/**
|
||||
* Converts a number of bytes to a human readable file size (eg 3.5 GB).
|
||||
*/
|
||||
public String readableFileSize(long bytes) {
|
||||
final String[] units = mContext.getResources().getStringArray(R.array.file_size_units);
|
||||
public static String readableFileSize(Context context, long bytes) {
|
||||
final String[] units = context.getResources().getStringArray(R.array.file_size_units);
|
||||
if (bytes <= 0) return "0 " + units[0];
|
||||
int digitGroups = (int) (Math.log10(bytes)/Math.log10(1024));
|
||||
return new DecimalFormat("#,##0.#")
|
||||
|
@ -431,9 +459,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
/**
|
||||
* Converts a number of bytes to a human readable transfer rate in bits (eg 100 Kb/s).
|
||||
*/
|
||||
public String readableTransferRate(long bytes) {
|
||||
long bits = bytes * 8;
|
||||
final String[] units = mContext.getResources().getStringArray(R.array.transfer_rate_units);
|
||||
public static String readableTransferRate(Context context, long bits) {
|
||||
final String[] units = context.getResources().getStringArray(R.array.transfer_rate_units);
|
||||
if (bits <= 0) return "0 " + units[0];
|
||||
int digitGroups = (int) (Math.log10(bits)/Math.log10(1024));
|
||||
return new DecimalFormat("#,##0.#")
|
||||
|
@ -442,6 +469,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
|
||||
/**
|
||||
* Listener for {@link #getConnections}.
|
||||
*
|
||||
* NOTE: The parameter connections is cached internally. Do not modify it or
|
||||
* any of its contents.
|
||||
*/
|
||||
public interface OnReceiveConnectionsListener {
|
||||
public void onReceiveConnections(Map<String, Connection> connections);
|
||||
|
@ -456,6 +486,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
new GetTask() {
|
||||
@Override
|
||||
protected void onPostExecute(String s) {
|
||||
Long now = System.currentTimeMillis();
|
||||
Long difference = (now - mPreviousConnectionTime) / 1000;
|
||||
if (difference < 1) {
|
||||
listener.onReceiveConnections(mPreviousConnections);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject json = new JSONObject(s);
|
||||
String[] names = json.names().join(" ").replace("\"", "").split(" ");
|
||||
|
@ -469,11 +506,24 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
c.OutBytesTotal = conn.getLong("OutBytesTotal");
|
||||
c.Address = conn.getString("Address");
|
||||
c.ClientVersion = conn.getString("ClientVersion");
|
||||
c.Completion = conn.getDouble("Completion");
|
||||
c.Completion = conn.getInt("Completion");
|
||||
|
||||
Connection prev = (mPreviousConnections.containsKey(address))
|
||||
? mPreviousConnections.get(address)
|
||||
: new Connection();
|
||||
mPreviousConnectionTime = now;
|
||||
if (difference != 0) {
|
||||
c.InBits = Math.max(0, 8 *
|
||||
(conn.getLong("InBytesTotal") - prev.InBytesTotal) / difference);
|
||||
c.OutBits = Math.max(0, 8 *
|
||||
(conn.getLong("OutBytesTotal") - prev.OutBytesTotal) / difference);
|
||||
}
|
||||
|
||||
connections.put(address, c);
|
||||
|
||||
}
|
||||
listener.onReceiveConnections(connections);
|
||||
mPreviousConnections = connections;
|
||||
listener.onReceiveConnections(mPreviousConnections);
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.w(TAG, "Failed to parse connections", e);
|
||||
|
@ -482,4 +532,43 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
}.execute(mUrl, GetTask.URI_CONNECTIONS, mApiKey);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listener for {@link #getModel}.
|
||||
*/
|
||||
public interface OnReceiveModelListener {
|
||||
public void onReceiveModel(String repoId, Model model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns status information about the repo with the given ID.
|
||||
*/
|
||||
public void getModel(final String repoId, final OnReceiveModelListener listener) {
|
||||
new GetTask() {
|
||||
@Override
|
||||
protected void onPostExecute(String s) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(s);
|
||||
Model m = new Model();
|
||||
m.globalBytes = json.getLong("globalBytes");
|
||||
m.globalDeleted = json.getLong("globalDeleted");
|
||||
m.globalFiles = json.getLong("globalFiles");
|
||||
m.localBytes = json.getLong("localBytes");
|
||||
m.localDeleted = json.getLong("localDeleted");
|
||||
m.localFiles = json.getLong("localFiles");
|
||||
m.inSyncBytes = json.getLong("inSyncBytes");
|
||||
m.inSyncFiles = json.getLong("inSyncFiles");
|
||||
m.needBytes = json.getLong("needBytes");
|
||||
m.needFiles = json.getLong("needFiles");
|
||||
m.state = json.getString("state");
|
||||
m.invalid = json.optString("invalid");
|
||||
listener.onReceiveModel(repoId, m);
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.w(TAG, "Failed to read repository info", e);
|
||||
}
|
||||
}
|
||||
}.execute(mUrl, GetTask.URI_MODEL, mApiKey, "repo", repoId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
<TextView
|
||||
android:id="@+id/node_id_title"
|
||||
android:textStyle="bold"
|
||||
android:text="Node ID"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
@ -30,7 +29,7 @@
|
|||
android:layout_height="wrap_content" >
|
||||
<TextView
|
||||
android:id="@+id/cpu_usage_title"
|
||||
android:text="CPU Usage"
|
||||
android:text="@string/cpu_usage"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -48,7 +47,7 @@
|
|||
android:layout_height="wrap_content" >
|
||||
<TextView
|
||||
android:id="@+id/ram_usage_title"
|
||||
android:text="RAM Usage"
|
||||
android:text="@string/ram_usage"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -66,7 +65,7 @@
|
|||
android:layout_height="wrap_content" >
|
||||
<TextView
|
||||
android:id="@+id/download_title"
|
||||
android:text="Download"
|
||||
android:text="@string/download_title"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -84,7 +83,7 @@
|
|||
android:layout_height="wrap_content" >
|
||||
<TextView
|
||||
android:id="@+id/upload_title"
|
||||
android:text="Upload"
|
||||
android:text="@string/upload_title"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -102,7 +101,7 @@
|
|||
android:layout_height="wrap_content" >
|
||||
<TextView
|
||||
android:id="@+id/announce_server_title"
|
||||
android:text="Announce Server"
|
||||
android:text="@string/announce_server"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight" >
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:padding="4dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
|
@ -11,7 +11,46 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:padding="4dip" />
|
||||
android:ellipsize="end" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignBottom="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_title"
|
||||
android:text="@string/download_title_colon"
|
||||
android:layout_below="@id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download"
|
||||
android:layout_alignBaseline="@id/download_title"
|
||||
android:layout_toRightOf="@id/download_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/upload_title"
|
||||
android:text="@string/upload_title_colon"
|
||||
android:layout_below="@id/download_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/upload"
|
||||
android:layout_alignBaseline="@id/upload_title"
|
||||
android:layout_toRightOf="@id/upload_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
</RelativeLayout>
|
|
@ -1,9 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight" >
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/id"
|
||||
|
@ -11,7 +12,35 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:padding="4dip" />
|
||||
android:ellipsize="end" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/state"
|
||||
android:textColor="#00ff00"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/folder"
|
||||
android:layout_below="@id/state"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/progress"
|
||||
android:layout_below="@id/folder"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/invalid"
|
||||
android:textColor="@color/text_red"
|
||||
android:layout_below="@id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</RelativeLayout>
|
6
src/main/res/values/colors.xml
Normal file
6
src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="text_red">#ffff4444</color>
|
||||
<color name="text_blue">#ff33b5e5</color>
|
||||
<color name="text_green">#ff99cc00</color>
|
||||
</resources>
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
<string name="repositories_fragment_title">Repositories</string>
|
||||
|
||||
<!-- Format string for repository progress. First parameter is status string, second is sync percentage -->
|
||||
<string name="repo_progress_format">%1$s (%2$d%%)</string>
|
||||
|
||||
<!-- Shown if no repos exist -->
|
||||
<string name="repositories_list_empty">No repositories found</string>
|
||||
|
||||
|
@ -35,6 +38,38 @@
|
|||
<!-- Shown if no nodes exist -->
|
||||
<string name="nodes_list_empty">No nodes found</string>
|
||||
|
||||
<!-- Indicates that a repo is fully synced to the local node -->
|
||||
<string name="node_up_to_date">Up to Date</string>
|
||||
|
||||
<!-- Indicates that the node is currently syncing. Parameter is sync percentage -->
|
||||
<string name="node_syncing">Syncing (%1$d%%)</string>
|
||||
|
||||
<!-- Indicates that there is no connection to the node -->
|
||||
<string name="node_disconnected">Disconnected</string>
|
||||
|
||||
<!-- Title for current download rate -->
|
||||
<string name="download_title">Download</string>
|
||||
|
||||
<!-- Title for current upload rate -->
|
||||
<string name="upload_title">Upload</string>
|
||||
|
||||
<!-- LocalNodeInfoFragment -->
|
||||
|
||||
<!-- Same as download_title with a colon and space appended -->
|
||||
<string name="download_title_colon">Download:\u0020</string>
|
||||
|
||||
<!-- Same as upload_title with a colon and space appended -->
|
||||
<string name="upload_title_colon">Upload:\u0020</string>
|
||||
|
||||
<!-- Title for current CPU usage -->
|
||||
<string name="cpu_usage">CPU Usage</string>
|
||||
|
||||
<!-- Title for current RAM usage -->
|
||||
<string name="ram_usage">RAM Usage</string>
|
||||
|
||||
<!-- Title for announce server status -->
|
||||
<string name="announce_server">Announce Server</string>
|
||||
|
||||
<!-- WebGuiActivity -->
|
||||
|
||||
<!-- Title of the web gui activity -->
|
||||
|
|
Loading…
Reference in a new issue