1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-23 03:11:30 +00:00

Use PreferenceFragments with a wrapper instead of SettingsFragments (fixes #64).

This commit is contained in:
Felix Ableitner 2014-08-03 21:54:30 +02:00
parent 299c901086
commit d2e0c291b6
16 changed files with 377 additions and 289 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "ext/syncthing/src/github.com/syncthing/syncthing"]
path = ext/syncthing/src/github.com/syncthing/syncthing
url = https://github.com/syncthing/syncthing.git
[submodule "libraries/android-support-v4-preferencefragment"]
path = libraries/android-support-v4-preferencefragment
url = https://github.com/kolavar/android-support-v4-preferencefragment.git

View file

@ -20,6 +20,7 @@ repositories {
dependencies {
compile 'com.android.support:appcompat-v7:19.1.+'
compile project(':android-support-v4-preferencefragment')
}
preBuild {

@ -0,0 +1 @@
Subproject commit 269e53b7b94b8001d2192b0ff2effb12eadaab07

2
settings.gradle Normal file
View file

@ -0,0 +1,2 @@
include ':android-support-v4-preferencefragment'
project(':android-support-v4-preferencefragment').projectDir = new File('libraries/android-support-v4-preferencefragment')

View file

@ -39,8 +39,7 @@
android:value=".gui.MainActivity" />
</activity>
<activity
android:name=".gui.SettingsActivity"
android:label="@string/settings_title" >
android:name=".gui.SettingsActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".gui.MainActivity" />
@ -48,10 +47,6 @@
<service android:name=".syncthing.SyncthingService" />
<activity
android:name=".gui.RepoSettingsActivity" />
<activity
android:name=".gui.NodeSettingsActivity" />
<activity
android:name=".gui.FolderPickerActivity"
android:label="@string/folder_picker_title" >

View file

@ -23,7 +23,6 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBar.TabListener;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@ -270,20 +269,23 @@ public class MainActivity extends ActionBarActivity
switch (item.getItemId()) {
case R.id.add_repo:
Intent intent = new Intent(this, RepoSettingsActivity.class);
intent.setAction(RepoSettingsActivity.ACTION_CREATE);
Intent intent = new Intent(this, SettingsActivity.class)
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
startActivity(intent);
return true;
case R.id.add_node:
intent = new Intent(this, NodeSettingsActivity.class);
intent.setAction(NodeSettingsActivity.ACTION_CREATE);
intent = new Intent(this, SettingsActivity.class)
.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT)
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
startActivity(intent);
return true;
case R.id.web_gui:
startActivity(new Intent(this, WebGuiActivity.class));
return true;
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
startActivity(new Intent(this, SettingsActivity.class)
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT));
return true;
default:
return super.onOptionsItemSelected(item);

View file

@ -9,13 +9,13 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.support.v4.preference.PreferenceFragment;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
@ -31,16 +31,12 @@ import java.util.Map;
/**
* Shows node details and allows changing them.
*/
public class NodeSettingsActivity extends PreferenceActivity implements
public class NodeSettingsFragment extends PreferenceFragment implements
Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
RestApi.OnReceiveConnectionsListener, SyncthingService.OnApiChangeListener,
RestApi.OnNodeIdNormalizedListener {
public static final String ACTION_CREATE = "create";
public static final String ACTION_EDIT = "edit";
public static final String KEY_NODE_ID = "node_id";
public static final String EXTRA_NODE_ID = "node_id";
private static final int SCAN_QR_REQUEST_CODE = 235;
@ -51,7 +47,7 @@ public class NodeSettingsActivity extends PreferenceActivity implements
public void onServiceConnected(ComponentName className, IBinder service) {
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
mSyncthingService = binder.getService();
mSyncthingService.registerOnApiChangeListener(NodeSettingsActivity.this);
mSyncthingService.registerOnApiChangeListener(NodeSettingsFragment.this);
}
public void onServiceDisconnected(ComponentName className) {
@ -73,20 +69,19 @@ public class NodeSettingsActivity extends PreferenceActivity implements
private Preference mDelete;
private boolean mIsCreate;
@Override
@SuppressLint("AppCompatMethod")
@TargetApi(11)
protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
mIsCreate = ((SettingsActivity) getActivity()).getIsCreate();
setHasOptionsMenu(true);
if (getIntent().getAction().equals(ACTION_CREATE)) {
if (mIsCreate) {
addPreferencesFromResource(R.xml.node_settings_create);
}
else if (getIntent().getAction().equals(ACTION_EDIT)) {
else {
addPreferencesFromResource(R.xml.node_settings_edit);
}
@ -96,7 +91,7 @@ public class NodeSettingsActivity extends PreferenceActivity implements
mName.setOnPreferenceChangeListener(this);
mAddresses = (EditTextPreference) findPreference("addresses");
mAddresses.setOnPreferenceChangeListener(this);
if (getIntent().getAction().equals(ACTION_EDIT)) {
if (!mIsCreate) {
mVersion = findPreference("version");
mVersion.setSummary("?");
mCurrentAddress = findPreference("current_address");
@ -105,38 +100,39 @@ public class NodeSettingsActivity extends PreferenceActivity implements
mDelete.setOnPreferenceClickListener(this);
}
bindService(new Intent(this, SyncthingService.class),
getActivity().bindService(new Intent(getActivity(), SyncthingService.class),
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void onApiChange(SyncthingService.State currentState) {
if (currentState != SyncthingService.State.ACTIVE) {
SyncthingService.showDisabledDialog(this);
finish();
SyncthingService.showDisabledDialog(getActivity());
getActivity().finish();
return;
}
if (getIntent().getAction().equals(ACTION_CREATE)) {
setTitle(R.string.add_node);
if (mIsCreate) {
getActivity().setTitle(R.string.add_node);
mNode = new RestApi.Node();
mNode.Name = "";
mNode.NodeID = "";
mNode.Addresses = "dynamic";
((EditTextPreference) mNodeId).setText(mNode.NodeID);
}
else if (getIntent().getAction().equals(ACTION_EDIT)) {
setTitle(R.string.edit_node);
else {
getActivity().setTitle(R.string.edit_node);
List<RestApi.Node> nodes = mSyncthingService.getApi().getNodes();
for (int i = 0; i < nodes.size(); i++) {
if (nodes.get(i).NodeID.equals(getIntent().getStringExtra(KEY_NODE_ID))) {
if (nodes.get(i).NodeID.equals(
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {
mNode = nodes.get(i);
break;
}
}
mNodeId.setOnPreferenceClickListener(this);
}
mSyncthingService.getApi().getConnections(NodeSettingsActivity.this);
mSyncthingService.getApi().getConnections(NodeSettingsFragment.this);
mNodeId.setSummary(mNode.NodeID);
mName.setText((mNode.Name));
@ -146,16 +142,15 @@ public class NodeSettingsActivity extends PreferenceActivity implements
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.node_settings, menu);
return true;
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.node_settings, menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.create).setVisible(getIntent().getAction().equals(ACTION_CREATE));
menu.findItem(R.id.share_node_id).setVisible(getIntent().getAction().equals(ACTION_EDIT));
return true;
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.create).setVisible(mIsCreate);
menu.findItem(R.id.share_node_id).setVisible(!mIsCreate);
}
@Override
@ -163,22 +158,22 @@ public class NodeSettingsActivity extends PreferenceActivity implements
switch (item.getItemId()) {
case R.id.create:
if (mNode.NodeID.equals("")) {
Toast.makeText(this, R.string.node_id_required, Toast.LENGTH_LONG)
Toast.makeText(getActivity(), R.string.node_id_required, Toast.LENGTH_LONG)
.show();
return true;
}
if (mNode.Name.equals("")) {
Toast.makeText(this, R.string.node_name_required, Toast.LENGTH_LONG)
Toast.makeText(getActivity(), R.string.node_name_required, Toast.LENGTH_LONG)
.show();
return true;
}
mSyncthingService.getApi().editNode(mNode, this);
return true;
case R.id.share_node_id:
RestApi.shareNodeId(this, mNode.NodeID);
RestApi.shareNodeId(getActivity(), mNode.NodeID);
return true;
case android.R.id.home:
finish();
getActivity().finish();
return true;
default:
return super.onOptionsItemSelected(item);
@ -188,7 +183,7 @@ public class NodeSettingsActivity extends PreferenceActivity implements
@Override
public void onDestroy() {
super.onDestroy();
unbindService(mSyncthingServiceConnection);
getActivity().unbindService(mSyncthingServiceConnection);
}
@Override
@ -219,13 +214,13 @@ public class NodeSettingsActivity extends PreferenceActivity implements
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference.equals(mDelete)) {
new AlertDialog.Builder(this)
new AlertDialog.Builder(getActivity())
.setMessage(R.string.delete_node_confirm)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mSyncthingService.getApi().deleteNode(mNode, NodeSettingsActivity.this);
finish();
mSyncthingService.getApi().deleteNode(mNode, getActivity());
getActivity().finish();
}
})
.setNegativeButton(android.R.string.no, null)
@ -257,7 +252,7 @@ public class NodeSettingsActivity extends PreferenceActivity implements
* Sends the updated node info if in edit mode.
*/
private void nodeUpdated() {
if (getIntent().getAction().equals(ACTION_EDIT)) {
if (!mIsCreate) {
mSyncthingService.getApi().editNode(mNode, this);
}
}
@ -274,7 +269,8 @@ public class NodeSettingsActivity extends PreferenceActivity implements
startActivityForResult(intentScan, SCAN_QR_REQUEST_CODE);
}
catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.no_qr_scanner_installed, Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), R.string.no_qr_scanner_installed,
Toast.LENGTH_LONG).show();
}
}
@ -282,7 +278,7 @@ public class NodeSettingsActivity extends PreferenceActivity implements
* Receives value of scanned QR code and sets it as node ID.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SCAN_QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
mNode.NodeID = data.getStringExtra("SCAN_RESULT");
((EditTextPreference) mNodeId).setText(mNode.NodeID);
@ -300,11 +296,10 @@ public class NodeSettingsActivity extends PreferenceActivity implements
@Override
public void onNodeIdNormalized(String normalizedId, String error) {
if (error != null) {
Toast.makeText(NodeSettingsActivity.this, error,
Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show();
}
else if (getIntent().getAction().equals(ACTION_CREATE)) {
finish();
else if (mIsCreate) {
getActivity().finish();
}
}

View file

@ -87,9 +87,10 @@ public class NodesFragment extends ListFragment implements SyncthingService.OnAp
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity(), NodeSettingsActivity.class);
intent.setAction(NodeSettingsActivity.ACTION_EDIT);
intent.putExtra(NodeSettingsActivity.KEY_NODE_ID, mAdapter.getItem(i).NodeID);
Intent intent = new Intent(getActivity(), SettingsActivity.class);
intent.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT);
intent.putExtra(SettingsActivity.EXTRA_IS_CREATE, false);
intent.putExtra(NodeSettingsFragment.EXTRA_NODE_ID, mAdapter.getItem(i).NodeID);
startActivity(intent);
}

View file

@ -16,9 +16,10 @@ import android.os.IBinder;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.support.v4.preference.PreferenceFragment;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
@ -34,17 +35,17 @@ import java.util.List;
/**
* Shows repo details and allows changing them.
*/
public class RepoSettingsActivity extends PreferenceActivity
public class RepoSettingsFragment extends PreferenceFragment
implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
SyncthingService.OnApiChangeListener {
private static final int DIRECTORY_REQUEST_CODE = 234;
public static final String ACTION_CREATE = "create";
public static final String ACTION_EDIT = "edit";
public static final String KEY_REPO_ID = "repo_id";
/**
* The ID of the repo to be edited. To be used with {@link SettingsActivity#EXTRA_IS_CREATE}
* set to false.
*/
public static final String EXTRA_REPO_ID = "repo_id";
private static final String KEY_NODE_SHARED = "node_shared";
@ -55,7 +56,7 @@ public class RepoSettingsActivity extends PreferenceActivity
public void onServiceConnected(ComponentName className, IBinder service) {
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
mSyncthingService = binder.getService();
mSyncthingService.registerOnApiChangeListener(RepoSettingsActivity.this);
mSyncthingService.registerOnApiChangeListener(RepoSettingsFragment.this);
}
public void onServiceDisconnected(ComponentName className) {
@ -79,20 +80,19 @@ public class RepoSettingsActivity extends PreferenceActivity
private Preference mDelete;
private boolean mIsCreate;
@Override
@SuppressLint("AppCompatMethod")
@TargetApi(11)
protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
mIsCreate = ((SettingsActivity) getActivity()).getIsCreate();
setHasOptionsMenu(true);
if (getIntent().getAction().equals(ACTION_CREATE)) {
if (mIsCreate) {
addPreferencesFromResource(R.xml.repo_settings_create);
}
else if (getIntent().getAction().equals(ACTION_EDIT)) {
else {
addPreferencesFromResource(R.xml.repo_settings_edit);
}
@ -108,36 +108,37 @@ public class RepoSettingsActivity extends PreferenceActivity
mVersioning.setOnPreferenceChangeListener(this);
mVersioningKeep = (EditTextPreference) findPreference("versioning_keep");
mVersioningKeep.setOnPreferenceChangeListener(this);
if (getIntent().getAction().equals(ACTION_EDIT)) {
if (!mIsCreate) {
mDelete = findPreference("delete");
mDelete.setOnPreferenceClickListener(this);
}
bindService(new Intent(this, SyncthingService.class),
getActivity().bindService(new Intent(getActivity(), SyncthingService.class),
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void onApiChange(SyncthingService.State currentState) {
if (currentState != SyncthingService.State.ACTIVE) {
SyncthingService.showDisabledDialog(this);
finish();
SyncthingService.showDisabledDialog(getActivity());
getActivity().finish();
return;
}
if (getIntent().getAction().equals(ACTION_CREATE)) {
setTitle(R.string.create_repo);
if (mIsCreate) {
getActivity().setTitle(R.string.create_repo);
mRepo = new RestApi.Repo();
mRepo.ID = "";
mRepo.Directory = "";
mRepo.Nodes = new ArrayList<RestApi.Node>();
mRepo.Versioning = new RestApi.Versioning();
}
else if (getIntent().getAction().equals(ACTION_EDIT)) {
setTitle(R.string.edit_repo);
else {
getActivity().setTitle(R.string.edit_repo);
List<RestApi.Repo> repos = mSyncthingService.getApi().getRepos();
for (int i = 0; i < repos.size(); i++) {
if (repos.get(i).ID.equals(getIntent().getStringExtra(KEY_REPO_ID))) {
if (repos.get(i).ID.equals(
getActivity().getIntent().getStringExtra(EXTRA_REPO_ID))) {
mRepo = repos.get(i);
break;
}
@ -150,11 +151,10 @@ public class RepoSettingsActivity extends PreferenceActivity
mRepoMaster.setChecked(mRepo.ReadOnly);
List<RestApi.Node> nodesList = mSyncthingService.getApi().getNodes();
for (RestApi.Node n : nodesList) {
ExtendedCheckBoxPreference cbp =
new ExtendedCheckBoxPreference(RepoSettingsActivity.this, n);
ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n);
cbp.setTitle(n.Name);
cbp.setKey(KEY_NODE_SHARED);
cbp.setOnPreferenceChangeListener(RepoSettingsActivity.this);
cbp.setOnPreferenceChangeListener(RepoSettingsFragment.this);
cbp.setChecked(false);
for (RestApi.Node n2 : mRepo.Nodes) {
if (n2.NodeID.equals(n.NodeID)) {
@ -175,15 +175,14 @@ public class RepoSettingsActivity extends PreferenceActivity
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.repo_settings, menu);
return true;
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.repo_settings, menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.create).setVisible(getIntent().getAction().equals(ACTION_CREATE));
return true;
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.create).setVisible(mIsCreate);
}
@Override
@ -191,18 +190,20 @@ public class RepoSettingsActivity extends PreferenceActivity
switch (item.getItemId()) {
case R.id.create:
if (mRepo.ID.equals("")) {
Toast.makeText(this, R.string.repo_id_required, Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), R.string.repo_id_required, Toast.LENGTH_LONG)
.show();
return true;
}
if (mRepo.Directory.equals("")) {
Toast.makeText(this, R.string.repo_path_required, Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), R.string.repo_path_required, Toast.LENGTH_LONG)
.show();
return true;
}
mSyncthingService.getApi().editRepo(mRepo, true, this);
finish();
mSyncthingService.getApi().editRepo(mRepo, true, getActivity());
getActivity().finish();
return true;
case android.R.id.home:
finish();
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
@ -211,7 +212,7 @@ public class RepoSettingsActivity extends PreferenceActivity
@Override
public void onDestroy() {
super.onDestroy();
unbindService(mSyncthingServiceConnection);
getActivity().unbindService(mSyncthingServiceConnection);
}
@Override
@ -280,7 +281,7 @@ public class RepoSettingsActivity extends PreferenceActivity
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference.equals(mDirectory)) {
Intent intent = new Intent(this, FolderPickerActivity.class)
Intent intent = new Intent(getActivity(), FolderPickerActivity.class)
.putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY,
(mRepo.Directory.length() != 0)
? mRepo.Directory
@ -288,16 +289,17 @@ public class RepoSettingsActivity extends PreferenceActivity
startActivityForResult(intent, DIRECTORY_REQUEST_CODE);
}
else if (preference.equals(mNodes) && mSyncthingService.getApi().getNodes().isEmpty()) {
Toast.makeText(this, R.string.no_nodes, Toast.LENGTH_SHORT).show();
Toast.makeText(getActivity(), R.string.no_nodes, Toast.LENGTH_SHORT)
.show();
}
else if (preference.equals(mDelete)) {
new AlertDialog.Builder(this)
new AlertDialog.Builder(getActivity())
.setMessage(R.string.delete_repo_confirm)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mSyncthingService.getApi().deleteRepo(mRepo, RepoSettingsActivity.this);
finish();
mSyncthingService.getApi().deleteRepo(mRepo, getActivity());
getActivity().finish();
}
})
.setNegativeButton(android.R.string.no, null)
@ -308,7 +310,7 @@ public class RepoSettingsActivity extends PreferenceActivity
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == DIRECTORY_REQUEST_CODE) {
mRepo.Directory = data.getStringExtra(FolderPickerActivity.EXTRA_RESULT_DIRECTORY);
mDirectory.setSummary(mRepo.Directory);
@ -317,8 +319,8 @@ public class RepoSettingsActivity extends PreferenceActivity
}
private void repoUpdated() {
if (getIntent().getAction().equals(ACTION_EDIT)) {
mSyncthingService.getApi().editRepo(mRepo, false, this);
if (!mIsCreate) {
mSyncthingService.getApi().editRepo(mRepo, false, getActivity());
}
}

View file

@ -86,9 +86,10 @@ public class ReposFragment extends ListFragment implements SyncthingService.OnAp
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity(), RepoSettingsActivity.class);
intent.setAction(RepoSettingsActivity.ACTION_EDIT);
intent.putExtra(RepoSettingsActivity.KEY_REPO_ID, mAdapter.getItem(i).ID);
Intent intent = new Intent(getActivity(), SettingsActivity.class)
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
.putExtra(SettingsActivity.EXTRA_IS_CREATE, false)
.putExtra(RepoSettingsFragment.EXTRA_REPO_ID, mAdapter.getItem(i).ID);
startActivity(intent);
}

View file

@ -1,183 +1,86 @@
package com.nutomic.syncthingandroid.gui;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.support.v4.app.NavUtils;
import android.text.InputType;
import android.view.MenuItem;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.syncthing.RestApi;
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.syncthing.SyncthingServiceBinder;
public class SettingsActivity extends PreferenceActivity
implements SyncthingService.OnApiChangeListener, Preference.OnPreferenceChangeListener {
private static final String SYNCTHING_OPTIONS_KEY = "syncthing_options";
private static final String SYNCTHING_GUI_KEY = "syncthing_gui";
private static final String SYNCTHING_VERSION_KEY = "syncthing_version";
private CheckBoxPreference mStopNotCharging;
private CheckBoxPreference mStopMobileData;
private Preference mVersion;
private PreferenceScreen mOptionsScreen;
private PreferenceScreen mGuiScreen;
private SyncthingService mSyncthingService;
/**
* Binds to service and sets syncthing preferences from Rest API.
* General Activity used by all PreferenceFragments.
*/
private final ServiceConnection mSyncthingServiceConnection = new ServiceConnection() {
public class SettingsActivity extends ActionBarActivity {
public void onServiceConnected(ComponentName className, IBinder service) {
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
mSyncthingService = binder.getService();
mSyncthingService.registerOnApiChangeListener(SettingsActivity.this);
}
public static final String ACTION_APP_SETTINGS_FRAGMENT = "app_settings_fragment";
public void onServiceDisconnected(ComponentName className) {
mSyncthingService = null;
}
};
public static final String ACTION_NODE_SETTINGS_FRAGMENT = "node_settings_fragment";
public static final String ACTION_REPO_SETTINGS_FRAGMENT = "repo_settings_fragment";
/**
* Must be set for {@link #ACTION_NODE_SETTINGS_FRAGMENT} and
* {@link #ACTION_REPO_SETTINGS_FRAGMENT} to determine if an existing repo/node should be
* edited or a new one created.
*
* If this is false, {@link RepoSettingsFragment#EXTRA_REPO_ID} or
* {@link NodeSettingsFragment#EXTRA_NODE_ID} must be set (according to the selected fragment).
*/
public static final String EXTRA_IS_CREATE = "create";
private Fragment mFragment;
@Override
public void onApiChange(SyncthingService.State currentState) {
mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
mGuiScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
mVersion.setSummary(mSyncthingService.getApi().getVersion());
if (currentState == SyncthingService.State.ACTIVE) {
for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) {
Preference pref = mOptionsScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsActivity.this);
String value = mSyncthingService.getApi()
.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
applyPreference(pref, value);
}
for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) {
Preference pref = mGuiScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsActivity.this);
String value = mSyncthingService.getApi()
.getValue(RestApi.TYPE_GUI, pref.getKey());
applyPreference(pref, value);
}
}
}
/**
* Applies the given value to the preference.
*
* If pref is an EditTextPreference, setText is used and the value shown as summary. If pref is
* a CheckBoxPreference, setChecked is used (by parsing value as Boolean).
*/
private void applyPreference(Preference pref, String value) {
if (pref instanceof EditTextPreference) {
((EditTextPreference) pref).setText(value);
pref.setSummary(value);
}
else if (pref instanceof CheckBoxPreference) {
((CheckBoxPreference) pref).setChecked(Boolean.parseBoolean(value));
}
}
/**
* Loads layout, sets version from Rest API.
*
* Manual target API as we manually check if ActionBar is available (for ActionBar back button).
*/
@Override
@SuppressLint("AppCompatMethod")
@TargetApi(11)
public void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState != null) {
mFragment = fm.getFragment(savedInstanceState,
savedInstanceState.getString("fragment_name"));
}
bindService(new Intent(this, SyncthingService.class),
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
addPreferencesFromResource(R.xml.app_settings);
PreferenceScreen screen = getPreferenceScreen();
mStopNotCharging = (CheckBoxPreference) findPreference("stop_sync_on_mobile_data");
mStopNotCharging.setOnPreferenceChangeListener(this);
mStopMobileData = (CheckBoxPreference) findPreference("stop_sync_while_not_charging");
mStopMobileData.setOnPreferenceChangeListener(this);
mVersion = screen.findPreference(SYNCTHING_VERSION_KEY);
mOptionsScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_OPTIONS_KEY);
mGuiScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_GUI_KEY);
else {
switch (getIntent().getAction()) {
case ACTION_APP_SETTINGS_FRAGMENT:
setTitle(R.string.settings_title);
mFragment = new SettingsFragment();
break;
case ACTION_NODE_SETTINGS_FRAGMENT:
mFragment = new NodeSettingsFragment();
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
}
@Override
public void onDestroy() {
super.onDestroy();
unbindService(mSyncthingServiceConnection);
break;
case ACTION_REPO_SETTINGS_FRAGMENT:
mFragment = new RepoSettingsFragment();
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
}
/**
* Handles ActionBar back selected.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
break;
default:
return super.onOptionsItemSelected(item);
throw new IllegalArgumentException(
"You must provide the requested fragment type as an extra.");
}
}
/**
* Sends the updated value to {@link }RestApi}, and sets it as the summary
* for EditTextPreference.
*/
fm.beginTransaction()
.replace(android.R.id.content, mFragment)
.commit();
}
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
if (preference instanceof EditTextPreference) {
String value = (String) o;
preference.setSummary(value);
EditTextPreference etp = (EditTextPreference) preference;
if (etp.getEditText().getInputType() == InputType.TYPE_CLASS_NUMBER) {
o = Integer.parseInt((String) o);
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String fragmentClassName = mFragment.getClass().getName();
outState.putString("fragment_name", fragmentClassName);
FragmentManager fm = getSupportFragmentManager();
fm.putFragment(outState, fragmentClassName, mFragment);
}
if (preference.equals(mStopNotCharging) || preference.equals(mStopMobileData)) {
mSyncthingService.updateState();
}
else if (mOptionsScreen.findPreference(preference.getKey()) != null) {
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o,
preference.getKey().equals("ListenAddress"), this);
}
else if (mGuiScreen.findPreference(preference.getKey()) != null) {
mSyncthingService.getApi().setValue(
RestApi.TYPE_GUI, preference.getKey(), o, false, this);
public boolean getIsCreate() {
return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false);
}
return true;
}
}

View file

@ -0,0 +1,177 @@
package com.nutomic.syncthingandroid.gui;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
import android.support.v4.preference.PreferenceFragment;
import android.support.v7.app.ActionBarActivity;
import android.text.InputType;
import android.view.MenuItem;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.syncthing.RestApi;
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.syncthing.SyncthingServiceBinder;
public class SettingsFragment extends PreferenceFragment
implements SyncthingService.OnApiChangeListener, Preference.OnPreferenceChangeListener {
private static final String SYNCTHING_OPTIONS_KEY = "syncthing_options";
private static final String SYNCTHING_GUI_KEY = "syncthing_gui";
private static final String SYNCTHING_VERSION_KEY = "syncthing_version";
private CheckBoxPreference mStopNotCharging;
private CheckBoxPreference mStopMobileData;
private Preference mVersion;
private PreferenceScreen mOptionsScreen;
private PreferenceScreen mGuiScreen;
private SyncthingService mSyncthingService;
/**
* Binds to service and sets syncthing preferences from Rest API.
*/
private final ServiceConnection mSyncthingServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
SyncthingServiceBinder binder = (SyncthingServiceBinder) service;
mSyncthingService = binder.getService();
mSyncthingService.registerOnApiChangeListener(SettingsFragment.this);
}
public void onServiceDisconnected(ComponentName className) {
mSyncthingService = null;
}
};
@Override
public void onApiChange(SyncthingService.State currentState) {
mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
mGuiScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
mVersion.setSummary(mSyncthingService.getApi().getVersion());
if (currentState == SyncthingService.State.ACTIVE) {
for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) {
Preference pref = mOptionsScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsFragment.this);
String value = mSyncthingService.getApi()
.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
applyPreference(pref, value);
}
for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) {
Preference pref = mGuiScreen.getPreference(i);
pref.setOnPreferenceChangeListener(SettingsFragment.this);
String value = mSyncthingService.getApi()
.getValue(RestApi.TYPE_GUI, pref.getKey());
applyPreference(pref, value);
}
}
}
/**
* Applies the given value to the preference.
*
* If pref is an EditTextPreference, setText is used and the value shown as summary. If pref is
* a CheckBoxPreference, setChecked is used (by parsing value as Boolean).
*/
private void applyPreference(Preference pref, String value) {
if (pref instanceof EditTextPreference) {
((EditTextPreference) pref).setText(value);
pref.setSummary(value);
}
else if (pref instanceof CheckBoxPreference) {
((CheckBoxPreference) pref).setChecked(Boolean.parseBoolean(value));
}
}
/**
* Loads layout, sets version from Rest API.
*
* Manual target API as we manually check if ActionBar is available (for ActionBar back button).
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().bindService(new Intent(getActivity(), SyncthingService.class),
mSyncthingServiceConnection, Context.BIND_AUTO_CREATE);
addPreferencesFromResource(R.xml.app_settings);
PreferenceScreen screen = getPreferenceScreen();
mStopNotCharging = (CheckBoxPreference) findPreference("stop_sync_on_mobile_data");
mStopNotCharging.setOnPreferenceChangeListener(this);
mStopMobileData = (CheckBoxPreference) findPreference("stop_sync_while_not_charging");
mStopMobileData.setOnPreferenceChangeListener(this);
mVersion = screen.findPreference(SYNCTHING_VERSION_KEY);
mOptionsScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_OPTIONS_KEY);
mGuiScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_GUI_KEY);
}
@Override
public void onDestroy() {
super.onDestroy();
getActivity().unbindService(mSyncthingServiceConnection);
}
/**
* Handles ActionBar back selected.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(getActivity());
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Sends the updated value to {@link }RestApi}, and sets it as the summary
* for EditTextPreference.
*/
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
if (preference instanceof EditTextPreference) {
String value = (String) o;
preference.setSummary(value);
EditTextPreference etp = (EditTextPreference) preference;
if (etp.getEditText().getInputType() == InputType.TYPE_CLASS_NUMBER) {
o = Integer.parseInt((String) o);
}
}
if (preference.equals(mStopNotCharging) || preference.equals(mStopMobileData)) {
mSyncthingService.updateState();
}
else if (mOptionsScreen.findPreference(preference.getKey()) != null) {
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o,
preference.getKey().equals("ListenAddress"), getActivity());
}
else if (mGuiScreen.findPreference(preference.getKey()) != null) {
mSyncthingService.getApi().setValue(
RestApi.TYPE_GUI, preference.getKey(), o, false, getActivity());
}
return true;
}
}

