1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-11-26 14:21:16 +00:00

Use generic listeners for RestApi callbacks

This commit is contained in:
Felix Ableitner 2016-10-31 03:59:26 +09:00
parent dcd800dc9e
commit 28407d2e94
6 changed files with 58 additions and 129 deletions

View file

@ -49,10 +49,7 @@ import static com.nutomic.syncthingandroid.util.Compression.METADATA;
/**
* Shows device details and allows changing them.
*/
public class DeviceFragment extends Fragment implements
SyncthingActivity.OnServiceConnectedListener, RestApi.OnReceiveConnectionsListener,
SyncthingService.OnApiChangeListener, RestApi.OnDeviceIdNormalizedListener,
View.OnClickListener {
public class DeviceFragment extends Fragment implements View.OnClickListener {
public static final String EXTRA_DEVICE_ID =
"com.nutomic.syncthingandroid.fragments.DeviceFragment.DEVICE_ID";
@ -155,7 +152,7 @@ public class DeviceFragment extends Fragment implements
SettingsActivity activity = (SettingsActivity) getActivity();
mIsCreateMode = activity.getIsCreate();
activity.registerOnServiceConnectedListener(this);
activity.registerOnServiceConnectedListener(this::onServiceConnected);
activity.setTitle(mIsCreateMode ? R.string.add_device : R.string.edit_device);
setHasOptionsMenu(true);
@ -173,7 +170,7 @@ public class DeviceFragment extends Fragment implements
public void onDestroy() {
super.onDestroy();
if (mSyncthingService != null) {
mSyncthingService.unregisterOnApiChangeListener(this);
mSyncthingService.unregisterOnApiChangeListener(this::onApiChange);
}
}
@ -235,10 +232,9 @@ public class DeviceFragment extends Fragment implements
mAddressesView.removeTextChangedListener(mAddressesTextWatcher);
}
@Override
public void onServiceConnected() {
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
mSyncthingService.registerOnApiChangeListener(this);
mSyncthingService.registerOnApiChangeListener(this::onApiChange);
}
/**
@ -247,7 +243,6 @@ public class DeviceFragment extends Fragment implements
* NOTE: This is only called once on startup, should be called more often to properly display
* version/address changes.
*/
@Override
public void onReceiveConnections(Map<String, Connection> connections) {
boolean viewsExist = mSyncthingVersionView != null && mCurrentAddressView != null;
if (viewsExist && connections.containsKey(mDevice.deviceID)) {
@ -258,7 +253,6 @@ public class DeviceFragment extends Fragment implements
}
}
@Override
public void onApiChange(SyncthingService.State currentState) {
if (currentState != ACTIVE) {
getActivity().finish();
@ -282,7 +276,7 @@ public class DeviceFragment extends Fragment implements
}
}
mSyncthingService.getApi().getConnections(this);
mSyncthingService.getApi().getConnections(this::onReceiveConnections);
updateViewsAndSetListeners();
}
@ -324,7 +318,8 @@ public class DeviceFragment extends Fragment implements
.show();
return true;
}
mSyncthingService.getApi().addDevice(mDevice, this);
mSyncthingService.getApi().addDevice(mDevice, error ->
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show());
getActivity().finish();
return true;
case R.id.share_device_id:
@ -358,17 +353,6 @@ public class DeviceFragment extends Fragment implements
}
}
/**
* Callback for {@link RestApi#editDevice}.
* Displays an error toast if error message present.
*/
@Override
public void onDeviceIdNormalized(String normalizedId, String error) {
if (error != null) {
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show();
}
}
private void initDevice() {
mDevice = new Device();
mDevice.name = "";

View file

@ -31,10 +31,7 @@ import java.util.TimerTask;
/**
* Displays information about the local device.
*/
public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemInfoListener,
RestApi.OnReceiveConnectionsListener,
RestApi.OnReceiveSystemVersionListener,
View.OnClickListener {
public class DrawerFragment extends Fragment implements View.OnClickListener {
private TextView mDeviceId;
private TextView mCpuUsage;
@ -139,9 +136,9 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
private void updateGui() {
if (mActivity.getApi() == null || getActivity() == null || getActivity().isFinishing())
return;
mActivity.getApi().getSystemInfo(this);
mActivity.getApi().getSystemVersion(this);
mActivity.getApi().getConnections(this);
mActivity.getApi().getSystemInfo(this::onReceiveSystemInfo);
mActivity.getApi().getSystemVersion(this::onReceiveSystemVersion);
mActivity.getApi().getConnections(this::onReceiveConnections);
}
/**
@ -156,7 +153,6 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
/**
* Populates views with status received via {@link RestApi#getSystemInfo}.
*/
@Override
public void onReceiveSystemInfo(SystemInfo info) {
if (getActivity() == null)
return;
@ -181,7 +177,6 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
/**
* Populates views with status received via {@link RestApi#getSystemInfo}.
*/
@Override
public void onReceiveSystemVersion(SystemVersion info) {
if (getActivity() == null)
return;
@ -192,8 +187,7 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI
/**
* Populates views with status received via {@link RestApi#getConnections}.
*/
@Override
public void onReceiveConnections(Map<String, Connection> connections) {
private void onReceiveConnections(Map<String, Connection> connections) {
Connection c = connections.get(RestApi.TOTAL_STATS);
mDownload.setText(Util.readableTransferRate(mActivity, c.inBits));
mUpload.setText(Util.readableTransferRate(mActivity, c.outBits));

View file

@ -8,7 +8,6 @@ import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.util.Log;
@ -232,7 +231,7 @@ public class SettingsFragment extends PreferenceFragment
}
public boolean onRequireRestart(Preference preference, Object o) {
mSyncthingService.getApi().requireRestart(getActivity());
mSyncthingService.getApi().showRestartDialog(getActivity());
return true;
}
@ -262,7 +261,7 @@ public class SettingsFragment extends PreferenceFragment
break;
case KEY_STTRACE:
if (((String) o).matches("[0-9a-z, ]*"))
mSyncthingService.getApi().requireRestart(getActivity());
mSyncthingService.getApi().showRestartDialog(getActivity());
else {
Toast.makeText(getActivity(), R.string.toast_invalid_sttrace, Toast.LENGTH_SHORT)
.show();
@ -284,7 +283,7 @@ public class SettingsFragment extends PreferenceFragment
new TestRootTask().execute();
} else {
new Thread(new ChownFilesRunnable()).start();
mSyncthingService.getApi().requireRestart(getActivity());
mSyncthingService.getApi().showRestartDialog(getActivity());
}
return true;
case KEY_EXPORT_CONFIG:
@ -350,7 +349,7 @@ public class SettingsFragment extends PreferenceFragment
@Override
protected void onPostExecute(Boolean haveRoot) {
if (haveRoot) {
mSyncthingService.getApi().requireRestart(getActivity());
mSyncthingService.getApi().showRestartDialog(getActivity());
mUseRoot.setChecked(true);
} else {
Toast.makeText(getActivity(), R.string.toast_root_denied, Toast.LENGTH_SHORT)

View file

@ -29,6 +29,7 @@ import com.nutomic.syncthingandroid.model.Options;
import com.nutomic.syncthingandroid.model.SystemInfo;
import com.nutomic.syncthingandroid.model.SystemVersion;
import com.nutomic.syncthingandroid.util.FolderObserver;
import com.nutomic.syncthingandroid.util.Util;
import org.json.JSONArray;
import org.json.JSONException;
@ -60,6 +61,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
void onConfigChanged();
}
public interface OnResultListener1<T> {
public void onResult(T t);
}
public interface OnResultListener2<T, R> {
public void onResult(T t, R r);
}
private final Context mContext;
private final URL mUrl;
private final String mApiKey;
@ -82,8 +91,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
private long mPreviousConnectionTime = 0;
/**
* Stores the latest result of {@link #getModel(String, OnReceiveModelListener)} for each folder,
* for calculating device percentage in {@link #getConnections(OnReceiveConnectionsListener)}.
* Stores the latest result of {@link #getModel} for each folder, for calculating device
* percentage in {@link #getConnections}.
*/
private final HashMap<String, Model> mCachedModelInfo = new HashMap<>();
@ -172,7 +181,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Either shows a restart dialog, or only updates the config, depending on
* {@link #mRestartPostponed}.
*/
public void requireRestart(Activity activity) {
public void showRestartDialog(Activity activity) {
if (mRestartPostponed) {
sendConfig();
} else {
@ -181,13 +190,16 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
mOnConfigChangedListener.onConfigChanged();
}
/**
* Sends current config to Syncthing.
*/
private void sendConfig() {
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, null)
.execute(new Gson().toJson(mConfig));
}
/**
* Immediately restarts Syncthing, without confirmation.
* Sends current config and restarts Syncthing.
*/
public void restart() {
new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> {
@ -263,16 +275,11 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
}
}
public void addDevice(Device device, OnDeviceIdNormalizedListener listener) {
normalizeDeviceId(device.deviceID, ((normalizedId, error) -> {
if (error == null) {
public void addDevice(Device device, OnResultListener1<String> errorListener) {
normalizeDeviceId(device.deviceID, normalizedId -> {
mConfig.devices.add(device);
sendConfig();
}
else {
listener.onDeviceIdNormalized(normalizedId, error);
}
}));
}, errorListener);
}
public void addFolder(Folder folder) {
@ -294,21 +301,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
public void editSettings(Config.Gui newGui, Options newOptions, Activity activity) {
mConfig.gui = newGui;
mConfig.options = newOptions;
requireRestart(activity);
}
/**
* Result listener for {@link #getSystemInfo(OnReceiveSystemInfoListener)}.
*/
public interface OnReceiveSystemInfoListener {
public void onReceiveSystemInfo(SystemInfo info);
}
/**
* Result listener for {@link #getSystemVersion(OnReceiveSystemVersionListener)}.
*/
public interface OnReceiveSystemVersionListener {
void onReceiveSystemVersion(SystemVersion version);
showRestartDialog(activity);
}
/**
@ -316,9 +309,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*
* @param listener Callback invoked when the result is received.
*/
public void getSystemInfo(final OnReceiveSystemInfoListener listener) {
public void getSystemInfo(OnResultListener1<SystemInfo> listener) {
new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, result -> {
listener.onReceiveSystemInfo(new Gson().fromJson(result, SystemInfo.class));
listener.onResult(new Gson().fromJson(result, SystemInfo.class));
}).execute();
}
@ -327,10 +320,10 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*
* @param listener Callback invoked when the result is received.
*/
public void getSystemVersion(final OnReceiveSystemVersionListener listener) {
public void getSystemVersion(OnResultListener1<SystemVersion> listener) {
new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> {
SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class);
listener.onReceiveSystemVersion(systemVersion);
listener.onResult(systemVersion);
}).execute();
}
@ -341,31 +334,19 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
return deepCopy(mConfig.folders, new TypeToken<List<Folder>>(){}.getType());
}
/**
* Listener for {@link #getConnections}.
*/
public interface OnReceiveConnectionsListener {
/**
* @param connections Map from Device id to {@link Connection}.
* <p/>
* NOTE: The parameter connections is cached internally. Do not modify it or
* any of its contents.
*/
public void onReceiveConnections(Map<String, Connection> connections);
}
/**
* 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 OnReceiveConnectionsListener listener) {
public void getConnections(final OnResultListener1<Map<String, Connection>> listener) {
new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, result -> {
Long now = System.currentTimeMillis();
Long timeElapsed = (now - mPreviousConnectionTime) / 1000;
if (timeElapsed < 1) {
listener.onReceiveConnections(mPreviousConnections);
listener.onResult(mPreviousConnections);
return;
}
@ -407,7 +388,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
}
mPreviousConnections = connections;
listener.onReceiveConnections(mPreviousConnections);
listener.onResult(mPreviousConnections);
} catch (JSONException e) {
Log.w(TAG, "Failed to parse connections", e);
}
@ -449,13 +430,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
: 100;
}
/**
* Listener for {@link #getModel}.
*/
public interface OnReceiveModelListener {
public void onReceiveModel(String folderId, Model model);
}
/**
* Listener for {@link #getEvents}.
*/
@ -472,14 +446,15 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
*/
void onDone(long lastId);
}
/**
* Returns status information about the folder with the given id.
*/
public void getModel(final String folderId, final OnReceiveModelListener listener) {
public void getModel(final String folderId, final OnResultListener2<String, Model> listener) {
new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey, result -> {
Model m = new Gson().fromJson(result, Model.class);
mCachedModelInfo.put(folderId, m);
listener.onReceiveModel(folderId, m);
listener.onResult(folderId, m);
}).execute("folder", folderId);
}
@ -508,31 +483,19 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
"since", String.valueOf(sinceId), "limit", String.valueOf(limit));
}
/**
* Result listener for {@link #normalizeDeviceId(String, OnDeviceIdNormalizedListener)}.
*/
public interface OnDeviceIdNormalizedListener {
/**
* On any call, exactly one parameter will be null.
*
* @param normalizedId The normalized device ID, or null on error.
* @param error An error message, or null on success.
*/
public void onDeviceIdNormalized(String normalizedId, String error);
}
/**
* Normalizes a given device ID.
*/
public void normalizeDeviceId(final String id, final OnDeviceIdNormalizedListener listener) {
public void normalizeDeviceId(String id, OnResultListener1<String> listener,
OnResultListener1<String> errorListener) {
new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, result -> {
JsonObject json = new JsonParser().parse(result).getAsJsonObject();
JsonElement normalizedId = json.get("id");
JsonElement error = json.get("error");
if (normalizedId != null)
listener.onDeviceIdNormalized(normalizedId.getAsString(), null);
listener.onResult(normalizedId.getAsString());
if (error != null)
listener.onDeviceIdNormalized(null, error.getAsString());
errorListener.onResult(error.getAsString());
}).execute("id", id);
}
@ -557,21 +520,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
throw new RuntimeException();
}
/**
* Callback for {@link #getUsageReport}.
*/
public interface OnReceiveUsageReportListener {
public void onReceiveUsageReport(String report);
}
/**
* Returns prettyfied usage report.
*/
public void getUsageReport(final OnReceiveUsageReportListener listener) {
public void getUsageReport(final OnResultListener1<String> listener) {
new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, result -> {
JsonElement json = new JsonParser().parse(result);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
listener.onReceiveUsageReport(gson.toJson(json));
listener.onResult(gson.toJson(json));
}).execute();
}

View file

@ -22,8 +22,7 @@ import java.util.Map;
/**
* Generates item views for device items.
*/
public class DevicesAdapter extends ArrayAdapter<Device>
implements RestApi.OnReceiveConnectionsListener {
public class DevicesAdapter extends ArrayAdapter<Device> {
private Map<String, Connection> mConnections =
new HashMap<>();
@ -78,11 +77,10 @@ public class DevicesAdapter extends ArrayAdapter<Device>
*/
public void updateConnections(RestApi api) {
for (int i = 0; i < getCount(); i++) {
api.getConnections(this);
api.getConnections(this::onReceiveConnections);
}
}
@Override
public void onReceiveConnections(Map<String, Connection> connections) {
mConnections = connections;
notifyDataSetChanged();

View file

@ -25,8 +25,7 @@ import static android.view.View.VISIBLE;
/**
* Generates item views for folder items.
*/
public class FoldersAdapter extends ArrayAdapter<Folder>
implements RestApi.OnReceiveModelListener {
public class FoldersAdapter extends ArrayAdapter<Folder> {
private final HashMap<String, Model> mModels = new HashMap<>();
private final LayoutInflater mInflater;
@ -100,11 +99,10 @@ public class FoldersAdapter extends ArrayAdapter<Folder>
*/
public void updateModel(RestApi api) {
for (int i = 0; i < getCount(); i++) {
api.getModel(getItem(i).id, this);
api.getModel(getItem(i).id, this::onReceiveModel);
}
}
@Override
public void onReceiveModel(String folderId, Model model) {
mModels.put(folderId, model);
notifyDataSetChanged();