App settings improvements (fixes #134, ref #122).

- removed options that aren't available in web GUI
- added options for local node name, announce servers and usage report
This commit is contained in:
Felix Ableitner 2015-01-20 00:43:47 +01:00
parent fea483764d
commit d7d35eb61e
7 changed files with 105 additions and 78 deletions

View File

@ -131,7 +131,7 @@ public class DeviceSettingsFragment extends PreferenceFragment implements
getActivity().setTitle(R.string.add_device); getActivity().setTitle(R.string.add_device);
} else { } else {
getActivity().setTitle(R.string.edit_device); getActivity().setTitle(R.string.edit_device);
List<RestApi.Device> devices = mSyncthingService.getApi().getDevices(); List<RestApi.Device> devices = mSyncthingService.getApi().getDevices(false);
for (int i = 0; i < devices.size(); i++) { for (int i = 0; i < devices.size(); i++) {
if (devices.get(i).DeviceID.equals( if (devices.get(i).DeviceID.equals(
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) { getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {

View File

@ -54,7 +54,7 @@ public class DevicesFragment extends ListFragment implements SyncthingService.On
return; return;
mAdapter = new DevicesAdapter(activity); mAdapter = new DevicesAdapter(activity);
mAdapter.add(activity.getApi().getDevices()); mAdapter.add(activity.getApi().getDevices(false));
setListAdapter(mAdapter); setListAdapter(mAdapter);
setEmptyText(getString(R.string.devices_list_empty)); setEmptyText(getString(R.string.devices_list_empty));
getListView().setOnItemClickListener(this); getListView().setOnItemClickListener(this);

View File

@ -148,7 +148,7 @@ public class FolderSettingsFragment extends PreferenceFragment
mRescanInterval.setText(Integer.toString(mFolder.RescanIntervalS)); mRescanInterval.setText(Integer.toString(mFolder.RescanIntervalS));
mRescanInterval.setSummary(Integer.toString(mFolder.RescanIntervalS)); mRescanInterval.setSummary(Integer.toString(mFolder.RescanIntervalS));
mFolderMaster.setChecked(mFolder.ReadOnly); mFolderMaster.setChecked(mFolder.ReadOnly);
List<RestApi.Device> devicesList = mSyncthingService.getApi().getDevices(); List<RestApi.Device> devicesList = mSyncthingService.getApi().getDevices(false);
for (RestApi.Device n : devicesList) { for (RestApi.Device n : devicesList) {
ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n); ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n);
// Calling addPreference later causes it to change the checked state. // Calling addPreference later causes it to change the checked state.
@ -297,7 +297,8 @@ public class FolderSettingsFragment extends PreferenceFragment
intent.putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY, mFolder.Path); intent.putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY, mFolder.Path);
} }
startActivityForResult(intent, DIRECTORY_REQUEST_CODE); startActivityForResult(intent, DIRECTORY_REQUEST_CODE);
} else if (preference.equals(mDevices) && mSyncthingService.getApi().getDevices().isEmpty()) { } else if (preference.equals(mDevices) &&
mSyncthingService.getApi().getDevices(false).isEmpty()) {
Toast.makeText(getActivity(), R.string.no_devices, Toast.LENGTH_SHORT) Toast.makeText(getActivity(), R.string.no_devices, Toast.LENGTH_SHORT)
.show(); .show();
} }

View File

@ -1,6 +1,5 @@
package com.nutomic.syncthingandroid.fragments; package com.nutomic.syncthingandroid.fragments;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
@ -29,6 +28,10 @@ public class SettingsFragment extends PreferenceFragment
private static final String SYNCTHING_GUI_KEY = "syncthing_gui"; private static final String SYNCTHING_GUI_KEY = "syncthing_gui";
private static final String DEVICE_NAME_KEY = "DeviceName";
private static final String USAGE_REPORT_ACCEPTED = "URAccepted";
private static final String SYNCTHING_VERSION_KEY = "syncthing_version"; private static final String SYNCTHING_VERSION_KEY = "syncthing_version";
private static final String APP_VERSION_KEY = "app_version"; private static final String APP_VERSION_KEY = "app_version";
@ -52,21 +55,33 @@ public class SettingsFragment extends PreferenceFragment
Preference syncthingVersion = getPreferenceScreen().findPreference(SYNCTHING_VERSION_KEY); Preference syncthingVersion = getPreferenceScreen().findPreference(SYNCTHING_VERSION_KEY);
syncthingVersion.setSummary(mSyncthingService.getApi().getVersion()); syncthingVersion.setSummary(mSyncthingService.getApi().getVersion());
RestApi api = mSyncthingService.getApi();
if (currentState == SyncthingService.State.ACTIVE) { if (currentState == SyncthingService.State.ACTIVE) {
for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) { for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) {
Preference pref = mOptionsScreen.getPreference(i); final Preference pref = mOptionsScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsFragment.this); pref.setOnPreferenceChangeListener(SettingsFragment.this);
String value = mSyncthingService.getApi() String value;
.getValue(RestApi.TYPE_OPTIONS, pref.getKey()); switch (pref.getKey()) {
case DEVICE_NAME_KEY:
value = api.getLocalDevice().Name;
break;
case USAGE_REPORT_ACCEPTED:
String v = api.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
value = (v.equals("1")) ? "true" : "false";
break;
default:
value = api.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
}
applyPreference(pref, value); applyPreference(pref, value);
} }
for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) { for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) {
Preference pref = mGuiScreen.getPreference(i); Preference pref = mGuiScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsFragment.this); pref.setOnPreferenceChangeListener(SettingsFragment.this);
String value = mSyncthingService.getApi() String value = api.getValue(RestApi.TYPE_GUI, pref.getKey());
.getValue(RestApi.TYPE_GUI, pref.getKey());
applyPreference(pref, value); applyPreference(pref, value);
} }
} }
@ -170,9 +185,23 @@ public class SettingsFragment extends PreferenceFragment
mSyncOnlyCharging.setEnabled((Boolean) o); mSyncOnlyCharging.setEnabled((Boolean) o);
mSyncOnlyWifi.setEnabled((Boolean) o); mSyncOnlyWifi.setEnabled((Boolean) o);
} else if (preference.getKey().equals(DEVICE_NAME_KEY)) {
RestApi.Device old = mSyncthingService.getApi().getLocalDevice();
RestApi.Device updated = new RestApi.Device();
updated.Addresses = old.Addresses;
updated.Compression = old.Compression;
updated.DeviceID = old.DeviceID;
updated.Introducer = old.Introducer;
updated.Name = (String) o;
mSyncthingService.getApi().editDevice(updated, getActivity(), null);
} else if (preference.getKey().equals(USAGE_REPORT_ACCEPTED)) {
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(),
((Boolean) o) ? 1 : 0, false, getActivity());
} else if (mOptionsScreen.findPreference(preference.getKey()) != null) { } else if (mOptionsScreen.findPreference(preference.getKey()) != null) {
boolean isArray = preference.getKey().equals("ListenAddress") ||
preference.getKey().equals("GlobalAnnServers");
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o, mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o,
preference.getKey().equals("ListenAddress"), getActivity()); isArray, getActivity());
} else if (mGuiScreen.findPreference(preference.getKey()) != null) { } else if (mGuiScreen.findPreference(preference.getKey()) != null) {
mSyncthingService.getApi().setValue( mSyncthingService.getApi().setValue(
RestApi.TYPE_GUI, preference.getKey(), o, false, getActivity()); RestApi.TYPE_GUI, preference.getKey(), o, false, getActivity());

View File

@ -25,7 +25,6 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import java.security.InvalidParameterException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -288,8 +287,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
try { try {
Object value = mConfig.getJSONObject(name).get(key); Object value = mConfig.getJSONObject(name).get(key);
return (value instanceof JSONArray) return (value instanceof JSONArray)
? ((JSONArray) value).join(" ").replace("\"", "") ? ((JSONArray) value).join(" ").replace("\"", "").replace("\\", "")
: String.valueOf(value); : value.toString();
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, "Failed to get value for " + key, e); Log.w(TAG, "Failed to get value for " + key, e);
return null; return null;
@ -392,13 +391,29 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
/** /**
* Returns a list of all existing devices. * Returns a list of all existing devices.
*
* @param includeLocal True if the local device should be included in the result.
*/ */
public List<Device> getDevices() { public List<Device> getDevices(boolean includeLocal) {
if (mConfig == null) if (mConfig == null)
return new ArrayList<>(); return new ArrayList<>();
try { try {
return getDevices(mConfig.getJSONArray("Devices")); JSONArray devices = mConfig.getJSONArray("Devices");
List<Device> ret = new ArrayList<>(devices.length());
for (int i = 0; i < devices.length(); i++) {
JSONObject json = devices.getJSONObject(i);
Device n = new Device();
n.Addresses = json.optJSONArray("Addresses").join(" ").replace("\"", "");
n.Name = json.getString("Name");
n.DeviceID = json.getString("DeviceID");
n.Compression = json.getBoolean("Compression");
n.Introducer = json.getBoolean("Introducer");
if (includeLocal || !mLocalDeviceId.equals(n.DeviceID)) {
ret.add(n);
}
}
return ret;
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, "Failed to read devices", e); Log.w(TAG, "Failed to read devices", e);
return null; return null;
@ -429,8 +444,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
SystemInfo si = new SystemInfo(); SystemInfo si = new SystemInfo();
si.alloc = system.getLong("alloc"); si.alloc = system.getLong("alloc");
si.cpuPercent = system.getDouble("cpuPercent"); si.cpuPercent = system.getDouble("cpuPercent");
if (system.has("extAnnounceOK")) {
JSONObject announce = system.getJSONObject("extAnnounceOK"); JSONObject announce = system.getJSONObject("extAnnounceOK");
si.extAnnounceConnected = 0;
si.extAnnounceTotal = announce.length(); si.extAnnounceTotal = announce.length();
for (Iterator<String> it = announce.keys(); it.hasNext(); ) { for (Iterator<String> it = announce.keys(); it.hasNext(); ) {
String key = it.next(); String key = it.next();
@ -438,6 +453,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
si.extAnnounceConnected++; si.extAnnounceConnected++;
} }
} }
}
si.goroutines = system.getInt("goroutines"); si.goroutines = system.getInt("goroutines");
si.myID = system.getString("myID"); si.myID = system.getString("myID");
si.sys = system.getLong("sys"); si.sys = system.getLong("sys");
@ -450,27 +466,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
} }
/** /**
* Returns a list of all devices in the array devices, excluding the local device. * Returns a list of all existing folders.
*/
private List<Device> getDevices(JSONArray devices) throws JSONException {
List<Device> ret = new ArrayList<>(devices.length());
for (int i = 0; i < devices.length(); i++) {
JSONObject json = devices.getJSONObject(i);
Device n = new Device();
n.Addresses = json.optJSONArray("Addresses").join(" ").replace("\"", "");
n.Name = json.getString("Name");
n.DeviceID = json.getString("DeviceID");
n.Compression = json.getBoolean("Compression");
n.Introducer = json.getBoolean("Introducer");
if (!n.DeviceID.equals(mLocalDeviceId)) {
ret.add(n);
}
}
return ret;
}
/**
* Returns a list of all existing foldersitores.
*/ */
public List<Folder> getFolders() { public List<Folder> getFolders() {
if (mConfig == null) if (mConfig == null)
@ -701,7 +697,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
* Updates or creates the given device, depending on whether it already exists. * Updates or creates the given device, depending on whether it already exists.
* *
* @param device Settings of the device to edit. To create a device, pass a non-existant device ID. * @param device Settings of the device to edit. To create a device, pass a non-existant device ID.
* @param listener {@link OnDeviceIdNormalizedListener} for the normalized device ID. * @param listener for the normalized device ID (may be null).
*/ */
public void editDevice(final Device device, final Activity activity, public void editDevice(final Device device, final Activity activity,
final OnDeviceIdNormalizedListener listener) { final OnDeviceIdNormalizedListener listener) {
@ -709,14 +705,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
new RestApi.OnDeviceIdNormalizedListener() { new RestApi.OnDeviceIdNormalizedListener() {
@Override @Override
public void onDeviceIdNormalized(String normalizedId, String error) { public void onDeviceIdNormalized(String normalizedId, String error) {
listener.onDeviceIdNormalized(normalizedId, error); if (listener != null) listener.onDeviceIdNormalized(normalizedId, error);
if (normalizedId == null) if (normalizedId == null)
return; return;
device.DeviceID = normalizedId; device.DeviceID = normalizedId;
// If the device already exists, just update it. // If the device already exists, just update it.
boolean create = true; boolean create = true;
for (RestApi.Device n : getDevices()) { for (RestApi.Device n : getDevices(true)) {
if (n.DeviceID.equals(device.DeviceID)) { if (n.DeviceID.equals(device.DeviceID)) {
create = false; create = false;
} }
@ -935,4 +931,16 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
relativePath); relativePath);
} }
/**
* Returns the object representing the local device.
*/
public Device getLocalDevice() {
for (Device d : getDevices(true)) {
if (d.DeviceID.equals(mLocalDeviceId)) {
return d;
}
}
return new Device();
}
} }

View File

@ -218,26 +218,24 @@ Please report any problems you encounter via Github.</string>
<string name="syncthing_options">Syncthing Options</string> <string name="syncthing_options">Syncthing Options</string>
<string name="device_name">Device Name</string>
<string name="listen_address">Sync Protocol Listen Addresses</string> <string name="listen_address">Sync Protocol Listen Addresses</string>
<string name="max_recv_kbps">Incoming Rate Limit (KiB/s)</string> <string name="max_recv_kbps">Incoming Rate Limit (KiB/s)</string>
<string name="max_send_kbps">Outgoing Rate Limit (KiB/s)</string> <string name="max_send_kbps">Outgoing Rate Limit (KiB/s)</string>
<string name="reconnect_interval">Reconnect Interval (s)</string>
<string name="parallell_requests">Max Outstanding Requests</string>
<string name="max_change_kbps">Max File Change Rate (KiB/s)</string>
<string name="global_announce_enabled">Global Discovery</string> <string name="global_announce_enabled">Global Discovery</string>
<string name="local_announce_enabled">Local Discovery</string> <string name="local_announce_enabled">Local Discovery</string>
<string name="local_announce_port">Local Discovery Port</string>
<string name="upnp_enabled">Enable UPnP</string> <string name="upnp_enabled">Enable UPnP</string>
<string name="global_announce_server">Global Discovery Server</string>
<string name="usage_reporting">Anonymous Usage Reporting</string>
<string name="syncthing_gui">Syncthing GUI</string> <string name="syncthing_gui">Syncthing GUI</string>
<string name="gui_address">GUI Listen Addresses</string> <string name="gui_address">GUI Listen Addresses</string>

View File

@ -26,10 +26,13 @@
android:title="@string/syncthing_options" android:title="@string/syncthing_options"
android:persistent="false"> android:persistent="false">
<EditTextPreference
android:key="DeviceName"
android:title="@string/device_name" />
<EditTextPreference <EditTextPreference
android:key="ListenAddress" android:key="ListenAddress"
android:title="@string/listen_address" android:title="@string/listen_address" />
android:defaultValue="0.0.0.0:22000" />
<EditTextPreference <EditTextPreference
android:key="MaxRecvKbps" android:key="MaxRecvKbps"
@ -41,21 +44,6 @@
android:title="@string/max_send_kbps" android:title="@string/max_send_kbps"
android:numeric="integer" /> android:numeric="integer" />
<EditTextPreference
android:key="ReconnectIntervalS"
android:title="@string/reconnect_interval"
android:numeric="integer" />
<EditTextPreference
android:key="ParallelRequests"
android:title="@string/parallell_requests"
android:numeric="integer" />
<EditTextPreference
android:key="MaxChangeKbps"
android:title="@string/max_change_kbps"
android:numeric="integer" />
<CheckBoxPreference <CheckBoxPreference
android:key="GlobalAnnEnabled" android:key="GlobalAnnEnabled"
android:title="@string/global_announce_enabled" /> android:title="@string/global_announce_enabled" />
@ -64,15 +52,18 @@
android:key="LocalAnnEnabled" android:key="LocalAnnEnabled"
android:title="@string/local_announce_enabled" /> android:title="@string/local_announce_enabled" />
<EditTextPreference
android:key="LocalAnnPort"
android:title="@string/local_announce_port"
android:numeric="integer" />
<CheckBoxPreference <CheckBoxPreference
android:key="UPnPEnabled" android:key="UPnPEnabled"
android:title="@string/upnp_enabled" /> android:title="@string/upnp_enabled" />
<EditTextPreference
android:key="GlobalAnnServers"
android:title="@string/global_announce_server" />
<CheckBoxPreference
android:key="URAccepted"
android:title="@string/usage_reporting" />
</PreferenceScreen> </PreferenceScreen>
<PreferenceScreen <PreferenceScreen