View file

@ -19,6 +19,7 @@ import android.util.Pair;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.gui.MainActivity;
import com.nutomic.syncthingandroid.gui.SettingsActivity;
import com.nutomic.syncthingandroid.gui.SettingsFragment;
import com.nutomic.syncthingandroid.util.ConfigXml;
import org.apache.http.HttpResponse;
@ -409,7 +410,9 @@ public class SyncthingService extends Service {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
activity.finish();
activity.startActivity(new Intent(activity, SettingsActivity.class));
Intent intent = new Intent(activity, SettingsActivity.class)
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT);
activity.startActivity(intent);
}
})
.setNegativeButton(R.string.exit,

View file

@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/create"
android:title="@string/add"
android:showAsAction="always" />
app:showAsAction="always" />
<item
android:id="@+id/share_node_id"
android:icon="@android:drawable/ic_menu_share"
android:title="@string/share_node_id"
android:showAsAction="always" />
app:showAsAction="always" />
</menu>

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/create"
android:title="@string/create"
android:showAsAction="always" />
app:showAsAction="always" />
</menu>

View file

@ -76,7 +76,7 @@
<!-- Title for announce server status -->
<string name="announce_server">Announce Server</string>
<!-- RepoSettingsActivity -->
<!-- RepoSettingsFragment -->
<!-- Setting title -->
@ -100,10 +100,10 @@
<!-- Setting title -->
<string name="delete_repo">Delete Repository</string>
<!-- Title for RepoSettingsActivity in create mode -->
<!-- Title for RepoSettingsFragment in create mode -->
<string name="create_repo">Create Repository</string>
<!-- Title for RepoSettingsActivity in edit mode -->
<!-- Title for RepoSettingsFragment in edit mode -->
<string name="edit_repo">Edit Repository</string>
<!-- Menu item to confirm repo creation -->
@ -121,7 +121,7 @@
<!-- Toast shown when selecting 'nodes' if no nodes have been added -->
<string name="no_nodes">Please connect a node first.</string>
<!-- NodeSettingsActivity -->
<!-- NodeSettingsFragment -->
<!-- Setting title -->
@ -139,13 +139,13 @@
<!-- Setting title -->
<string name="delete_node">Delete Node</string>
<!-- Title for NodeSettingsActivity in create mode -->
<!-- Title for NodeSettingsFragment in create mode -->
<string name="add_node">Add Node</string>
<!-- Menu item to confirm adding a node -->
<string name="add">Add</string>
<!-- Title for NodeSettingsActivity in edit mode -->
<!-- Title for NodeSettingsFragment in edit mode -->
<string name="edit_node">Edit Node</string>
<!-- Dialog shown when attempting to delete a node -->
@ -185,7 +185,7 @@ This app is currently in Alpha state, and you may experience bugs, performance p
There is currently no special handling for mobile data, so it may use up your data volume if active.\n\n\
Please report any problems you encounter.</string>
<!-- SettingsActivity -->
<!-- SettingsFragment -->
<!-- Activity title -->