1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-01 16:51:16 +00:00

Add locally discovered devices to the "add device" dialog (fixes #305) (#306)

* ENABLE_TEST_DATA

* http/GetRequest: Add URI_SYSTEM_DISCOVERY

* Add model/DiscoveredDevice

* Add RestApi#getDiscoveredDevices (fixes #305)

* Add DeviceActivity#asyncQueryDiscoveredDevices in onServiceConnected (fixes #305)

* Add strings

* Add layout: item_discovered_device_form

* Add discoveredDevicesTitle, discoveredDevicesContainer to "add device" dialog (fixes #305)

* Revert "ENABLE_TEST_DATA"

This reverts commit b2efe73b9b4f7e9d4db8cc50cb48a5422f78c084.

* Fix lint error

* Updated de translation
This commit is contained in:
Catfriend1 2019-02-08 18:35:45 +01:00 committed by GitHub
parent f5bb5473e6
commit 1163b1ec83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 189 additions and 0 deletions

View file

@ -14,11 +14,15 @@ import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -29,6 +33,7 @@ import com.google.zxing.integration.android.IntentResult;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.model.DiscoveredDevice;
import com.nutomic.syncthingandroid.service.Constants;
import com.nutomic.syncthingandroid.service.RestApi;
import com.nutomic.syncthingandroid.service.SyncthingService;
@ -42,12 +47,19 @@ import com.nutomic.syncthingandroid.util.Util;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import static android.support.v4.view.MarginLayoutParamsCompat.setMarginEnd;
import static android.support.v4.view.MarginLayoutParamsCompat.setMarginStart;
import static android.text.TextUtils.isEmpty;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.nutomic.syncthingandroid.util.Compression.METADATA;
/**
@ -75,6 +87,8 @@ public class DeviceActivity extends SyncthingActivity {
private Device mDevice;
private EditText mEditDeviceId;
private TextView mDiscoveredDevicesTitle;
private ViewGroup mDiscoveredDevicesContainer;
private View mShowDeviceIdContainer;
private EditText mShowDeviceId;
private View mQrButton;
@ -182,6 +196,8 @@ public class DeviceActivity extends SyncthingActivity {
setTitle(mIsCreateMode ? R.string.add_device : R.string.edit_device);
mEditDeviceId = findViewById(R.id.editDeviceId);
mDiscoveredDevicesTitle = findViewById(R.id.discoveredDevicesTitle);
mDiscoveredDevicesContainer = findViewById(R.id.discoveredDevicesContainer);
mShowDeviceIdContainer = findViewById(R.id.showDeviceIdContainer);
mShowDeviceId = findViewById(R.id.showDeviceId);
mQrButton = findViewById(R.id.qrButton);
@ -276,6 +292,9 @@ public class DeviceActivity extends SyncthingActivity {
RestApi restApi = syncthingService.getApi();
if (restApi != null) {
restApi.getConnections(this::onReceiveConnections);
if (mIsCreateMode) {
asyncQueryDiscoveredDevices(restApi);
}
}
}
@ -615,4 +634,83 @@ public class DeviceActivity extends SyncthingActivity {
.create();
mDiscardDialog.show();
}
/**
* Perform asynchronous query via REST to retrieve locally discovered devices.
* Precondition:
* restApi != null
* mIsCreateMode == true
*/
private void asyncQueryDiscoveredDevices(RestApi restApi) {
if (!restApi.isConfigLoaded()) {
return;
}
restApi.getDiscoveredDevices(this::onReceiveDiscoveredDevices);
}
/**
* Callback after {@link asyncQueryDiscoveredDevices}.
* Precondition:
* mIsCreateMode == true
*/
private void onReceiveDiscoveredDevices(Map<String, DiscoveredDevice> discoveredDevices) {
if (discoveredDevices == null) {
Log.e(TAG, "onReceiveDiscoveredDevices: discoveredDevices == null");
return;
}
mDiscoveredDevicesContainer.removeAllViews();
if (discoveredDevices.size() == 0) {
// No discovered devices.
int height = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, 48, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WRAP_CONTENT, height);
int dividerInset = getResources().getDimensionPixelOffset(R.dimen.material_divider_inset);
int contentInset = getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_content_inset_material);
setMarginStart(params, dividerInset);
setMarginEnd(params, contentInset);
TextView emptyView = new TextView(mDiscoveredDevicesContainer.getContext());
emptyView.setGravity(CENTER_VERTICAL);
emptyView.setText(R.string.discovered_device_list_empty);
mDiscoveredDevicesContainer.addView(emptyView, params);
return;
}
for (String deviceId : discoveredDevices.keySet()) {
if (deviceId != null) {
// Get device address.
String readableAddresses = "";
DiscoveredDevice discoveredDevice = discoveredDevices.get(deviceId);
if (discoveredDevice != null && discoveredDevice.addresses != null) {
readableAddresses = TextUtils.join(", ", discoveredDevice.addresses);
// Log.v(TAG, "onReceiveDiscoveredDevices: deviceID = '" + deviceId + "' has addresses '" + readableAddresses + "'");
}
String caption = deviceId + (TextUtils.isEmpty(readableAddresses) ? "" : " (" + readableAddresses + ")");
LayoutInflater inflater = getLayoutInflater();
inflater.inflate(R.layout.item_discovered_device_form, mDiscoveredDevicesContainer);
TextView deviceIdView = (TextView) mDiscoveredDevicesContainer.getChildAt(mDiscoveredDevicesContainer.getChildCount()-1);
deviceIdView.setOnClickListener(null);
deviceIdView.setText(caption);
deviceIdView.setTag(deviceId);
deviceIdView.setOnClickListener(v -> onDeviceIdViewClick(v));
}
}
/**
* If "mEditDeviceId" already contains content, don't show local discovery results.
* This also suppresses the results being shown a second time after the user chose a
* deviceId from the list and rotated the screen.
*/
mDiscoveredDevicesTitle.setVisibility(TextUtils.isEmpty(mEditDeviceId.getText()) ? View.VISIBLE : View.GONE);
mDiscoveredDevicesContainer.setVisibility(TextUtils.isEmpty(mEditDeviceId.getText()) ? View.VISIBLE : View.GONE);
}
/**
* Copies the deviceId from TextView to "device_id" EditText.
* Hides the "mDiscoveredDevicesContainer" view afterwards.
*/
private void onDeviceIdViewClick(View view) {
mEditDeviceId.setText((String) view.getTag());
mDiscoveredDevicesTitle.setVisibility(View.GONE);
mDiscoveredDevicesContainer.setVisibility(View.GONE);
}
}

