From d2e0c291b6e42c6dd620472809e1a723b4b20009 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sun, 3 Aug 2014 21:54:30 +0200 Subject: [PATCH] Use PreferenceFragments with a wrapper instead of SettingsFragments (fixes #64). --- .gitmodules | 3 + build.gradle | 1 + .../android-support-v4-preferencefragment | 1 + settings.gradle | 2 + src/main/AndroidManifest.xml | 7 +- .../syncthingandroid/gui/MainActivity.java | 14 +- ...ctivity.java => NodeSettingsFragment.java} | 93 ++++---- .../syncthingandroid/gui/NodesFragment.java | 7 +- ...ctivity.java => RepoSettingsFragment.java} | 98 ++++---- .../syncthingandroid/gui/ReposFragment.java | 7 +- .../gui/SettingsActivity.java | 223 +++++------------- .../gui/SettingsFragment.java | 177 ++++++++++++++ .../syncthing/SyncthingService.java | 5 +- src/main/res/menu/node_settings.xml | 7 +- src/main/res/menu/repo_settings.xml | 7 +- src/main/res/values/strings.xml | 14 +- 16 files changed, 377 insertions(+), 289 deletions(-) create mode 160000 libraries/android-support-v4-preferencefragment create mode 100644 settings.gradle rename src/main/java/com/nutomic/syncthingandroid/gui/{NodeSettingsActivity.java => NodeSettingsFragment.java} (75%) rename src/main/java/com/nutomic/syncthingandroid/gui/{RepoSettingsActivity.java => RepoSettingsFragment.java} (76%) create mode 100644 src/main/java/com/nutomic/syncthingandroid/gui/SettingsFragment.java diff --git a/.gitmodules b/.gitmodules index 01fed3c4..b2ae8c24 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/build.gradle b/build.gradle index a038ecb8..733cc49f 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ repositories { dependencies { compile 'com.android.support:appcompat-v7:19.1.+' + compile project(':android-support-v4-preferencefragment') } preBuild { diff --git a/libraries/android-support-v4-preferencefragment b/libraries/android-support-v4-preferencefragment new file mode 160000 index 00000000..269e53b7 --- /dev/null +++ b/libraries/android-support-v4-preferencefragment @@ -0,0 +1 @@ +Subproject commit 269e53b7b94b8001d2192b0ff2effb12eadaab07 diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..5d102a70 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':android-support-v4-preferencefragment' +project(':android-support-v4-preferencefragment').projectDir = new File('libraries/android-support-v4-preferencefragment') diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index d6b50bca..478a0b5d 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -39,8 +39,7 @@ android:value=".gui.MainActivity" /> + android:name=".gui.SettingsActivity" > @@ -48,10 +47,6 @@ - - diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/MainActivity.java b/src/main/java/com/nutomic/syncthingandroid/gui/MainActivity.java index 547f4b2a..60b68c03 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/MainActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/MainActivity.java @@ -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); diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsActivity.java b/src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsFragment.java similarity index 75% rename from src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsActivity.java rename to src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsFragment.java index f4239ee6..f41a1df3 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/NodeSettingsFragment.java @@ -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 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(); } } diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/NodesFragment.java b/src/main/java/com/nutomic/syncthingandroid/gui/NodesFragment.java index b7e0dc0b..827fa989 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/NodesFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/NodesFragment.java @@ -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); } diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsActivity.java b/src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsFragment.java similarity index 76% rename from src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsActivity.java rename to src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsFragment.java index bf1882fc..4c7bf580 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/RepoSettingsFragment.java @@ -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(); 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 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 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()); } } diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/ReposFragment.java b/src/main/java/com/nutomic/syncthingandroid/gui/ReposFragment.java index 18cb2415..63ee4084 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/ReposFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/ReposFragment.java @@ -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); } diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/SettingsActivity.java b/src/main/java/com/nutomic/syncthingandroid/gui/SettingsActivity.java index 63c43176..5e471f0f 100644 --- a/src/main/java/com/nutomic/syncthingandroid/gui/SettingsActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/gui/SettingsActivity.java @@ -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 { +/** + * General Activity used by all PreferenceFragments. + */ +public class SettingsActivity extends ActionBarActivity { - private static final String SYNCTHING_OPTIONS_KEY = "syncthing_options"; + public static final String ACTION_APP_SETTINGS_FRAGMENT = "app_settings_fragment"; - private static final String SYNCTHING_GUI_KEY = "syncthing_gui"; + public static final String ACTION_NODE_SETTINGS_FRAGMENT = "node_settings_fragment"; - 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; + public static final String ACTION_REPO_SETTINGS_FRAGMENT = "repo_settings_fragment"; /** - * Binds to service and sets syncthing preferences from Rest API. + * 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). */ - private final ServiceConnection mSyncthingServiceConnection = new ServiceConnection() { + public static final String EXTRA_IS_CREATE = "create"; - public void onServiceConnected(ComponentName className, IBinder service) { - SyncthingServiceBinder binder = (SyncthingServiceBinder) service; - mSyncthingService = binder.getService(); - mSyncthingService.registerOnApiChangeListener(SettingsActivity.this); - } - - public void onServiceDisconnected(ComponentName className) { - mSyncthingService = null; - } - }; + 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); - } - - @Override - public void onDestroy() { - super.onDestroy(); - unbindService(mSyncthingServiceConnection); - } - - /** - * Handles ActionBar back selected. - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - 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); + 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"); + } + break; + case ACTION_REPO_SETTINGS_FRAGMENT: + mFragment = new RepoSettingsFragment(); + if (!getIntent().hasExtra(EXTRA_IS_CREATE)) { + throw new IllegalArgumentException("EXTRA_IS_CREATE must be set"); + } + break; + default: + throw new IllegalArgumentException( + "You must provide the requested fragment type as an extra."); } } - 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); - } - - return true; + fm.beginTransaction() + .replace(android.R.id.content, mFragment) + .commit(); } + + @Override + 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); + } + + public boolean getIsCreate() { + return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false); + } + } diff --git a/src/main/java/com/nutomic/syncthingandroid/gui/SettingsFragment.java b/src/main/java/com/nutomic/syncthingandroid/gui/SettingsFragment.java new file mode 100644 index 00000000..52f8cfdb --- /dev/null +++ b/src/main/java/com/nutomic/syncthingandroid/gui/SettingsFragment.java @@ -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; + } +} diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java index c3aafe19..6dc39e11 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java @@ -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, diff --git a/src/main/res/menu/node_settings.xml b/src/main/res/menu/node_settings.xml index 8108cf11..1ddf813a 100644 --- a/src/main/res/menu/node_settings.xml +++ b/src/main/res/menu/node_settings.xml @@ -1,16 +1,17 @@ - + + app:showAsAction="always" /> + app:showAsAction="always" /> diff --git a/src/main/res/menu/repo_settings.xml b/src/main/res/menu/repo_settings.xml index e24eecef..1ea63153 100644 --- a/src/main/res/menu/repo_settings.xml +++ b/src/main/res/menu/repo_settings.xml @@ -1,9 +1,10 @@ - + - \ No newline at end of file + app:showAsAction="always" /> + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 6d6843cb..5a20ddae 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -76,7 +76,7 @@ Announce Server - + @@ -100,10 +100,10 @@ Delete Repository - + Create Repository - + Edit Repository @@ -121,7 +121,7 @@ Please connect a node first. - + @@ -139,13 +139,13 @@ Delete Node - + Add Node Add - + Edit 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. - +