Updated device details styling.
Made actionmode bar overlay the toolbar. Updated UI for device edit/create fragment to match the folder one. Refactored FolderFragment to match DeviceFragment. Improvements for Details styles and item heights.
|
@ -3,7 +3,7 @@ package com.nutomic.syncthingandroid.test.activities;
|
|||
import android.test.ActivityInstrumentationTestCase2;
|
||||
|
||||
import com.nutomic.syncthingandroid.activities.MainActivity;
|
||||
import com.nutomic.syncthingandroid.fragments.DevicesFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.DeviceListFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.FolderListFragment;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingServiceBinder;
|
||||
import com.nutomic.syncthingandroid.test.MockSyncthingService;
|
||||
|
@ -20,7 +20,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
|||
getActivity().onServiceConnected(null, new SyncthingServiceBinder(mService));
|
||||
assertTrue(mService.containsListenerInstance(MainActivity.class));
|
||||
assertTrue(mService.containsListenerInstance(FolderListFragment.class));
|
||||
assertTrue(mService.containsListenerInstance(DevicesFragment.class));
|
||||
assertTrue(mService.containsListenerInstance(DeviceListFragment.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@
|
|||
android:value="splitActionBarWhenNarrow" />
|
||||
</activity>
|
||||
<activity android:name=".activities.RestartActivity"
|
||||
android:theme="@style/Theme.Syncthing.Translucent"/>
|
||||
android:theme="@style/Theme.Syncthing.Translucent"
|
||||
android:launchMode="singleTop"/>
|
||||
|
||||
<service android:name=".syncthing.SyncthingService" />
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import android.view.ViewGroup;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.fragments.DevicesFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.DeviceListFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.DrawerFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.FolderListFragment;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
|
@ -45,8 +45,8 @@ import static java.lang.Math.min;
|
|||
|
||||
/**
|
||||
* Shows {@link FolderListFragment} and
|
||||
* {@link com.nutomic.syncthingandroid.fragments.DevicesFragment} in different tabs, and
|
||||
* {@link com.nutomic.syncthingandroid.fragments.DrawerFragment} in the navigation drawer.
|
||||
* {@link DeviceListFragment} in different tabs, and
|
||||
* {@link DrawerFragment} in the navigation drawer.
|
||||
*/
|
||||
public class MainActivity extends SyncthingActivity
|
||||
implements SyncthingService.OnApiChangeListener {
|
||||
|
@ -161,9 +161,9 @@ public class MainActivity extends SyncthingActivity
|
|||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return mFolderFragment;
|
||||
return mFolderListFragment;
|
||||
case 1:
|
||||
return mDevicesFragment;
|
||||
return mDeviceListFragment;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -187,9 +187,9 @@ public class MainActivity extends SyncthingActivity
|
|||
}
|
||||
};
|
||||
|
||||
private FolderListFragment mFolderFragment;
|
||||
private FolderListFragment mFolderListFragment;
|
||||
|
||||
private DevicesFragment mDevicesFragment;
|
||||
private DeviceListFragment mDeviceListFragment;
|
||||
|
||||
private DrawerFragment mDrawerFragment;
|
||||
|
||||
|
@ -216,16 +216,16 @@ public class MainActivity extends SyncthingActivity
|
|||
|
||||
if (savedInstanceState != null) {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
mFolderFragment = (FolderListFragment) fm.getFragment(
|
||||
mFolderListFragment = (FolderListFragment) fm.getFragment(
|
||||
savedInstanceState, FolderListFragment.class.getName());
|
||||
mDevicesFragment = (DevicesFragment) fm.getFragment(
|
||||
savedInstanceState, DevicesFragment.class.getName());
|
||||
mDeviceListFragment = (DeviceListFragment) fm.getFragment(
|
||||
savedInstanceState, DeviceListFragment.class.getName());
|
||||
mDrawerFragment = (DrawerFragment) fm.getFragment(
|
||||
savedInstanceState, DrawerFragment.class.getName());
|
||||
mViewPager.setCurrentItem(savedInstanceState.getInt("currentTab"));
|
||||
} else {
|
||||
mFolderFragment = new FolderListFragment();
|
||||
mDevicesFragment = new DevicesFragment();
|
||||
mFolderListFragment = new FolderListFragment();
|
||||
mDeviceListFragment = new DeviceListFragment();
|
||||
mDrawerFragment = new DrawerFragment();
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,8 @@ public class MainActivity extends SyncthingActivity
|
|||
}
|
||||
if (getService() != null) {
|
||||
getService().unregisterOnApiChangeListener(this);
|
||||
getService().unregisterOnApiChangeListener(mFolderFragment);
|
||||
getService().unregisterOnApiChangeListener(mDevicesFragment);
|
||||
getService().unregisterOnApiChangeListener(mFolderListFragment);
|
||||
getService().unregisterOnApiChangeListener(mDeviceListFragment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,8 +256,8 @@ public class MainActivity extends SyncthingActivity
|
|||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||
super.onServiceConnected(componentName, iBinder);
|
||||
getService().registerOnApiChangeListener(this);
|
||||
getService().registerOnApiChangeListener(mFolderFragment);
|
||||
getService().registerOnApiChangeListener(mDevicesFragment);
|
||||
getService().registerOnApiChangeListener(mFolderListFragment);
|
||||
getService().registerOnApiChangeListener(mDeviceListFragment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,10 +267,10 @@ public class MainActivity extends SyncthingActivity
|
|||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// Avoid crash if called during startup.
|
||||
if (mFolderFragment != null && mDevicesFragment != null && mDrawerFragment != null) {
|
||||
if (mFolderListFragment != null && mDeviceListFragment != null && mDrawerFragment != null) {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
fm.putFragment(outState, FolderListFragment.class.getName(), mFolderFragment);
|
||||
fm.putFragment(outState, DevicesFragment.class.getName(), mDevicesFragment);
|
||||
fm.putFragment(outState, FolderListFragment.class.getName(), mFolderListFragment);
|
||||
fm.putFragment(outState, DeviceListFragment.class.getName(), mDeviceListFragment);
|
||||
fm.putFragment(outState, DrawerFragment.class.getName(), mDrawerFragment);
|
||||
outState.putInt("currentTab", mViewPager.getCurrentItem());
|
||||
}
|
||||
|
|
|
@ -3,10 +3,9 @@ package com.nutomic.syncthingandroid.activities;
|
|||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.View;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.fragments.DeviceSettingsFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.DeviceFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.FolderFragment;
|
||||
import com.nutomic.syncthingandroid.fragments.SettingsFragment;
|
||||
|
||||
|
@ -27,7 +26,7 @@ public class SettingsActivity extends SyncthingActivity {
|
|||
* edited or a new one created.
|
||||
* <p/>
|
||||
* If this is false, {@link FolderFragment#EXTRA_REPO_ID} or
|
||||
* {@link com.nutomic.syncthingandroid.fragments.DeviceSettingsFragment#EXTRA_NODE_ID} must be set (according to the selected fragment).
|
||||
* {@link DeviceFragment#EXTRA_NODE_ID} must be set (according to the selected fragment).
|
||||
*/
|
||||
public static final String EXTRA_IS_CREATE = "create";
|
||||
|
||||
|
@ -50,7 +49,7 @@ public class SettingsActivity extends SyncthingActivity {
|
|||
mFragment = new SettingsFragment();
|
||||
break;
|
||||
case ACTION_NODE_SETTINGS_FRAGMENT:
|
||||
mFragment = new DeviceSettingsFragment();
|
||||
mFragment = new DeviceFragment();
|
||||
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
|
||||
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
|
||||
}
|
||||
|
@ -87,16 +86,4 @@ public class SettingsActivity extends SyncthingActivity {
|
|||
public boolean getIsCreate() {
|
||||
return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for the QR code scanner in DeviceSettingsFragment.
|
||||
*
|
||||
* Instead of the cast, an interface could be used (if there are multiple fragments using this).
|
||||
*/
|
||||
public void onClick(View view) {
|
||||
if (mFragment instanceof DeviceSettingsFragment) {
|
||||
((DeviceSettingsFragment) mFragment).onClick(view);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,425 @@
|
|||
package com.nutomic.syncthingandroid.fragments;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.activities.SettingsActivity;
|
||||
import com.nutomic.syncthingandroid.activities.SyncthingActivity;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.util.BarcodeIntentIntegrator;
|
||||
import com.nutomic.syncthingandroid.util.BarcodeIntentResult;
|
||||
import com.nutomic.syncthingandroid.util.Compression;
|
||||
import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
|
||||
import static com.nutomic.syncthingandroid.syncthing.SyncthingService.State.ACTIVE;
|
||||
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 static final String EXTRA_NODE_ID = "device_id";
|
||||
|
||||
private static final String TAG = "DeviceSettingsFragment";
|
||||
|
||||
private static final String DYNAMIC_ADDRESSES = "dynamic";
|
||||
|
||||
private SyncthingService mSyncthingService;
|
||||
|
||||
private RestApi.Device mDevice;
|
||||
|
||||
private View mIdContainer;
|
||||
|
||||
private EditText mIdView;
|
||||
|
||||
private View mQrButton;
|
||||
|
||||
private EditText mNameView;
|
||||
|
||||
private EditText mAddressesView;
|
||||
|
||||
private TextView mCurrentAddressView;
|
||||
|
||||
private TextView mCompressionValueView;
|
||||
|
||||
private SwitchCompat mIntroducerView;
|
||||
|
||||
private TextView mSyncthingVersionView;
|
||||
|
||||
private View mCompressionContainer;
|
||||
|
||||
private boolean mIsCreateMode;
|
||||
|
||||
private boolean mDeviceNeedsToUpdate;
|
||||
|
||||
private DialogInterface.OnClickListener mCompressionEntrySelectedListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
Compression compression = Compression.fromIndex(which);
|
||||
// Don't pop the restart dialog unless the value is actually different.
|
||||
if (compression != Compression.fromValue(getActivity(), mDevice.compression)) {
|
||||
mDeviceNeedsToUpdate = true;
|
||||
|
||||
mDevice.compression = compression.getValue(getActivity());
|
||||
mCompressionValueView.setText(compression.getTitle(getActivity()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private TextWatcher mIdTextWatcher = new TextWatcherAdapter() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (!s.toString().equals(mDevice.deviceID)) {
|
||||
mDeviceNeedsToUpdate = true;
|
||||
|
||||
mDevice.deviceID = s.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private TextWatcher mNameTextWatcher = new TextWatcherAdapter() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (!s.toString().equals(mDevice.name)) {
|
||||
mDeviceNeedsToUpdate = true;
|
||||
|
||||
mDevice.name = s.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private TextWatcher mAddressesTextWatcher = new TextWatcherAdapter() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (!s.toString().equals(mDevice.addresses)) {
|
||||
mDeviceNeedsToUpdate = true;
|
||||
|
||||
mDevice.addresses = persistableAddresses(s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private CompoundButton.OnCheckedChangeListener mIntroducerCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (mDevice.introducer != isChecked) {
|
||||
mDeviceNeedsToUpdate = true;
|
||||
|
||||
mDevice.introducer = isChecked;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
mIsCreateMode = activity.getIsCreate();
|
||||
activity.registerOnServiceConnectedListener(this);
|
||||
activity.setTitle(mIsCreateMode ? R.string.add_device : R.string.edit_device);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (mIsCreateMode) {
|
||||
if (savedInstanceState != null) {
|
||||
mDevice = (RestApi.Device) savedInstanceState.getSerializable("device");
|
||||
}
|
||||
if (mDevice == null) {
|
||||
initDevice();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mSyncthingService != null) {
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// We don't want to update every time a TextView's character changes,
|
||||
// so we hold off until the view stops being visible to the user.
|
||||
if (mDeviceNeedsToUpdate) {
|
||||
updateDevice();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current settings in case we are in create mode and they aren't yet stored in the config.
|
||||
*/
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable("device", mDevice);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_device, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mIdContainer = view.findViewById(R.id.idContainer);
|
||||
mIdView = (EditText) view.findViewById(R.id.id);
|
||||
mQrButton = view.findViewById(R.id.qrButton);
|
||||
mNameView = (EditText) view.findViewById(R.id.name);
|
||||
mAddressesView = (EditText) view.findViewById(R.id.addresses);
|
||||
mCurrentAddressView = (TextView) view.findViewById(R.id.currentAddress);
|
||||
mCompressionContainer = view.findViewById(R.id.compressionContainer);
|
||||
mCompressionValueView = (TextView) view.findViewById(R.id.compressionValue);
|
||||
mIntroducerView = (SwitchCompat) view.findViewById(R.id.introducer);
|
||||
mSyncthingVersionView = (TextView) view.findViewById(R.id.syncthingVersion);
|
||||
|
||||
mQrButton.setOnClickListener(this);
|
||||
mCompressionContainer.setOnClickListener(this);
|
||||
|
||||
if (!mIsCreateMode) {
|
||||
prepareEditMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
mIdView.removeTextChangedListener(mIdTextWatcher);
|
||||
mNameView.removeTextChangedListener(mNameTextWatcher);
|
||||
mAddressesView.removeTextChangedListener(mAddressesTextWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets version and current address of the device.
|
||||
* <p/>
|
||||
* 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, RestApi.Connection> connections) {
|
||||
boolean viewsExist = mSyncthingVersionView != null && mCurrentAddressView != null;
|
||||
if (viewsExist && connections.containsKey(mDevice.deviceID)) {
|
||||
mCurrentAddressView.setVisibility(VISIBLE);
|
||||
mSyncthingVersionView.setVisibility(VISIBLE);
|
||||
mCurrentAddressView.setText(connections.get(mDevice.deviceID).address);
|
||||
mSyncthingVersionView.setText(connections.get(mDevice.deviceID).clientVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (currentState != ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIsCreateMode) {
|
||||
List<RestApi.Device> devices = mSyncthingService.getApi().getDevices(false);
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
if (devices.get(i).deviceID.equals(
|
||||
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {
|
||||
mDevice = devices.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mDevice == null) {
|
||||
Log.w(TAG, "Device not found in API update");
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mSyncthingService.getApi().getConnections(this);
|
||||
|
||||
updateViewsAndSetListeners();
|
||||
}
|
||||
|
||||
private void updateViewsAndSetListeners() {
|
||||
// Update views
|
||||
mIdView.setText(mDevice.deviceID);
|
||||
mNameView.setText((mDevice.name));
|
||||
mAddressesView.setText(displayableAddresses());
|
||||
mCompressionValueView.setText(Compression.fromValue(getActivity(), mDevice.compression).getTitle(getActivity()));
|
||||
mIntroducerView.setChecked(mDevice.introducer);
|
||||
|
||||
// Keep state updated
|
||||
mIdView.addTextChangedListener(mIdTextWatcher);
|
||||
mNameView.addTextChangedListener(mNameTextWatcher);
|
||||
mAddressesView.addTextChangedListener(mAddressesTextWatcher);
|
||||
mIntroducerView.setOnCheckedChangeListener(mIntroducerCheckedChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.device_settings, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(R.id.create).setVisible(mIsCreateMode);
|
||||
menu.findItem(R.id.share_device_id).setVisible(!mIsCreateMode);
|
||||
menu.findItem(R.id.delete).setVisible(!mIsCreateMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.create:
|
||||
if (isEmpty(mDevice.deviceID)) {
|
||||
Toast.makeText(getActivity(), R.string.device_id_required, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
if (isEmpty(mDevice.name)) {
|
||||
Toast.makeText(getActivity(), R.string.device_name_required, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
mSyncthingService.getApi().editDevice(mDevice, getActivity(), this);
|
||||
getActivity().finish();
|
||||
return true;
|
||||
case R.id.share_device_id:
|
||||
RestApi.shareDeviceId(getActivity(), mDevice.deviceID);
|
||||
return true;
|
||||
case R.id.delete:
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.delete_device_confirm)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
mSyncthingService.getApi().deleteDevice(mDevice, getActivity());
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
return true;
|
||||
case android.R.id.home:
|
||||
getActivity().finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives value of scanned QR code and sets it as device ID.
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
BarcodeIntentResult scanResult = BarcodeIntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
|
||||
if (scanResult != null) {
|
||||
mDevice.deviceID = scanResult.getContents();
|
||||
mIdView.setText(mDevice.deviceID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 RestApi.Device();
|
||||
mDevice.name = "";
|
||||
mDevice.deviceID = "";
|
||||
mDevice.addresses = "dynamic";
|
||||
mDevice.compression = METADATA.getValue(getActivity());
|
||||
mDevice.introducer = false;
|
||||
}
|
||||
|
||||
private void prepareEditMode() {
|
||||
getActivity().getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
|
||||
mIdView.setEnabled(false);
|
||||
mQrButton.setVisibility(GONE);
|
||||
|
||||
mIdContainer.setOnClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the updated device info if in edit mode.
|
||||
*/
|
||||
private void updateDevice() {
|
||||
if (!mIsCreateMode && mDeviceNeedsToUpdate) {
|
||||
mSyncthingService.getApi().editDevice(mDevice, getActivity(), this);
|
||||
}
|
||||
}
|
||||
|
||||
private String persistableAddresses(CharSequence userInput) {
|
||||
return isEmpty(userInput) ? DYNAMIC_ADDRESSES : userInput.toString();
|
||||
}
|
||||
|
||||
private String displayableAddresses() {
|
||||
return DYNAMIC_ADDRESSES.equals(mDevice.addresses) ? "" : mDevice.addresses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(mCompressionContainer)) {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.compression)
|
||||
.setSingleChoiceItems(R.array.compress_entries,
|
||||
Compression.fromValue(getActivity(), mDevice.compression).getIndex(),
|
||||
mCompressionEntrySelectedListener)
|
||||
.show();
|
||||
} else if (v.equals(mQrButton)){
|
||||
BarcodeIntentIntegrator integrator = new BarcodeIntentIntegrator(DeviceFragment.this);
|
||||
integrator.initiateScan();
|
||||
} else if (v.equals(mIdContainer)) {
|
||||
mSyncthingService.getApi().copyDeviceId(mDevice.deviceID);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import java.util.TimerTask;
|
|||
/**
|
||||
* Displays a list of all existing devices.
|
||||
*/
|
||||
public class DevicesFragment extends ListFragment implements SyncthingService.OnApiChangeListener,
|
||||
public class DeviceListFragment extends ListFragment implements SyncthingService.OnApiChangeListener,
|
||||
ListView.OnItemClickListener {
|
||||
|
||||
private DevicesAdapter mAdapter;
|
||||
|
@ -96,7 +96,7 @@ public class DevicesFragment extends ListFragment implements SyncthingService.On
|
|||
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
||||
intent.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT);
|
||||
intent.putExtra(SettingsActivity.EXTRA_IS_CREATE, false);
|
||||
intent.putExtra(DeviceSettingsFragment.EXTRA_NODE_ID, mAdapter.getItem(i).deviceID);
|
||||
intent.putExtra(DeviceFragment.EXTRA_NODE_ID, mAdapter.getItem(i).deviceID);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
|
@ -1,330 +0,0 @@
|
|||
package com.nutomic.syncthingandroid.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.preference.PreferenceFragment;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.activities.SettingsActivity;
|
||||
import com.nutomic.syncthingandroid.activities.SyncthingActivity;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.util.BarcodeIntentIntegrator;
|
||||
import com.nutomic.syncthingandroid.util.BarcodeIntentResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Shows device details and allows changing them.
|
||||
*/
|
||||
public class DeviceSettingsFragment extends PreferenceFragment implements
|
||||
SyncthingActivity.OnServiceConnectedListener, Preference.OnPreferenceChangeListener,
|
||||
Preference.OnPreferenceClickListener, RestApi.OnReceiveConnectionsListener,
|
||||
SyncthingService.OnApiChangeListener, RestApi.OnDeviceIdNormalizedListener {
|
||||
|
||||
public static final String EXTRA_NODE_ID = "device_id";
|
||||
|
||||
private static final String TAG = "DeviceSettingsFragment";
|
||||
|
||||
private static final int SCAN_QR_REQUEST_CODE = 235;
|
||||
|
||||
private SyncthingService mSyncthingService;
|
||||
|
||||
private RestApi.Device mDevice;
|
||||
|
||||
private Preference mDeviceId;
|
||||
|
||||
private EditTextPreference mName;
|
||||
|
||||
private EditTextPreference mAddresses;
|
||||
|
||||
private ListPreference mCompression;
|
||||
|
||||
private CheckBoxPreference mIntroducer;
|
||||
|
||||
private Preference mVersion;
|
||||
|
||||
private Preference mCurrentAddress;
|
||||
|
||||
private boolean mIsCreate;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
|
||||
|
||||
mIsCreate = ((SettingsActivity) getActivity()).getIsCreate();
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (mIsCreate) {
|
||||
addPreferencesFromResource(R.xml.device_settings_create);
|
||||
} else {
|
||||
addPreferencesFromResource(R.xml.device_settings_edit);
|
||||
}
|
||||
|
||||
mDeviceId = findPreference("device_id");
|
||||
mDeviceId.setOnPreferenceChangeListener(this);
|
||||
mName = (EditTextPreference) findPreference("name");
|
||||
mName.setOnPreferenceChangeListener(this);
|
||||
mAddresses = (EditTextPreference) findPreference("addresses");
|
||||
mAddresses.setOnPreferenceChangeListener(this);
|
||||
mCompression = (ListPreference) findPreference("compression");
|
||||
mCompression.setOnPreferenceChangeListener(this);
|
||||
mIntroducer = (CheckBoxPreference) findPreference("introducer");
|
||||
mIntroducer.setOnPreferenceChangeListener(this);
|
||||
if (!mIsCreate) {
|
||||
mVersion = findPreference("version");
|
||||
mVersion.setSummary("?");
|
||||
mCurrentAddress = findPreference("current_address");
|
||||
mCurrentAddress.setSummary("?");
|
||||
}
|
||||
|
||||
if (mIsCreate) {
|
||||
if (savedInstanceState != null) {
|
||||
mDevice = (RestApi.Device) savedInstanceState.getSerializable("device");
|
||||
}
|
||||
if (mDevice == null) {
|
||||
mDevice = new RestApi.Device();
|
||||
mDevice.name = "";
|
||||
mDevice.deviceID = "";
|
||||
mDevice.addresses = "dynamic";
|
||||
mDevice.compression = "metadata";
|
||||
mDevice.introducer = false;
|
||||
((EditTextPreference) mDeviceId).setText(mDevice.deviceID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current settings in case we are in create mode and they aren't yet stored in the config.
|
||||
*/
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable("device", mDevice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (currentState != SyncthingService.State.ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsCreate)
|
||||
getActivity().setTitle(R.string.add_device);
|
||||
else {
|
||||
RestApi.Device device = null;
|
||||
getActivity().setTitle(R.string.edit_device);
|
||||
List<RestApi.Device> devices = mSyncthingService.getApi().getDevices(false);
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
if (devices.get(i).deviceID.equals(
|
||||
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {
|
||||
device = devices.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (device == null) {
|
||||
Log.w(TAG, "Device not found in API update");
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
mDevice = device;
|
||||
mDeviceId.setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
mSyncthingService.getApi().getConnections(DeviceSettingsFragment.this);
|
||||
|
||||
mDeviceId.setSummary(mDevice.deviceID);
|
||||
mName.setText((mDevice.name));
|
||||
mName.setSummary(mDevice.name);
|
||||
mAddresses.setText(mDevice.addresses);
|
||||
mAddresses.setSummary(mDevice.addresses);
|
||||
mCompression.setValue(mDevice.compression);
|
||||
mCompression.setSummary(mDevice.compression);
|
||||
mIntroducer.setChecked(mDevice.introducer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.device_settings, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(R.id.create).setVisible(mIsCreate);
|
||||
menu.findItem(R.id.share_device_id).setVisible(!mIsCreate);
|
||||
menu.findItem(R.id.delete).setVisible(!mIsCreate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.create:
|
||||
if (mDevice.deviceID.equals("")) {
|
||||
Toast.makeText(getActivity(), R.string.device_id_required, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
if (mDevice.name.equals("")) {
|
||||
Toast.makeText(getActivity(), R.string.device_name_required, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
mSyncthingService.getApi().editDevice(mDevice, getActivity(), this);
|
||||
getActivity().finish();
|
||||
return true;
|
||||
case R.id.share_device_id:
|
||||
RestApi.shareDeviceId(getActivity(), mDevice.deviceID);
|
||||
return true;
|
||||
case R.id.delete:
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.delete_device_confirm)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
mSyncthingService.getApi().deleteDevice(mDevice, getActivity());
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
return true;
|
||||
case android.R.id.home:
|
||||
getActivity().finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||
if (preference instanceof EditTextPreference) {
|
||||
EditTextPreference pref = (EditTextPreference) preference;
|
||||
pref.setSummary((String) o);
|
||||
}
|
||||
if (preference instanceof ListPreference) {
|
||||
ListPreference pref = (ListPreference) preference;
|
||||
pref.setSummary((String) o);
|
||||
}
|
||||
if (preference.equals(mDeviceId)) {
|
||||
mDevice.deviceID = (String) o;
|
||||
deviceUpdated();
|
||||
return true;
|
||||
} else if (preference.equals(mName)) {
|
||||
mDevice.name = (String) o;
|
||||
deviceUpdated();
|
||||
return true;
|
||||
} else if (preference.equals(mAddresses)) {
|
||||
mDevice.addresses = (String) o;
|
||||
deviceUpdated();
|
||||
return true;
|
||||
} else if (preference.equals(mCompression)) {
|
||||
mDevice.compression = (String) o;
|
||||
deviceUpdated();
|
||||
return true;
|
||||
} else if (preference.equals(mIntroducer)) {
|
||||
mDevice.introducer = (Boolean) o;
|
||||
deviceUpdated();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (preference.equals(mDeviceId)) {
|
||||
mSyncthingService.getApi().copyDeviceId(mDevice.deviceID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets version and current address of the device.
|
||||
*
|
||||
* 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, RestApi.Connection> connections) {
|
||||
if (mVersion == null || mCurrentAddress == null)
|
||||
return;
|
||||
if (connections.containsKey(mDevice.deviceID)) {
|
||||
mVersion.setSummary(connections.get(mDevice.deviceID).clientVersion);
|
||||
mCurrentAddress.setSummary(connections.get(mDevice.deviceID).address);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the updated device info if in edit mode.
|
||||
*/
|
||||
private void deviceUpdated() {
|
||||
if (!mIsCreate) {
|
||||
mSyncthingService.getApi().editDevice(mDevice, getActivity(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends QR code scanning intent when clicking the QR code icon.
|
||||
*/
|
||||
public void onClick(View view) {
|
||||
BarcodeIntentIntegrator integrator = new BarcodeIntentIntegrator(this);
|
||||
integrator.initiateScan();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives value of scanned QR code and sets it as device ID.
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
BarcodeIntentResult scanResult = BarcodeIntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
|
||||
if (scanResult != null) {
|
||||
mDevice.deviceID = scanResult.getContents();
|
||||
((EditTextPreference) mDeviceId).setText(mDevice.deviceID);
|
||||
mDeviceId.setSummary(mDevice.deviceID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ import com.nutomic.syncthingandroid.syncthing.RestApi;
|
|||
import com.nutomic.syncthingandroid.syncthing.RestApi.SimpleVersioning;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi.Versioning;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -76,7 +77,7 @@ public class FolderFragment extends Fragment
|
|||
|
||||
private TextView mVersioningKeepView;
|
||||
|
||||
private boolean mIsCreate;
|
||||
private boolean mIsCreateMode;
|
||||
|
||||
private KeepVersionsDialogFragment mKeepVersionsDialogFragment = new KeepVersionsDialogFragment();
|
||||
|
||||
|
@ -154,12 +155,12 @@ public class FolderFragment extends Fragment
|
|||
super.onCreate(savedInstanceState);
|
||||
|
||||
SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
mIsCreate = activity.getIsCreate();
|
||||
activity.setTitle(isCreatingFolder() ? R.string.create_folder : R.string.edit_folder);
|
||||
mIsCreateMode = activity.getIsCreate();
|
||||
activity.setTitle(mIsCreateMode ? R.string.create_folder : R.string.edit_folder);
|
||||
activity.registerOnServiceConnectedListener(this);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (isCreatingFolder()) {
|
||||
if (mIsCreateMode) {
|
||||
if (savedInstanceState != null) {
|
||||
mFolder = (RestApi.Folder) savedInstanceState.getSerializable("folder");
|
||||
}
|
||||
|
@ -169,6 +170,14 @@ public class FolderFragment extends Fragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mSyncthingService != null) {
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current settings in case we are in create mode and they aren't yet stored in the config.
|
||||
*/
|
||||
|
@ -196,11 +205,50 @@ public class FolderFragment extends Fragment
|
|||
mPathView.setOnClickListener(mPathViewClickListener);
|
||||
view.findViewById(R.id.versioningContainer).setOnClickListener(mVersioningContainerClickListener);
|
||||
|
||||
if (isEditingFolder()) {
|
||||
if (!mIsCreateMode) {
|
||||
prepareEditMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mIdView.removeTextChangedListener(mIdTextWatcher);
|
||||
mPathView.removeTextChangedListener(mPathTextWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (currentState != ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIsCreateMode) {
|
||||
List<RestApi.Folder> folders = mSyncthingService.getApi().getFolders();
|
||||
String passedId = getActivity().getIntent().getStringExtra(EXTRA_REPO_ID);
|
||||
for (RestApi.Folder currentFolder : folders) {
|
||||
if (currentFolder.id.equals(passedId)) {
|
||||
mFolder = currentFolder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mFolder == null) {
|
||||
Log.w(TAG, "Folder not found in API update");
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateViewsAndSetListeners();
|
||||
}
|
||||
|
||||
private void updateViewsAndSetListeners() {
|
||||
// Update views
|
||||
mIdView.setText(mFolder.id);
|
||||
|
@ -233,53 +281,6 @@ public class FolderFragment extends Fragment
|
|||
mKeepVersionsDialogFragment.setOnValueChangeListener(mOnValueChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mIdView.removeTextChangedListener(mIdTextWatcher);
|
||||
mPathView.removeTextChangedListener(mPathTextWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (currentState != ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEditingFolder()) {
|
||||
List<RestApi.Folder> folders = mSyncthingService.getApi().getFolders();
|
||||
String passedId = getActivity().getIntent().getStringExtra(EXTRA_REPO_ID);
|
||||
for (RestApi.Folder currentFolder : folders) {
|
||||
if (currentFolder.id.equals(passedId)) {
|
||||
mFolder = currentFolder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mFolder == null) {
|
||||
Log.w(TAG, "Folder not found in API update");
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateViewsAndSetListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mSyncthingService != null) {
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
@ -288,8 +289,8 @@ public class FolderFragment extends Fragment
|
|||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(R.id.create).setVisible(isCreatingFolder());
|
||||
menu.findItem(R.id.delete).setVisible(isEditingFolder());
|
||||
menu.findItem(R.id.create).setVisible(mIsCreateMode);
|
||||
menu.findItem(R.id.delete).setVisible(!mIsCreateMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -324,8 +325,9 @@ public class FolderFragment extends Fragment
|
|||
case android.R.id.home:
|
||||
getActivity().finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -355,7 +357,6 @@ public class FolderFragment extends Fragment
|
|||
|
||||
private void addEmptyDeviceListView() {
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WRAP_CONTENT, dp(48, getActivity()));
|
||||
// 72dp margin to align with dividers
|
||||
int dividerInset = getResources().getDimensionPixelOffset(R.dimen.material_divider_inset);
|
||||
int contentInset = getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_content_inset_material);
|
||||
setMarginStart(params, dividerInset);
|
||||
|
@ -376,28 +377,8 @@ public class FolderFragment extends Fragment
|
|||
}
|
||||
|
||||
private void updateRepo() {
|
||||
if (isEditingFolder()) {
|
||||
if (!mIsCreateMode) {
|
||||
mSyncthingService.getApi().editFolder(mFolder, false, getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEditingFolder() {
|
||||
return !mIsCreate;
|
||||
}
|
||||
|
||||
private boolean isCreatingFolder() {
|
||||
return mIsCreate;
|
||||
}
|
||||
|
||||
private class TextWatcherAdapter implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package com.nutomic.syncthingandroid.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
|
||||
/**
|
||||
* Device compression attribute helper. This unifies operations between string values as expected by
|
||||
* Syncthing with string values as displayed to the user and int ordinals as expected by the dialog
|
||||
* click interface.
|
||||
*/
|
||||
public enum Compression {
|
||||
NONE(0),
|
||||
METADATA(1),
|
||||
ALWAYS(2);
|
||||
|
||||
private final int index;
|
||||
|
||||
Compression(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String getValue(Context context) {
|
||||
return context.getResources().getStringArray(R.array.compress_values)[index];
|
||||
}
|
||||
|
||||
public String getTitle(Context context) {
|
||||
return context.getResources().getStringArray(R.array.compress_entries)[index];
|
||||
}
|
||||
|
||||
public static Compression fromIndex(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return NONE;
|
||||
case 2:
|
||||
return ALWAYS;
|
||||
default:
|
||||
return METADATA;
|
||||
}
|
||||
}
|
||||
|
||||
public static Compression fromValue(Context context, String value) {
|
||||
int index = 0;
|
||||
String[] values = context.getResources().getStringArray(R.array.compress_values);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i].equals(value)) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return fromIndex(index);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.nutomic.syncthingandroid.util;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
public class TextWatcherAdapter implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.nutomic.syncthingandroid.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.widget.EditText;
|
||||
|
||||
import static android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
|
||||
|
||||
/**
|
||||
* Apparently EditText blocks touch event propagation to the parent even
|
||||
* when disabled/not clickable/not focusable. Therefore we have to manually
|
||||
* check whether we are enabled and either ignore the event or process it normally. <br/>
|
||||
* <br/>
|
||||
* This class also blocks the default EditText behaviour of textMultiLine flag enforcing replacement
|
||||
* of the IME action button with the new line character. This allows rendering soft wraps on single
|
||||
* line input.
|
||||
*/
|
||||
public class EnhancedEditText extends EditText {
|
||||
|
||||
public EnhancedEditText(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public EnhancedEditText(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public EnhancedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (isEnabled()) {
|
||||
return super.onTouchEvent(event);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||
InputConnection conn = super.onCreateInputConnection(outAttrs);
|
||||
outAttrs.imeOptions &= ~IME_FLAG_NO_ENTER_ACTION;
|
||||
return conn;
|
||||
}
|
||||
}
|
BIN
src/main/res/drawable-hdpi/ic_cellphone_black_24dp_active.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
src/main/res/drawable-hdpi/ic_cellphone_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
src/main/res/drawable-hdpi/ic_info_black_24dp_active.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
src/main/res/drawable-hdpi/ic_info_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 286 B |
BIN
src/main/res/drawable-hdpi/ic_link_black_24dp_active.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
src/main/res/drawable-hdpi/ic_link_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
src/main/res/drawable-hdpi/ic_phonelink_black_24dp_active.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
src/main/res/drawable-hdpi/ic_phonelink_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 148 B |
Before Width: | Height: | Size: 942 B |
BIN
src/main/res/drawable-hdpi/ic_qrcode_black_24dp_active.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
src/main/res/drawable-hdpi/ic_qrcode_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 308 B |
After Width: | Height: | Size: 295 B |
BIN
src/main/res/drawable-hdpi/ic_zip_box_black_24dp_active.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
src/main/res/drawable-hdpi/ic_zip_box_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 178 B |
Before Width: | Height: | Size: 857 B |
BIN
src/main/res/drawable-xhdpi/ic_cellphone_black_24dp_active.png
Normal file
After Width: | Height: | Size: 161 B |
BIN
src/main/res/drawable-xhdpi/ic_cellphone_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 161 B |
BIN
src/main/res/drawable-xhdpi/ic_info_black_24dp_active.png
Normal file
After Width: | Height: | Size: 383 B |
BIN
src/main/res/drawable-xhdpi/ic_info_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 358 B |
BIN
src/main/res/drawable-xhdpi/ic_link_black_24dp_active.png
Normal file
After Width: | Height: | Size: 333 B |
BIN
src/main/res/drawable-xhdpi/ic_link_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 274 B |
BIN
src/main/res/drawable-xhdpi/ic_phonelink_black_24dp_active.png
Normal file
After Width: | Height: | Size: 164 B |
BIN
src/main/res/drawable-xhdpi/ic_phonelink_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 163 B |
Before Width: | Height: | Size: 1.2 KiB |
BIN
src/main/res/drawable-xhdpi/ic_qrcode_black_24dp_active.png
Normal file
After Width: | Height: | Size: 137 B |
BIN
src/main/res/drawable-xhdpi/ic_qrcode_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 139 B |
After Width: | Height: | Size: 320 B |
After Width: | Height: | Size: 306 B |
BIN
src/main/res/drawable-xhdpi/ic_zip_box_black_24dp_active.png
Normal file
After Width: | Height: | Size: 169 B |
BIN
src/main/res/drawable-xhdpi/ic_zip_box_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
src/main/res/drawable-xxhdpi/ic_cellphone_black_24dp_active.png
Normal file
After Width: | Height: | Size: 204 B |
After Width: | Height: | Size: 195 B |
BIN
src/main/res/drawable-xxhdpi/ic_info_black_24dp_active.png
Normal file
After Width: | Height: | Size: 547 B |
BIN
src/main/res/drawable-xxhdpi/ic_info_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
src/main/res/drawable-xxhdpi/ic_link_black_24dp_active.png
Normal file
After Width: | Height: | Size: 519 B |
BIN
src/main/res/drawable-xxhdpi/ic_link_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 445 B |
BIN
src/main/res/drawable-xxhdpi/ic_phonelink_black_24dp_active.png
Normal file
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 205 B |
Before Width: | Height: | Size: 2.5 KiB |
BIN
src/main/res/drawable-xxhdpi/ic_qrcode_black_24dp_active.png
Normal file
After Width: | Height: | Size: 156 B |
BIN
src/main/res/drawable-xxhdpi/ic_qrcode_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 156 B |
After Width: | Height: | Size: 459 B |
After Width: | Height: | Size: 443 B |
BIN
src/main/res/drawable-xxhdpi/ic_zip_box_black_24dp_active.png
Normal file
After Width: | Height: | Size: 206 B |
BIN
src/main/res/drawable-xxhdpi/ic_zip_box_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
src/main/res/drawable-xxxhdpi/ic_cellphone_black_24dp_active.png
Normal file
After Width: | Height: | Size: 277 B |
After Width: | Height: | Size: 255 B |
BIN
src/main/res/drawable-xxxhdpi/ic_info_black_24dp_active.png
Normal file
After Width: | Height: | Size: 721 B |
BIN
src/main/res/drawable-xxxhdpi/ic_info_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 670 B |
BIN
src/main/res/drawable-xxxhdpi/ic_link_black_24dp_active.png
Normal file
After Width: | Height: | Size: 674 B |
BIN
src/main/res/drawable-xxxhdpi/ic_link_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 561 B |
BIN
src/main/res/drawable-xxxhdpi/ic_phonelink_black_24dp_active.png
Normal file
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 254 B |
BIN
src/main/res/drawable-xxxhdpi/ic_qrcode_black_24dp_active.png
Normal file
After Width: | Height: | Size: 155 B |
BIN
src/main/res/drawable-xxxhdpi/ic_qrcode_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 155 B |
After Width: | Height: | Size: 685 B |
After Width: | Height: | Size: 570 B |
BIN
src/main/res/drawable-xxxhdpi/ic_zip_box_black_24dp_active.png
Normal file
After Width: | Height: | Size: 270 B |
BIN
src/main/res/drawable-xxxhdpi/ic_zip_box_black_24dp_inactive.png
Normal file
After Width: | Height: | Size: 259 B |
5
src/main/res/drawable/ic_cellphone_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_cellphone_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_cellphone_black_24dp_active" />
|
||||
</selector>
|
5
src/main/res/drawable/ic_info_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_info_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_info_black_24dp_active" />
|
||||
</selector>
|
5
src/main/res/drawable/ic_link_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_link_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_link_black_24dp_active" />
|
||||
</selector>
|
5
src/main/res/drawable/ic_phonelink_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_phonelink_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_phonelink_black_24dp_active" />
|
||||
</selector>
|
5
src/main/res/drawable/ic_qrcode_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_qrcode_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_qrcode_black_24dp_active" />
|
||||
</selector>
|
5
src/main/res/drawable/ic_tag_text_outline_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_tag_text_outline_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_tag_text_outline_black_24dp_active" />
|
||||
</selector>
|
8
src/main/res/drawable/ic_transparent_24dp.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size
|
||||
android:width="24dp"
|
||||
android:height="24dp" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
5
src/main/res/drawable/ic_zip_box_black_24dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_zip_box_black_24dp_inactive" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/ic_zip_box_black_24dp_active" />
|
||||
</selector>
|
133
src/main/res/layout/fragment_device.xml
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.DeviceFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="?android:listDivider"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:showDividers="middle">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/idContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.nutomic.syncthingandroid.widget.EnhancedEditText
|
||||
android:id="@+id/id"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details.Field"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawableLeft="@drawable/ic_cellphone_black_24dp"
|
||||
android:drawableStart="@drawable/ic_cellphone_black_24dp"
|
||||
android:hint="@string/device_id"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textNoSuggestions|textMultiLine"
|
||||
android:nextFocusForward="@+id/name"
|
||||
tools:text="@string/device_id_placeholder" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrButton"
|
||||
style="?actionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/abc_action_bar_content_inset_material"
|
||||
android:layout_marginRight="@dimen/abc_action_bar_content_inset_material"
|
||||
android:contentDescription="@string/scan_qr_code_description"
|
||||
android:src="@drawable/ic_qrcode_black_24dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details.Field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_tag_text_outline_black_24dp"
|
||||
android:drawableStart="@drawable/ic_tag_text_outline_black_24dp"
|
||||
android:hint="@string/name"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textCapWords" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/addresses"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details.Field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_link_black_24dp"
|
||||
android:drawableStart="@drawable/ic_link_black_24dp"
|
||||
android:hint="@string/addresses"
|
||||
android:imeOptions="actionDone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/compressionContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:checked="false"
|
||||
android:drawableLeft="@drawable/ic_zip_box_black_24dp"
|
||||
android:drawableStart="@drawable/ic_zip_box_black_24dp"
|
||||
android:text="@string/compression" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/compressionValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/abc_action_bar_content_inset_material"
|
||||
android:layout_marginRight="@dimen/abc_action_bar_content_inset_material"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/introducer"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableLeft="@drawable/ic_phonelink_black_24dp"
|
||||
android:drawableStart="@drawable/ic_phonelink_black_24dp"
|
||||
android:text="@string/introducer" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentAddress"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_info_black_24dp"
|
||||
android:drawableStart="@drawable/ic_info_black_24dp"
|
||||
android:enabled="false"
|
||||
android:hint="@string/current_address"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/syncthingVersion"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_transparent_24dp"
|
||||
android:drawableStart="@drawable/ic_transparent_24dp"
|
||||
android:enabled="false"
|
||||
android:hint="@string/syncthing_version_title"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.FoldersFragment">
|
||||
tools:context=".fragments.FolderFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -12,23 +12,24 @@
|
|||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:showDividers="middle"
|
||||
tools:ignore="RtlSymmetry">
|
||||
android:showDividers="middle">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/id"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder.Field"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details.Field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_vpn_key_black_24dp"
|
||||
android:drawableStart="@drawable/ic_vpn_key_black_24dp"
|
||||
android:hint="@string/folder_id" />
|
||||
android:hint="@string/folder_id"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textCapWords" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/directory"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_folder_black_24dp"
|
||||
android:drawableStart="@drawable/ic_folder_black_24dp"
|
||||
android:hint="@string/directory" />
|
||||
|
@ -40,9 +41,9 @@
|
|||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_device_hub_black_24dp"
|
||||
android:drawableStart="@drawable/ic_device_hub_black_24dp"
|
||||
android:text="@string/devices" />
|
||||
|
@ -50,9 +51,9 @@
|
|||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/master"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableLeft="@drawable/ic_lock_black_24dp"
|
||||
android:drawableStart="@drawable/ic_lock_black_24dp"
|
||||
|
@ -66,14 +67,14 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:checked="false"
|
||||
android:drawableLeft="@drawable/ic_history_black_24dp"
|
||||
android:drawableStart="@drawable/ic_history_black_24dp"
|
||||
android:background="@null"
|
||||
android:text="@string/keep_versions" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.SwitchCompat xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Folder.DeviceList"
|
||||
style="@style/Widget.Syncthing.TextView.Label.Details.DeviceList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/material_divider_inset"
|
||||
android:layout_marginStart="@dimen/material_divider_inset"
|
||||
android:layout_marginRight="@dimen/abc_action_bar_content_inset_material"
|
||||
android:layout_marginEnd="@dimen/abc_action_bar_content_inset_material"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
tools:ignore="RtlHardcoded,RtlSymmetry" />
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip"
|
||||
android:src="@drawable/ic_qrcode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_qrcode_black_24dp"
|
||||
android:onClick="onClick"
|
||||
android:contentDescription="@string/scan_qr_code_description" />
|
||||
|
|
|
@ -25,18 +25,20 @@
|
|||
<item name="android:paddingRight">@dimen/abc_action_bar_content_inset_material</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Syncthing.TextView.Label.Folder">
|
||||
<style name="Widget.Syncthing.TextView.Label.Details">
|
||||
<item name="android:textColor">?attr/editTextColor</item>
|
||||
<item name="android:minHeight">56dp</item>
|
||||
<item name="android:paddingTop">8dp</item>
|
||||
<item name="android:paddingBottom">8dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Syncthing.TextView.Label.Folder.DeviceList">
|
||||
<style name="Widget.Syncthing.TextView.Label.Details.DeviceList">
|
||||
<item name="android:paddingLeft">4dp</item>
|
||||
<item name="android:minHeight">48dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Syncthing.TextView.Label.Folder.Field">
|
||||
<style name="Widget.Syncthing.TextView.Label.Details.Field">
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:imeOptions">actionDone</item>
|
||||
<item name="android:inputType">textVisiblePassword</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Syncthing.Switch" parent="@style/Widget.AppCompat.CompoundButton.Switch" >
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<item name="textAppearanceListItemSecondary">@style/TextAppearance.Syncthing.ListItemSecondary</item>
|
||||
<item name="textAppearanceListItemSmall">@style/TextAppearance.Syncthing.ListItemSmall</item>
|
||||
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="android:listViewStyle">@style/Widget.Syncthing.ListView</item>
|
||||
<item name="android:listDivider">@drawable/list_divider_inset</item>
|
||||
<item name="drawerArrowStyle">@style/Widget.Syncthing.DrawerArrowToggle</item>
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<EditTextPreference
|
||||
android:persistent="false"
|
||||
android:key="device_id"
|
||||
android:title="@string/device_id"
|
||||
android:widgetLayout="@layout/pref_widget_scan_qr_code" />
|
||||
|
||||
<EditTextPreference
|
||||
android:persistent="false"
|
||||
android:key="name"
|
||||
android:title="@string/name" />
|
||||
|
||||
<EditTextPreference
|
||||
android:persistent="false"
|
||||
android:key="addresses"
|
||||
android:title="@string/addresses" />
|
||||
|
||||
<ListPreference
|
||||
android:persistent="false"
|
||||
android:key="compression"
|
||||
android:entries="@array/compress_entries"
|
||||
android:entryValues="@array/compress_values"
|
||||
android:title="@string/compression" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:persistent="false"
|
||||
android:key="introducer"
|
||||
android:title="@string/introducer" />
|
||||
|
||||
</PreferenceScreen>
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<Preference
|
||||
android:persistent="false"
|
||||
android:key="device_id"
|
||||
android:title="@string/device_id" />
|
||||
|
||||
<EditTextPreference
|
||||
android:persistent="false"
|
||||
android:key="name"
|
||||
android:title="@string/name" />
|
||||
|
||||
<EditTextPreference
|
||||
android:persistent="false"
|
||||
android:key="addresses"
|
||||
android:title="@string/addresses" />
|
||||
|
||||
<ListPreference
|
||||
android:persistent="false"
|
||||
android:key="compression"
|
||||
android:entries="@array/compress_entries"
|
||||
android:entryValues="@array/compress_values"
|
||||
android:title="@string/compression" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:persistent="false"
|
||||
android:key="introducer"
|
||||
android:title="@string/introducer" />
|
||||
|
||||
<Preference
|
||||
android:persistent="false"
|
||||
android:key="version"
|
||||
android:title="@string/syncthing_version_title"
|
||||
style="?android:preferenceInformationStyle" />
|
||||
|
||||
<Preference
|
||||
android:persistent="false"
|
||||
android:key="current_address"
|
||||
android:title="@string/current_address"
|
||||
style="?android:preferenceInformationStyle" />
|
||||
|
||||
</PreferenceScreen>
|