View file

@ -18,6 +18,7 @@ public class GetRequest extends ApiRequest {
public static final String URI_CONFIG = "/rest/system/config";
public static final String URI_DEBUG = "/rest/system/debug";
public static final String URI_SYSTEM_DISCOVERY = "/rest/system/discovery";
public static final String URI_VERSION = "/rest/system/version";
public static final String URI_SYSTEM_STATUS = "/rest/system/status";
public static final String URI_CONNECTIONS = "/rest/system/connections";

View file

@ -0,0 +1,22 @@
package com.nutomic.syncthingandroid.model;
import java.util.Map;
/**
* This receives the deserialization result of the URI_SYSTEM_DISCOVERY query.
*
* JSON result example
* {
* "2MY7NNQ-IRBZIFP-B2V574Y-AX6FNIP-55VGH5H-GUD3RFV-K2RXX6P-XXXXXX":
* {
* "addresses":
* [
* "tcp4://192.168.178.10:40001"
* ]
* }
* }
*
*/
public class DiscoveredDevice {
public String[] addresses;
}

View file

@ -26,6 +26,7 @@ import com.nutomic.syncthingandroid.model.Completion;
import com.nutomic.syncthingandroid.model.CompletionInfo;
import com.nutomic.syncthingandroid.model.Connections;
import com.nutomic.syncthingandroid.model.Device;
import com.nutomic.syncthingandroid.model.DiscoveredDevice;
import com.nutomic.syncthingandroid.model.DiskEvent;
import com.nutomic.syncthingandroid.model.Event;
import com.nutomic.syncthingandroid.model.Folder;
@ -618,6 +619,23 @@ public class RestApi {
}
}
/**
* Requests locally discovered devices.
*/
public void getDiscoveredDevices(OnResultListener1<Map<String, DiscoveredDevice>> listener) {
new GetRequest(mContext, mUrl, GetRequest.URI_SYSTEM_DISCOVERY, mApiKey,
null, result -> {
Map<String, DiscoveredDevice> discoveredDevices = mGson.fromJson(result, new TypeToken<Map<String, DiscoveredDevice>>(){}.getType());
if (ENABLE_TEST_DATA) {
DiscoveredDevice fakeDiscoveredDevice = new DiscoveredDevice();
fakeDiscoveredDevice.addresses = new String[]{"tcp4://192.168.178.10:40004"};
discoveredDevices.put("ZOK75WR-W3XWWUZ-NNLXV7V-DUYKVWA-SSPD7OH-3QYOZBY-SBH3N2Y-IAVJ4QH", fakeDiscoveredDevice);
discoveredDevices.put("ZPUZOWC-SUCJILE-ITNLBLL-MHBWJG5-46QM47Y-CDTQT3M-IA4RSJV-7BYA7QA", fakeDiscoveredDevice);
}
listener.onResult(discoveredDevices);
});
}
/**
* Requests ignore list for given folder.
*/

View file

@ -56,6 +56,26 @@
</LinearLayout>
<TextView
style="@style/Widget.Syncthing.TextView.Label.Details"
android:id="@+id/discoveredDevicesTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_device_hub_black_24dp_active"
android:drawableStart="@drawable/ic_device_hub_black_24dp_active"
android:focusable="false"
android:text="@string/discovered_devices_title"
android:visibility="gone" />
<LinearLayout
android:id="@+id/discoveredDevicesContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusable="false"
android:visibility="gone">
</LinearLayout>
<!-- Option 2: Show or copy device ID -->
<LinearLayout
android:id="@+id/showDeviceIdContainer"

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/device_button"
style="@style/Widget.Syncthing.TextView.Label.Details.DeviceList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/material_divider_inset"
android:layout_marginStart="@dimen/material_divider_inset"
android:layout_marginEnd="@dimen/abc_action_bar_content_inset_material"
android:layout_marginRight="@dimen/abc_action_bar_content_inset_material"
android:clickable="true"
android:drawableEnd="@drawable/ic_content_copy_black_24dp"
android:drawableRight="@drawable/ic_content_copy_black_24dp"
android:focusable="true"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="ASD1ASD-ASD1ASD-ASD1ASD-ASD1ASD-ASD1ASD-ASD1ASD-ASD1ASD-ASD1ASD" />

View file

@ -257,6 +257,12 @@ Bitte melden Sie auftretende Probleme via GitHub.</string>
<!-- Setting title -->
<string name="device_id">Geräte-ID</string>
<!-- Status title -->
<string name="discovered_devices_title">Gefundene Geräte - Tippe zur Auswahl</string>
<!-- Status text -->
<string name="discovered_device_list_empty">Die lokale Geräteerkennung hat im lokalen Netzwerk keine Geräte gefunden.</string>
<!-- Setting title -->
<string name="name">Name</string>

View file

@ -260,6 +260,12 @@ Please report any problems you encounter via Github.</string>
<!-- Setting title -->
<string name="device_id">Device ID</string>
<!-- Status title -->
<string name="discovered_devices_title">Discovered devices - Tap to select</string>
<!-- Status text -->
<string name="discovered_device_list_empty">Local discovery didn\'t find any devices on the local network.</string>
<!-- Setting title -->
<string name="name">Name</string>