diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4419dde8..50f56bdc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,6 +41,6 @@ screenshots: *link to file* (only for UI problems) Always welcome. -Code should follow the [Android Code Style Guidelines](https://source.android.com/source/code-style.html#java-language-rules), with the exception that we use tabs, not spaces for indentation. +Code should follow the [Android Code Style Guidelines](https://source.android.com/source/code-style.html#java-language-rules). This can be done automatically in Android Studio. Lint warnings should be fixed. If that's not possible, they should be ignored as specifically as possible. diff --git a/build.gradle b/build.gradle index 733cc49f..5ffdae23 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ buildscript { - repositories { - mavenCentral() - } + repositories { + mavenCentral() + } - dependencies { - classpath 'com.android.tools.build:gradle:0.12.+' - classpath 'com.alexvasilkov:android_sign:0.2+' - } + dependencies { + classpath 'com.android.tools.build:gradle:0.12.+' + classpath 'com.alexvasilkov:android_sign:0.2+' + } } import java.util.regex.Pattern @@ -15,126 +15,126 @@ apply plugin: 'com.android.application' apply plugin: 'android_sign' repositories { - mavenCentral() + mavenCentral() } dependencies { - compile 'com.android.support:appcompat-v7:19.1.+' - compile project(':android-support-v4-preferencefragment') + compile 'com.android.support:appcompat-v7:19.1.+' + compile project(':android-support-v4-preferencefragment') } preBuild { - dependsOn 'buildNative' + dependsOn 'buildNative' } android { - compileSdkVersion 19 - buildToolsVersion "19.1.0" + compileSdkVersion 19 + buildToolsVersion "19.1.0" - defaultConfig { - versionCode getVersionCodeFromManifest() - } + defaultConfig { + versionCode getVersionCodeFromManifest() + } - sourceSets { - main { - jniLibs.srcDir file("libs/") - } - } + sourceSets { + main { + jniLibs.srcDir file("libs/") + } + } - signingConfigs { - release { - // Android Studio does not pass environment variables. - // This means you have to use the command line for release builds. - def ks = System.getenv("KEYSTORE") - def ka = System.getenv("KEY_ALIAS") - if (ks != null && ka != null) { - storeFile file(ks) - keyAlias ka - } - } - } + signingConfigs { + release { + // Android Studio does not pass environment variables. + // This means you have to use the command line for release builds. + def ks = System.getenv("KEYSTORE") + def ka = System.getenv("KEY_ALIAS") + if (ks != null && ka != null) { + storeFile file(ks) + keyAlias ka + } + } + } - buildTypes { - debug { - applicationIdSuffix ".debug" - debuggable true - } - release { - signingConfig signingConfigs.release - } - } + buildTypes { + debug { + applicationIdSuffix ".debug" + debuggable true + } + release { + signingConfig signingConfigs.release + } + } - productFlavors { - x86 { - versionCode Integer.parseInt("4" + defaultConfig.versionCode) - ndk { - abiFilter "x86" - } - } - armeabi_v7a { - versionCode Integer.parseInt("3" + defaultConfig.versionCode) - ndk { - abiFilter "armeabi-v7a" - } - } - armeabi { - versionCode Integer.parseInt("2" + defaultConfig.versionCode) - ndk { - abiFilter "armeabi" - } - } - mips { - versionCode Integer.parseInt("1" + defaultConfig.versionCode) - ndk { - abiFilter "mips" - } - } - fat { - versionCode Integer.parseInt("0" + defaultConfig.versionCode) - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } + productFlavors { + x86 { + versionCode Integer.parseInt("4" + defaultConfig.versionCode) + ndk { + abiFilter "x86" + } + } + armeabi_v7a { + versionCode Integer.parseInt("3" + defaultConfig.versionCode) + ndk { + abiFilter "armeabi-v7a" + } + } + armeabi { + versionCode Integer.parseInt("2" + defaultConfig.versionCode) + ndk { + abiFilter "armeabi" + } + } + mips { + versionCode Integer.parseInt("1" + defaultConfig.versionCode) + ndk { + abiFilter "mips" + } + } + fat { + versionCode Integer.parseInt("0" + defaultConfig.versionCode) + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } } def getVersionCodeFromManifest() { - def manifestFile = file(android.sourceSets.main.manifest.srcFile) - def pattern = Pattern.compile("versionCode=\"(\\d+)\"") - def matcher = pattern.matcher(manifestFile.getText()) - matcher.find() - return Integer.parseInt(matcher.group(1)) + def manifestFile = file(android.sourceSets.main.manifest.srcFile) + def pattern = Pattern.compile("versionCode=\"(\\d+)\"") + def matcher = pattern.matcher(manifestFile.getText()) + matcher.find() + return Integer.parseInt(matcher.group(1)) } task buildNative(type: Exec) { - outputs.upToDateWhen { false } - executable = './build-syncthing.sh' + outputs.upToDateWhen { false } + executable = './build-syncthing.sh' } task copyNative(type: Copy) { - def lib_dir = "libs/" - new File(lib_dir).mkdirs() - def st_dir = "bin/"; - from st_dir + 'syncthing-x86', st_dir + 'syncthing-armeabi', st_dir + 'syncthing-armeabi-v7a'; - into lib_dir - rename('syncthing-x86', 'x86/libsyncthing.so') + def lib_dir = "libs/" + new File(lib_dir).mkdirs() + def st_dir = "bin/"; + from st_dir + 'syncthing-x86', st_dir + 'syncthing-armeabi', st_dir + 'syncthing-armeabi-v7a'; + into lib_dir + rename('syncthing-x86', 'x86/libsyncthing.so') rename('syncthing-armeabi-v7a', 'armeabi-v7a/libsyncthing.so') - rename('syncthing-armeabi', 'armeabi/libsyncthing.so') + rename('syncthing-armeabi', 'armeabi/libsyncthing.so') } buildNative.finalizedBy copyNative task cleanBin(type: Delete) { - delete 'bin/' + delete 'bin/' } copyNative.finalizedBy cleanBin task cleanNative(type: Delete) { - delete 'bin/' - delete 'build/' - delete 'libs/' - delete 'ext/syncthing/bin/' - delete 'ext/syncthing/pkg/' + delete 'bin/' + delete 'build/' + delete 'libs/' + delete 'ext/syncthing/bin/' + delete 'ext/syncthing/pkg/' } clean.dependsOn cleanNative diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index a7e60935..054f2a7a 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,75 +1,75 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.nutomic.syncthingandroid" + android:versionCode="33" + android:versionName="0.4.19" + tools:ignore="GradleOverrides" > - + - - - - - + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - + + + + + diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/FolderPickerActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/FolderPickerActivity.java index c7356ec2..ae570e70 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/FolderPickerActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/FolderPickerActivity.java @@ -32,42 +32,42 @@ import java.util.Arrays; * Activity that allows selecting a directory in the local file system. */ public class FolderPickerActivity extends SyncthingActivity - implements AdapterView.OnItemClickListener, SyncthingService.OnApiChangeListener { + implements AdapterView.OnItemClickListener, SyncthingService.OnApiChangeListener { - private static final String TAG = "FolderPickerActivity"; + private static final String TAG = "FolderPickerActivity"; - public static final String EXTRA_INITIAL_DIRECTORY = "initial_directory"; + public static final String EXTRA_INITIAL_DIRECTORY = "initial_directory"; - public static final String EXTRA_RESULT_DIRECTORY = "result_directory"; + public static final String EXTRA_RESULT_DIRECTORY = "result_directory"; - private ListView mListView; + private ListView mListView; - private FileAdapter mAdapter; + private FileAdapter mAdapter; - private File mLocation; + private File mLocation; - @Override + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.folder_picker_activity); - mListView = (ListView) findViewById(android.R.id.list); - mListView.setOnItemClickListener(this); - mListView.setEmptyView(findViewById(android.R.id.empty)); - mAdapter = new FileAdapter(this); - mListView.setAdapter(mAdapter); + mListView = (ListView) findViewById(android.R.id.list); + mListView.setOnItemClickListener(this); + mListView.setEmptyView(findViewById(android.R.id.empty)); + mAdapter = new FileAdapter(this); + mListView.setAdapter(mAdapter); - mLocation = new File(getIntent().getStringExtra(EXTRA_INITIAL_DIRECTORY)); - refresh(); + mLocation = new File(getIntent().getStringExtra(EXTRA_INITIAL_DIRECTORY)); + refresh(); } - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - super.onServiceConnected(componentName, iBinder); - getService().registerOnApiChangeListener(this); - } + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + super.onServiceConnected(componentName, iBinder); + getService().registerOnApiChangeListener(this); + } @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -78,116 +78,116 @@ public class FolderPickerActivity extends SyncthingActivity @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.create_folder: - final EditText et = new EditText(this); - AlertDialog dialog = new AlertDialog.Builder(this) - .setTitle(R.string.create_folder) - .setView(et) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - createFolder(et.getText().toString()); - } - }) - .setNegativeButton(android.R.string.cancel, null) - .create(); - dialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialogInterface) { - ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)) - .showSoftInput(et, InputMethodManager.SHOW_IMPLICIT); - } - }); - dialog.show(); - return true; - case R.id.select: - Intent intent = new Intent() - .putExtra(EXTRA_RESULT_DIRECTORY, mLocation.getAbsolutePath()); - setResult(Activity.RESULT_OK, intent); - finish(); - return true; - case android.R.id.home: - finish(); - return true; - default: - return super.onOptionsItemSelected(item); - } + switch (item.getItemId()) { + case R.id.create_folder: + final EditText et = new EditText(this); + AlertDialog dialog = new AlertDialog.Builder(this) + .setTitle(R.string.create_folder) + .setView(et) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + createFolder(et.getText().toString()); + } + } + ) + .setNegativeButton(android.R.string.cancel, null) + .create(); + dialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialogInterface) { + ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)) + .showSoftInput(et, InputMethodManager.SHOW_IMPLICIT); + } + }); + dialog.show(); + return true; + case R.id.select: + Intent intent = new Intent() + .putExtra(EXTRA_RESULT_DIRECTORY, mLocation.getAbsolutePath()); + setResult(Activity.RESULT_OK, intent); + finish(); + return true; + case android.R.id.home: + finish(); + return true; + default: + return super.onOptionsItemSelected(item); + } } - /** - * Creates a new folder with the given name and enters it. - */ - private void createFolder(String name) { - File newFolder = new File(mLocation, name); - newFolder.mkdir(); - mLocation = newFolder; - refresh(); - } + /** + * Creates a new folder with the given name and enters it. + */ + private void createFolder(String name) { + File newFolder = new File(mLocation, name); + newFolder.mkdir(); + mLocation = newFolder; + refresh(); + } - /** - * Refreshes the ListView to show the contents of the folder in {@code }mLocation.peek()}. - */ - private void refresh() { - mAdapter.clear(); - File[] contents = mLocation.listFiles(new FileFilter() { - @Override - public boolean accept(File file) { - return file.isDirectory(); - } - }); - Arrays.sort(contents); - for (File f : contents) { - mAdapter.add(f); - } - } + /** + * Refreshes the ListView to show the contents of the folder in {@code }mLocation.peek()}. + */ + private void refresh() { + mAdapter.clear(); + File[] contents = mLocation.listFiles(new FileFilter() { + @Override + public boolean accept(File file) { + return file.isDirectory(); + } + }); + Arrays.sort(contents); + for (File f : contents) { + mAdapter.add(f); + } + } - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - mLocation = mAdapter.getItem(i); - refresh(); - } + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + mLocation = mAdapter.getItem(i); + refresh(); + } - private class FileAdapter extends ArrayAdapter { + private class FileAdapter extends ArrayAdapter { - public FileAdapter(Context context) { - super(context, android.R.layout.simple_list_item_1); - } + public FileAdapter(Context context) { + super(context, android.R.layout.simple_list_item_1); + } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false); - } + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + LayoutInflater inflater = (LayoutInflater) getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false); + } - TextView title = (TextView) convertView.findViewById(android.R.id.text1); - title.setText(getItem(position).getName()); - return convertView; - } - } + TextView title = (TextView) convertView.findViewById(android.R.id.text1); + title.setText(getItem(position).getName()); + return convertView; + } + } - @Override - public void onBackPressed() { - if (!mLocation.equals(Environment.getExternalStorageDirectory())) { - mLocation = mLocation.getParentFile(); - refresh(); - } - else { - setResult(Activity.RESULT_CANCELED); - finish(); - } - } + @Override + public void onBackPressed() { + if (!mLocation.equals(Environment.getExternalStorageDirectory())) { + mLocation = mLocation.getParentFile(); + refresh(); + } else { + setResult(Activity.RESULT_CANCELED); + finish(); + } + } - @Override - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) { - setResult(Activity.RESULT_CANCELED); - SyncthingService.showDisabledDialog(this); - finish(); - } - } + @Override + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE) { + setResult(Activity.RESULT_CANCELED); + SyncthingService.showDisabledDialog(this); + finish(); + } + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java index 9c64bd55..108c1a6a 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java @@ -37,253 +37,254 @@ import com.nutomic.syncthingandroid.syncthing.SyncthingService; * {@link com.nutomic.syncthingandroid.fragments.LocalNodeInfoFragment} in the navigation drawer. */ public class MainActivity extends SyncthingActivity - implements SyncthingService.OnApiChangeListener { + implements SyncthingService.OnApiChangeListener { - private AlertDialog mLoadingDialog; + private AlertDialog mLoadingDialog; - /** - * Causes population of repo and node lists, unlocks info drawer. - */ - @Override - @SuppressLint("InflateParams") - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) { - if (currentState == SyncthingService.State.DISABLED) { - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); - } - SyncthingService.showDisabledDialog(this); - } - else if (mLoadingDialog == null) { - final SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(MainActivity.this); + /** + * Causes population of repo and node lists, unlocks info drawer. + */ + @Override + @SuppressLint("InflateParams") + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) { + if (currentState == SyncthingService.State.DISABLED) { + if (mLoadingDialog != null) { + mLoadingDialog.dismiss(); + } + SyncthingService.showDisabledDialog(this); + } else if (mLoadingDialog == null) { + final SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(MainActivity.this); - LayoutInflater inflater = getLayoutInflater(); - View dialogLayout = inflater.inflate(R.layout.loading_dialog, null); - TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text); - loadingText.setText((getService().isFirstStart()) - ? R.string.web_gui_creating_key - : R.string.api_loading); + LayoutInflater inflater = getLayoutInflater(); + View dialogLayout = inflater.inflate(R.layout.loading_dialog, null); + TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text); + loadingText.setText((getService().isFirstStart()) + ? R.string.web_gui_creating_key + : R.string.api_loading); - mLoadingDialog = new AlertDialog.Builder(this) - .setCancelable(false) - .setView(dialogLayout) - .show(); + mLoadingDialog = new AlertDialog.Builder(this) + .setCancelable(false) + .setView(dialogLayout) + .show(); - // Make sure the first start dialog is shown on top. - if (prefs.getBoolean("first_start", true)) { - new AlertDialog.Builder(this) - .setTitle(R.string.welcome_title) - .setMessage(R.string.welcome_text) - .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - prefs.edit().putBoolean("first_start", false).commit(); - } - }) - .show(); - } - } - return; - } + // Make sure the first start dialog is shown on top. + if (prefs.getBoolean("first_start", true)) { + new AlertDialog.Builder(this) + .setTitle(R.string.welcome_title) + .setMessage(R.string.welcome_text) + .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + prefs.edit().putBoolean("first_start", false).commit(); + } + }) + .show(); + } + } + return; + } - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); - } - mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); - mDrawerLayout.setDrawerListener(mDrawerToggle); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - } + if (mLoadingDialog != null) { + mLoadingDialog.dismiss(); + } + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); + mDrawerLayout.setDrawerListener(mDrawerToggle); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeButtonEnabled(true); + } - private final FragmentPagerAdapter mSectionsPagerAdapter = - new FragmentPagerAdapter(getSupportFragmentManager()) { + private final FragmentPagerAdapter mSectionsPagerAdapter = + new FragmentPagerAdapter(getSupportFragmentManager()) { - @Override - public Fragment getItem(int position) { - switch (position) { - case 0: return mRepositoriesFragment; - case 1: return mNodesFragment; - default: return null; - } - } + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: + return mRepositoriesFragment; + case 1: + return mNodesFragment; + default: + return null; + } + } - @Override - public int getCount() { - return 2; - } + @Override + public int getCount() { + return 2; + } - }; + }; - private ReposFragment mRepositoriesFragment; + private ReposFragment mRepositoriesFragment; - private NodesFragment mNodesFragment; + private NodesFragment mNodesFragment; - private LocalNodeInfoFragment mLocalNodeInfoFragment; + private LocalNodeInfoFragment mLocalNodeInfoFragment; - private ViewPager mViewPager; + private ViewPager mViewPager; - private ActionBarDrawerToggle mDrawerToggle; + private ActionBarDrawerToggle mDrawerToggle; - private DrawerLayout mDrawerLayout; + private DrawerLayout mDrawerLayout; - /** - * Initializes tab navigation. - */ - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - final ActionBar actionBar = getSupportActionBar(); + /** + * Initializes tab navigation. + */ + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final ActionBar actionBar = getSupportActionBar(); - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - setContentView(R.layout.main_activity); - mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + setContentView(R.layout.main_activity); + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mViewPager = (ViewPager) findViewById(R.id.pager); - mViewPager.setAdapter(mSectionsPagerAdapter); - mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageSelected(int position) { - actionBar.setSelectedNavigationItem(position); - } - }); + mViewPager = (ViewPager) findViewById(R.id.pager); + mViewPager.setAdapter(mSectionsPagerAdapter); + mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + actionBar.setSelectedNavigationItem(position); + } + }); - TabListener tabListener = new TabListener() { - public void onTabSelected(Tab tab, FragmentTransaction ft) { - mViewPager.setCurrentItem(tab.getPosition()); - } + TabListener tabListener = new TabListener() { + public void onTabSelected(Tab tab, FragmentTransaction ft) { + mViewPager.setCurrentItem(tab.getPosition()); + } - @Override - public void onTabReselected(Tab tab, FragmentTransaction ft) { - } + @Override + public void onTabReselected(Tab tab, FragmentTransaction ft) { + } - @Override - public void onTabUnselected(Tab tab, FragmentTransaction ft) { - } - }; + @Override + public void onTabUnselected(Tab tab, FragmentTransaction ft) { + } + }; - actionBar.addTab(actionBar.newTab() - .setText(R.string.repositories_fragment_title) - .setTabListener(tabListener)); - actionBar.addTab(actionBar.newTab() - .setText(R.string.nodes_fragment_title) - .setTabListener(tabListener)); + actionBar.addTab(actionBar.newTab() + .setText(R.string.repositories_fragment_title) + .setTabListener(tabListener)); + actionBar.addTab(actionBar.newTab() + .setText(R.string.nodes_fragment_title) + .setTabListener(tabListener)); - if (savedInstanceState != null) { - FragmentManager fm = getSupportFragmentManager(); - mRepositoriesFragment = (ReposFragment) fm.getFragment( - savedInstanceState, ReposFragment.class.getName()); - mNodesFragment = (NodesFragment) fm.getFragment( - savedInstanceState, NodesFragment.class.getName()); - mLocalNodeInfoFragment = (LocalNodeInfoFragment) fm.getFragment( - savedInstanceState, LocalNodeInfoFragment.class.getName()); - mViewPager.setCurrentItem(savedInstanceState.getInt("currentTab")); - } - else { - mRepositoriesFragment = new ReposFragment(); - mNodesFragment = new NodesFragment(); - mLocalNodeInfoFragment = new LocalNodeInfoFragment(); - } + if (savedInstanceState != null) { + FragmentManager fm = getSupportFragmentManager(); + mRepositoriesFragment = (ReposFragment) fm.getFragment( + savedInstanceState, ReposFragment.class.getName()); + mNodesFragment = (NodesFragment) fm.getFragment( + savedInstanceState, NodesFragment.class.getName()); + mLocalNodeInfoFragment = (LocalNodeInfoFragment) fm.getFragment( + savedInstanceState, LocalNodeInfoFragment.class.getName()); + mViewPager.setCurrentItem(savedInstanceState.getInt("currentTab")); + } else { + mRepositoriesFragment = new ReposFragment(); + mNodesFragment = new NodesFragment(); + mLocalNodeInfoFragment = new LocalNodeInfoFragment(); + } - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.drawer, mLocalNodeInfoFragment) - .commit(); - mDrawerToggle = mLocalNodeInfoFragment.new Toggle(this, mDrawerLayout, - R.drawable.ic_drawer); - mDrawerLayout.setDrawerListener(mDrawerToggle); - } + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.drawer, mLocalNodeInfoFragment) + .commit(); + mDrawerToggle = mLocalNodeInfoFragment.new Toggle(this, mDrawerLayout, + R.drawable.ic_drawer); + mDrawerLayout.setDrawerListener(mDrawerToggle); + } - @Override - public void onDestroy() { - super.onDestroy(); - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); - } - } + @Override + public void onDestroy() { + super.onDestroy(); + if (mLoadingDialog != null) { + mLoadingDialog.dismiss(); + } + } - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - super.onServiceConnected(componentName, iBinder); - getService().registerOnApiChangeListener(mRepositoriesFragment); - getService().registerOnApiChangeListener(mNodesFragment); - } + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + super.onServiceConnected(componentName, iBinder); + getService().registerOnApiChangeListener(mRepositoriesFragment); + getService().registerOnApiChangeListener(mNodesFragment); + } - /** - * Saves fragment states. - */ - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - // Avoid crash if called during startup. - if (mRepositoriesFragment != null && mNodesFragment != null && - mLocalNodeInfoFragment != null) { - FragmentManager fm = getSupportFragmentManager(); - fm.putFragment(outState, ReposFragment.class.getName(), mRepositoriesFragment); - fm.putFragment(outState, NodesFragment.class.getName(), mNodesFragment); - fm.putFragment(outState, LocalNodeInfoFragment.class.getName(), mLocalNodeInfoFragment); - outState.putInt("currentTab", mViewPager.getCurrentItem()); - } - } + /** + * Saves fragment states. + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + // Avoid crash if called during startup. + if (mRepositoriesFragment != null && mNodesFragment != null && + mLocalNodeInfoFragment != null) { + FragmentManager fm = getSupportFragmentManager(); + fm.putFragment(outState, ReposFragment.class.getName(), mRepositoriesFragment); + fm.putFragment(outState, NodesFragment.class.getName(), mNodesFragment); + fm.putFragment(outState, LocalNodeInfoFragment.class.getName(), mLocalNodeInfoFragment); + outState.putInt("currentTab", mViewPager.getCurrentItem()); + } + } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.main, menu); - return true; - } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main, menu); + return true; + } - /** - * Shows menu only once syncthing service is running, and shows "share" option only when - * drawer is open. - */ - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - boolean drawerOpen = mDrawerLayout.isDrawerOpen(findViewById(R.id.drawer)); - menu.findItem(R.id.share_node_id).setVisible(drawerOpen); - return true; - } + /** + * Shows menu only once syncthing service is running, and shows "share" option only when + * drawer is open. + */ + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + boolean drawerOpen = mDrawerLayout.isDrawerOpen(findViewById(R.id.drawer)); + menu.findItem(R.id.share_node_id).setVisible(drawerOpen); + return true; + } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (mLocalNodeInfoFragment.onOptionsItemSelected(item) || - mDrawerToggle.onOptionsItemSelected(item)) { - return true; - } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (mLocalNodeInfoFragment.onOptionsItemSelected(item) || + mDrawerToggle.onOptionsItemSelected(item)) { + return true; + } - switch (item.getItemId()) { - case R.id.add_repo: - 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, 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) - .setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT)); - return true; - default: - return super.onOptionsItemSelected(item); - } - } + switch (item.getItemId()) { + case R.id.add_repo: + 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, 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) + .setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } - @Override - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - mDrawerToggle.syncState(); - } + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mDrawerToggle.syncState(); + } - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mDrawerToggle.onConfigurationChanged(newConfig); - } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mDrawerToggle.onConfigurationChanged(newConfig); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java index 5c4be58e..37f137e9 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java @@ -14,75 +14,74 @@ import com.nutomic.syncthingandroid.fragments.SettingsFragment; */ public class SettingsActivity extends SyncthingActivity { - public static final String ACTION_APP_SETTINGS_FRAGMENT = "app_settings_fragment"; + public static final String ACTION_APP_SETTINGS_FRAGMENT = "app_settings_fragment"; - public static final String ACTION_NODE_SETTINGS_FRAGMENT = "node_settings_fragment"; + public static final String ACTION_NODE_SETTINGS_FRAGMENT = "node_settings_fragment"; - public static final String ACTION_REPO_SETTINGS_FRAGMENT = "repo_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 com.nutomic.syncthingandroid.fragments.RepoSettingsFragment#EXTRA_REPO_ID} or - * {@link com.nutomic.syncthingandroid.fragments.NodeSettingsFragment#EXTRA_NODE_ID} must be set (according to the selected fragment). - */ - public static final String EXTRA_IS_CREATE = "create"; + /** + * 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 com.nutomic.syncthingandroid.fragments.RepoSettingsFragment#EXTRA_REPO_ID} or + * {@link com.nutomic.syncthingandroid.fragments.NodeSettingsFragment#EXTRA_NODE_ID} must be set (according to the selected fragment). + */ + public static final String EXTRA_IS_CREATE = "create"; - private Fragment mFragment; + private Fragment mFragment; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); - FragmentManager fm = getSupportFragmentManager(); - if (savedInstanceState != null) { - mFragment = fm.getFragment(savedInstanceState, - savedInstanceState.getString("fragment_name")); - } - 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."); - } - } + FragmentManager fm = getSupportFragmentManager(); + if (savedInstanceState != null) { + mFragment = fm.getFragment(savedInstanceState, + savedInstanceState.getString("fragment_name")); + } 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."); + } + } - fm.beginTransaction() - .replace(android.R.id.content, mFragment) - .commit(); - } + 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); - } + @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); - } + public boolean getIsCreate() { + return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/SyncthingActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/SyncthingActivity.java index 26eb80d7..534ca6b4 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/SyncthingActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/SyncthingActivity.java @@ -19,71 +19,70 @@ import java.util.LinkedList; */ public class SyncthingActivity extends ActionBarActivity implements ServiceConnection { - private SyncthingService mSyncthingService; + private SyncthingService mSyncthingService; - private LinkedList mServiceConnectedListeners = new LinkedList<>(); + private LinkedList mServiceConnectedListeners = new LinkedList<>(); - /** - * To be used for Fragments. - */ - public interface OnServiceConnectedListener { - public void onServiceConnected(); - } + /** + * To be used for Fragments. + */ + public interface OnServiceConnectedListener { + public void onServiceConnected(); + } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - bindService(new Intent(this, SyncthingService.class), - this, Context.BIND_AUTO_CREATE); - } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + bindService(new Intent(this, SyncthingService.class), + this, Context.BIND_AUTO_CREATE); + } - @Override - protected void onDestroy() { - super.onDestroy(); - unbindService(this); - } + @Override + protected void onDestroy() { + super.onDestroy(); + unbindService(this); + } - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - SyncthingServiceBinder binder = (SyncthingServiceBinder) iBinder; - mSyncthingService = binder.getService(); - for (OnServiceConnectedListener listener : mServiceConnectedListeners) { - listener.onServiceConnected(); - } - mServiceConnectedListeners.clear(); - } + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + SyncthingServiceBinder binder = (SyncthingServiceBinder) iBinder; + mSyncthingService = binder.getService(); + for (OnServiceConnectedListener listener : mServiceConnectedListeners) { + listener.onServiceConnected(); + } + mServiceConnectedListeners.clear(); + } - @Override - public void onServiceDisconnected(ComponentName componentName) { - mSyncthingService = null; - } + @Override + public void onServiceDisconnected(ComponentName componentName) { + mSyncthingService = null; + } - /** - * Used for Fragments to use the Activity's service connection. - */ - public void registerOnServiceConnectedListener(OnServiceConnectedListener listener) { - if (mSyncthingService != null) { - listener.onServiceConnected(); - } - else { - mServiceConnectedListeners.addLast(listener); - } - } + /** + * Used for Fragments to use the Activity's service connection. + */ + public void registerOnServiceConnectedListener(OnServiceConnectedListener listener) { + if (mSyncthingService != null) { + listener.onServiceConnected(); + } else { + mServiceConnectedListeners.addLast(listener); + } + } - /** - * Returns service object (or null if not bound). - */ - public SyncthingService getService() { - return mSyncthingService; - } + /** + * Returns service object (or null if not bound). + */ + public SyncthingService getService() { + return mSyncthingService; + } - /** - * Returns RestApi instance, or null if SyncthingService is not yet connected. - */ - public RestApi getApi() { - return (getService() != null) - ? getService().getApi() - : null; - } + /** + * Returns RestApi instance, or null if SyncthingService is not yet connected. + */ + public RestApi getApi() { + return (getService() != null) + ? getService().getApi() + : null; + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java index 7d1b6b9a..f2888970 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/WebGuiActivity.java @@ -17,56 +17,56 @@ import com.nutomic.syncthingandroid.syncthing.SyncthingService; */ public class WebGuiActivity extends SyncthingActivity implements SyncthingService.OnWebGuiAvailableListener { - private WebView mWebView; + private WebView mWebView; - private View mLoadingView; + private View mLoadingView; - /** - * Hides the loading screen and shows the WebView once it is fully loaded. - */ - private final WebViewClient mWebViewClient = new WebViewClient() { + /** + * Hides the loading screen and shows the WebView once it is fully loaded. + */ + private final WebViewClient mWebViewClient = new WebViewClient() { - @Override - public void onPageFinished(WebView view, String url) { - mWebView.setVisibility(View.VISIBLE); - mLoadingView.setVisibility(View.GONE); - } - }; + @Override + public void onPageFinished(WebView view, String url) { + mWebView.setVisibility(View.VISIBLE); + mLoadingView.setVisibility(View.GONE); + } + }; - /** - * Initialize WebView. - * - * Ignore lint javascript warning as js is loaded only from our known, local service. - */ - @Override - @SuppressLint("SetJavaScriptEnabled") - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + /** + * Initialize WebView. + *

+ * Ignore lint javascript warning as js is loaded only from our known, local service. + */ + @Override + @SuppressLint("SetJavaScriptEnabled") + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - setContentView(R.layout.web_gui_activity); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + setContentView(R.layout.web_gui_activity); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); - mLoadingView = findViewById(R.id.loading); - ProgressBar pb = (ProgressBar) mLoadingView.findViewById(R.id.progress); - pb.setIndeterminate(true); + mLoadingView = findViewById(R.id.loading); + ProgressBar pb = (ProgressBar) mLoadingView.findViewById(R.id.progress); + pb.setIndeterminate(true); - mWebView = (WebView) findViewById(R.id.webview); - mWebView.getSettings().setJavaScriptEnabled(true); - mWebView.setWebViewClient(mWebViewClient); - } + mWebView = (WebView) findViewById(R.id.webview); + mWebView.getSettings().setJavaScriptEnabled(true); + mWebView.setWebViewClient(mWebViewClient); + } - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - super.onServiceConnected(componentName, iBinder); - getService().registerOnWebGuiAvailableListener(WebGuiActivity.this); - } + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + super.onServiceConnected(componentName, iBinder); + getService().registerOnWebGuiAvailableListener(WebGuiActivity.this); + } + + /** + * Loads and shows WebView, hides loading view. + */ + @Override + public void onWebGuiAvailable() { + mWebView.loadUrl(getApi().getUrl()); + } - /** - * Loads and shows WebView, hides loading view. - */ - @Override - public void onWebGuiAvailable() { - mWebView.loadUrl(getApi().getUrl()); - } - } diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/LocalNodeInfoFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/LocalNodeInfoFragment.java index d6e5744f..ecdb5e71 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/LocalNodeInfoFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/LocalNodeInfoFragment.java @@ -26,152 +26,153 @@ import java.util.TimerTask; * Displays information about the local node. */ public class LocalNodeInfoFragment extends Fragment - implements RestApi.OnReceiveSystemInfoListener, RestApi.OnReceiveConnectionsListener { + implements RestApi.OnReceiveSystemInfoListener, RestApi.OnReceiveConnectionsListener { - private TextView mNodeId; + private TextView mNodeId; - private TextView mCpuUsage; + private TextView mCpuUsage; - private TextView mRamUsage; + private TextView mRamUsage; - private TextView mDownload; + private TextView mDownload; - private TextView mUpload; + private TextView mUpload; - private TextView mAnnounceServer; + private TextView mAnnounceServer; - private Timer mTimer; + private Timer mTimer; - private MainActivity mActivity; + private MainActivity mActivity; - /** - * Starts polling for status when opened, stops when closed. - */ - public class Toggle extends ActionBarDrawerToggle { - public Toggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes) { - super(activity, drawerLayout, drawerImageRes, R.string.app_name, R.string.system_info); - } + /** + * Starts polling for status when opened, stops when closed. + */ + public class Toggle extends ActionBarDrawerToggle { + public Toggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes) { + super(activity, drawerLayout, drawerImageRes, R.string.app_name, R.string.system_info); + } - @Override - public void onDrawerClosed(View view) { - super.onDrawerClosed(view); - mTimer.cancel(); - mTimer = null; - mActivity.getSupportActionBar().setTitle(R.string.app_name); - mActivity.supportInvalidateOptionsMenu(); - } + @Override + public void onDrawerClosed(View view) { + super.onDrawerClosed(view); + mTimer.cancel(); + mTimer = null; + mActivity.getSupportActionBar().setTitle(R.string.app_name); + mActivity.supportInvalidateOptionsMenu(); + } - @Override - public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - LocalNodeInfoFragment.this.onDrawerOpened(); - } - }; + @Override + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + LocalNodeInfoFragment.this.onDrawerOpened(); + } + } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.local_node_info_fragment, container, false); - mNodeId = (TextView) view.findViewById(R.id.node_id); - mCpuUsage = (TextView) view.findViewById(R.id.cpu_usage); - mRamUsage = (TextView) view.findViewById(R.id.ram_usage); - mDownload = (TextView) view.findViewById(R.id.download); - mUpload = (TextView) view.findViewById(R.id.upload); - mAnnounceServer = (TextView) view.findViewById(R.id.announce_server); + ; - return view; - } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.local_node_info_fragment, container, false); + mNodeId = (TextView) view.findViewById(R.id.node_id); + mCpuUsage = (TextView) view.findViewById(R.id.cpu_usage); + mRamUsage = (TextView) view.findViewById(R.id.ram_usage); + mDownload = (TextView) view.findViewById(R.id.download); + mUpload = (TextView) view.findViewById(R.id.upload); + mAnnounceServer = (TextView) view.findViewById(R.id.announce_server); - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - mActivity = (MainActivity) getActivity(); + return view; + } - if (savedInstanceState != null && savedInstanceState.getBoolean("active")) { - onDrawerOpened(); - } - } + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mActivity = (MainActivity) getActivity(); - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean("active", mTimer != null); - } + if (savedInstanceState != null && savedInstanceState.getBoolean("active")) { + onDrawerOpened(); + } + } - private void onDrawerOpened() { - // FIXME: never called - mTimer = new Timer(); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - updateGui(); - } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean("active", mTimer != null); + } - }, 0, SyncthingService.GUI_UPDATE_INTERVAL); - mActivity.getSupportActionBar().setTitle(R.string.system_info); - mActivity.supportInvalidateOptionsMenu(); - } + private void onDrawerOpened() { + // FIXME: never called + mTimer = new Timer(); + mTimer.schedule(new TimerTask() { + @Override + public void run() { + updateGui(); + } - /** - * Invokes status callbacks. - */ - private void updateGui() { - if (mActivity.getApi() != null) { - mActivity.getApi().getSystemInfo(this); - mActivity.getApi().getConnections(this); - } - } + }, 0, SyncthingService.GUI_UPDATE_INTERVAL); + mActivity.getSupportActionBar().setTitle(R.string.system_info); + mActivity.supportInvalidateOptionsMenu(); + } - /** - * Populates views with status received via {@link RestApi#getSystemInfo}. - */ - @Override - public void onReceiveSystemInfo(RestApi.SystemInfo info) { - if (getActivity() == null) - return; + /** + * Invokes status callbacks. + */ + private void updateGui() { + if (mActivity.getApi() != null) { + mActivity.getApi().getSystemInfo(this); + mActivity.getApi().getConnections(this); + } + } - mNodeId.setText(info.myID); - mNodeId.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - mActivity.getApi().copyNodeId(mNodeId.getText().toString()); - view.performClick(); - return true; - } - }); - mCpuUsage.setText(new DecimalFormat("0.00").format(info.cpuPercent) + "%"); - mRamUsage.setText(RestApi.readableFileSize(mActivity, info.sys)); - if (info.extAnnounceOK) { - mAnnounceServer.setText("Online"); - mAnnounceServer.setTextColor(getResources().getColor(R.color.text_green)); - } - else { - mAnnounceServer.setText("Offline"); - mAnnounceServer.setTextColor(getResources().getColor(R.color.text_red)); - } - } + /** + * Populates views with status received via {@link RestApi#getSystemInfo}. + */ + @Override + public void onReceiveSystemInfo(RestApi.SystemInfo info) { + if (getActivity() == null) + return; - /** - * Populates views with status received via {@link RestApi#getConnections}. - */ - @Override - public void onReceiveConnections(Map connections) { - RestApi.Connection c = connections.get(RestApi.LOCAL_NODE_CONNECTIONS); - mDownload.setText(RestApi.readableTransferRate(mActivity, c.InBits)); - mUpload.setText(RestApi.readableTransferRate(mActivity, c.OutBits)); - } + mNodeId.setText(info.myID); + mNodeId.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + mActivity.getApi().copyNodeId(mNodeId.getText().toString()); + view.performClick(); + return true; + } + }); + mCpuUsage.setText(new DecimalFormat("0.00").format(info.cpuPercent) + "%"); + mRamUsage.setText(RestApi.readableFileSize(mActivity, info.sys)); + if (info.extAnnounceOK) { + mAnnounceServer.setText("Online"); + mAnnounceServer.setTextColor(getResources().getColor(R.color.text_green)); + } else { + mAnnounceServer.setText("Offline"); + mAnnounceServer.setTextColor(getResources().getColor(R.color.text_red)); + } + } - /** - * Shares the local node ID when "share" is clicked. - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.share_node_id: - RestApi.shareNodeId(getActivity(), mNodeId.getText().toString()); - return true; - default: - return super.onOptionsItemSelected(item); - } - } + /** + * Populates views with status received via {@link RestApi#getConnections}. + */ + @Override + public void onReceiveConnections(Map connections) { + RestApi.Connection c = connections.get(RestApi.LOCAL_NODE_CONNECTIONS); + mDownload.setText(RestApi.readableTransferRate(mActivity, c.InBits)); + mUpload.setText(RestApi.readableTransferRate(mActivity, c.OutBits)); + } + + /** + * Shares the local node ID when "share" is clicked. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.share_node_id: + RestApi.shareNodeId(getActivity(), mNodeId.getText().toString()); + return true; + default: + return super.onOptionsItemSelected(item); + } + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/NodeSettingsFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/NodeSettingsFragment.java index 9e0a8a2f..89443fed 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/NodeSettingsFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/NodeSettingsFragment.java @@ -1,6 +1,5 @@ package com.nutomic.syncthingandroid.fragments; -import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.ActivityNotFoundException; @@ -29,259 +28,253 @@ import java.util.Map; * Shows node details and allows changing them. */ public class NodeSettingsFragment extends PreferenceFragment implements - SyncthingActivity.OnServiceConnectedListener, Preference.OnPreferenceChangeListener, - Preference.OnPreferenceClickListener, RestApi.OnReceiveConnectionsListener, - SyncthingService.OnApiChangeListener, RestApi.OnNodeIdNormalizedListener { + SyncthingActivity.OnServiceConnectedListener, Preference.OnPreferenceChangeListener, + Preference.OnPreferenceClickListener, RestApi.OnReceiveConnectionsListener, + SyncthingService.OnApiChangeListener, RestApi.OnNodeIdNormalizedListener { - public static final String EXTRA_NODE_ID = "node_id"; + public static final String EXTRA_NODE_ID = "node_id"; - private static final int SCAN_QR_REQUEST_CODE = 235; + private static final int SCAN_QR_REQUEST_CODE = 235; - private SyncthingService mSyncthingService; + private SyncthingService mSyncthingService; - private RestApi.Node mNode; + private RestApi.Node mNode; - private Preference mNodeId; + private Preference mNodeId; - private EditTextPreference mName; + private EditTextPreference mName; - private EditTextPreference mAddresses; + private EditTextPreference mAddresses; - private Preference mVersion; + private Preference mVersion; - private Preference mCurrentAddress; + private Preference mCurrentAddress; - private boolean mIsCreate; + private boolean mIsCreate; - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); + ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); - mIsCreate = ((SettingsActivity) getActivity()).getIsCreate(); - setHasOptionsMenu(true); + mIsCreate = ((SettingsActivity) getActivity()).getIsCreate(); + setHasOptionsMenu(true); - if (mIsCreate) { - addPreferencesFromResource(R.xml.node_settings_create); - } - else { - addPreferencesFromResource(R.xml.node_settings_edit); - } + if (mIsCreate) { + addPreferencesFromResource(R.xml.node_settings_create); + } else { + addPreferencesFromResource(R.xml.node_settings_edit); + } - mNodeId = findPreference("node_id"); - mNodeId.setOnPreferenceChangeListener(this); - mName = (EditTextPreference) findPreference("name"); - mName.setOnPreferenceChangeListener(this); - mAddresses = (EditTextPreference) findPreference("addresses"); - mAddresses.setOnPreferenceChangeListener(this); - if (!mIsCreate) { - mVersion = findPreference("version"); - mVersion.setSummary("?"); - mCurrentAddress = findPreference("current_address"); - mCurrentAddress.setSummary("?"); - } - } + mNodeId = findPreference("node_id"); + mNodeId.setOnPreferenceChangeListener(this); + mName = (EditTextPreference) findPreference("name"); + mName.setOnPreferenceChangeListener(this); + mAddresses = (EditTextPreference) findPreference("addresses"); + mAddresses.setOnPreferenceChangeListener(this); + if (!mIsCreate) { + mVersion = findPreference("version"); + mVersion.setSummary("?"); + mCurrentAddress = findPreference("current_address"); + mCurrentAddress.setSummary("?"); + } + } - @Override - public void onServiceConnected() { - mSyncthingService = ((SyncthingActivity) getActivity()).getService(); - mSyncthingService.registerOnApiChangeListener(this); - } + @Override + public void onServiceConnected() { + mSyncthingService = ((SyncthingActivity) getActivity()).getService(); + mSyncthingService.registerOnApiChangeListener(this); + } - @Override - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) { - getActivity().finish(); - return; - } + @Override + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE) { + getActivity().finish(); + return; + } - if (getActivity() == null || getActivity().isFinishing()) - return; + if (getActivity() == null || getActivity().isFinishing()) + return; - 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 { - 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( - getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) { - mNode = nodes.get(i); - break; - } - } - mNodeId.setOnPreferenceClickListener(this); - } - mSyncthingService.getApi().getConnections(NodeSettingsFragment.this); + 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 { + 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( + getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) { + mNode = nodes.get(i); + break; + } + } + mNodeId.setOnPreferenceClickListener(this); + } + mSyncthingService.getApi().getConnections(NodeSettingsFragment.this); - mNodeId.setSummary(mNode.NodeID); - mName.setText((mNode.Name)); - mName.setSummary(mNode.Name); - mAddresses.setText(mNode.Addresses); - mAddresses.setSummary(mNode.Addresses); - } + mNodeId.setSummary(mNode.NodeID); + mName.setText((mNode.Name)); + mName.setSummary(mNode.Name); + mAddresses.setText(mNode.Addresses); + mAddresses.setSummary(mNode.Addresses); + } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.node_settings, menu); - } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.node_settings, menu); + } - @Override - public void onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.create).setVisible(mIsCreate); - menu.findItem(R.id.share_node_id).setVisible(!mIsCreate); - menu.findItem(R.id.delete).setVisible(!mIsCreate); - } + @Override + public void onPrepareOptionsMenu(Menu menu) { + menu.findItem(R.id.create).setVisible(mIsCreate); + menu.findItem(R.id.share_node_id).setVisible(!mIsCreate); + menu.findItem(R.id.delete).setVisible(!mIsCreate); + } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.create: - if (mNode.NodeID.equals("")) { - Toast.makeText(getActivity(), R.string.node_id_required, Toast.LENGTH_LONG) - .show(); - return true; - } - if (mNode.Name.equals("")) { - 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(getActivity(), mNode.NodeID); - return true; - case R.id.delete: - 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, getActivity()); - getActivity().finish(); - } - }) - .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 onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.create: + if (mNode.NodeID.equals("")) { + Toast.makeText(getActivity(), R.string.node_id_required, Toast.LENGTH_LONG) + .show(); + return true; + } + if (mNode.Name.equals("")) { + 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(getActivity(), mNode.NodeID); + return true; + case R.id.delete: + 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, getActivity()); + getActivity().finish(); + } + }) + .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); - } + @Override + public boolean onPreferenceChange(Preference preference, Object o) { + if (preference instanceof EditTextPreference) { + EditTextPreference pref = (EditTextPreference) preference; + pref.setSummary((String) o); + } - if (preference.equals(mNodeId)) { - mNode.NodeID = (String) o; - nodeUpdated(); - return true; - } - else if (preference.equals(mName)) { - mNode.Name = (String) o; - nodeUpdated(); - return true; - } - else if (preference.equals(mAddresses)) { - mNode.Addresses = (String) o; - nodeUpdated(); - return true; - } - return false; - } + if (preference.equals(mNodeId)) { + mNode.NodeID = (String) o; + nodeUpdated(); + return true; + } else if (preference.equals(mName)) { + mNode.Name = (String) o; + nodeUpdated(); + return true; + } else if (preference.equals(mAddresses)) { + mNode.Addresses = (String) o; + nodeUpdated(); + return true; + } + return false; + } - @Override - public boolean onPreferenceClick(Preference preference) { - if (preference.equals(mNodeId)) { - mSyncthingService.getApi().copyNodeId(mNode.NodeID); - return true; - } - return false; - } + @Override + public boolean onPreferenceClick(Preference preference) { + if (preference.equals(mNodeId)) { + mSyncthingService.getApi().copyNodeId(mNode.NodeID); + return true; + } + return false; + } - /** - * Sets version and current address of the node. - * - * NOTE: This is only called once on startup, should be called more often to properly display - * version/address changes. - */ - @Override - public void onReceiveConnections(Map connections) { - if (connections.containsKey(mNode.NodeID)) { - mVersion.setSummary(connections.get(mNode.NodeID).ClientVersion); - mCurrentAddress.setSummary(connections.get(mNode.NodeID).Address); - } - } + /** + * Sets version and current address of the node. + *

+ * NOTE: This is only called once on startup, should be called more often to properly display + * version/address changes. + */ + @Override + public void onReceiveConnections(Map connections) { + if (connections.containsKey(mNode.NodeID)) { + mVersion.setSummary(connections.get(mNode.NodeID).ClientVersion); + mCurrentAddress.setSummary(connections.get(mNode.NodeID).Address); + } + } - /** - * Sends the updated node info if in edit mode. - */ - private void nodeUpdated() { - if (!mIsCreate) { - mSyncthingService.getApi().editNode(mNode, this); - } - } + /** + * Sends the updated node info if in edit mode. + */ + private void nodeUpdated() { + if (!mIsCreate) { + mSyncthingService.getApi().editNode(mNode, this); + } + } - /** - * Sends QR code scanning intent when clicking the qrcode icon. - */ - public void onClick(View view) { - Intent intentScan = new Intent("com.google.zxing.client.android.SCAN"); - intentScan.addCategory(Intent.CATEGORY_DEFAULT); - intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - try { - startActivityForResult(intentScan, SCAN_QR_REQUEST_CODE); - } - catch (ActivityNotFoundException e) { - Toast.makeText(getActivity(), R.string.no_qr_scanner_installed, - Toast.LENGTH_LONG).show(); - } - } + /** + * Sends QR code scanning intent when clicking the qrcode icon. + */ + public void onClick(View view) { + Intent intentScan = new Intent("com.google.zxing.client.android.SCAN"); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + try { + startActivityForResult(intentScan, SCAN_QR_REQUEST_CODE); + } catch (ActivityNotFoundException e) { + Toast.makeText(getActivity(), R.string.no_qr_scanner_installed, + Toast.LENGTH_LONG).show(); + } + } - /** - * Receives value of scanned QR code and sets it as node ID. - */ - @Override - 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); - mNodeId.setSummary(mNode.NodeID); - } - } + /** + * Receives value of scanned QR code and sets it as node ID. + */ + @Override + 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); + mNodeId.setSummary(mNode.NodeID); + } + } - /** - * Callback for {@link RestApi#editNode(RestApi.Node, RestApi.OnNodeIdNormalizedListener)}. - * Displays an error message if present, or finishes the Activity on success in edit mode. - * - * @param normalizedId The normalized node ID, or null on error. - * @param error An error message, or null on success. - */ - @Override - public void onNodeIdNormalized(String normalizedId, String error) { - if (error != null) { - Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show(); - } - else if (mIsCreate) { - getActivity().finish(); - } - } + /** + * Callback for {@link RestApi#editNode(RestApi.Node, RestApi.OnNodeIdNormalizedListener)}. + * Displays an error message if present, or finishes the Activity on success in edit mode. + * + * @param normalizedId The normalized node ID, or null on error. + * @param error An error message, or null on success. + */ + @Override + public void onNodeIdNormalized(String normalizedId, String error) { + if (error != null) { + Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show(); + } else if (mIsCreate) { + getActivity().finish(); + } + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/NodesFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/NodesFragment.java index 5106025a..653f8b13 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/NodesFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/NodesFragment.java @@ -21,80 +21,79 @@ import java.util.TimerTask; * Displays a list of all existing nodes. */ public class NodesFragment extends ListFragment implements SyncthingService.OnApiChangeListener, - ListView.OnItemClickListener { + ListView.OnItemClickListener { - private NodesAdapter mAdapter; + private NodesAdapter mAdapter; - private Timer mTimer; + private Timer mTimer; - @Override - public void onResume() { - super.onResume(); - setListShown(true); - } + @Override + public void onResume() { + super.onResume(); + setListShown(true); + } - @Override - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) - return; + @Override + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE) + return; - initAdapter(); - } + initAdapter(); + } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); - initAdapter(); - } + initAdapter(); + } - private void initAdapter() { - SyncthingActivity activity = (SyncthingActivity) getActivity(); - if (activity == null || activity.getApi() == null) - return; + private void initAdapter() { + SyncthingActivity activity = (SyncthingActivity) getActivity(); + if (activity == null || activity.getApi() == null) + return; - mAdapter = new NodesAdapter(activity); - mAdapter.add(activity.getApi().getNodes()); - setListAdapter(mAdapter); - setEmptyText(getString(R.string.nodes_list_empty)); - getListView().setOnItemClickListener(this); - } + mAdapter = new NodesAdapter(activity); + mAdapter.add(activity.getApi().getNodes()); + setListAdapter(mAdapter); + setEmptyText(getString(R.string.nodes_list_empty)); + getListView().setOnItemClickListener(this); + } - private void updateList() { - if (mAdapter == null || getView() == null) - return; + private void updateList() { + if (mAdapter == null || getView() == null) + return; - MainActivity activity = (MainActivity) getActivity(); - mAdapter.updateConnections(activity.getApi(), getListView()); - } + MainActivity activity = (MainActivity) getActivity(); + mAdapter.updateConnections(activity.getApi(), getListView()); + } - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); - if (isVisibleToUser) { - mTimer = new Timer(); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - updateList(); - } + if (isVisibleToUser) { + mTimer = new Timer(); + mTimer.schedule(new TimerTask() { + @Override + public void run() { + updateList(); + } - }, 0, SyncthingService.GUI_UPDATE_INTERVAL); - } - else if (mTimer != null) { - mTimer.cancel(); - mTimer = null; - } - } + }, 0, SyncthingService.GUI_UPDATE_INTERVAL); + } else if (mTimer != null) { + mTimer.cancel(); + mTimer = null; + } + } - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - 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); - } + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + 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/fragments/RepoSettingsFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/RepoSettingsFragment.java index bf20f6c2..c0821dd5 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/RepoSettingsFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/RepoSettingsFragment.java @@ -31,275 +31,265 @@ import java.util.List; * Shows repo details and allows changing them. */ public class RepoSettingsFragment extends PreferenceFragment - implements SyncthingActivity.OnServiceConnectedListener, - Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener, - SyncthingService.OnApiChangeListener { + implements SyncthingActivity.OnServiceConnectedListener, + Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener, + SyncthingService.OnApiChangeListener { - private static final int DIRECTORY_REQUEST_CODE = 234; + private static final int DIRECTORY_REQUEST_CODE = 234; - /** - * The ID of the repo to be edited. To be used with {@link com.nutomic.syncthingandroid.activities.SettingsActivity#EXTRA_IS_CREATE} - * set to false. - */ - public static final String EXTRA_REPO_ID = "repo_id"; + /** + * The ID of the repo to be edited. To be used with {@link com.nutomic.syncthingandroid.activities.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"; + private static final String KEY_NODE_SHARED = "node_shared"; - private SyncthingService mSyncthingService; + private SyncthingService mSyncthingService; - private RestApi.Repo mRepo; + private RestApi.Repo mRepo; - private EditTextPreference mRepoId; + private EditTextPreference mRepoId; - private Preference mDirectory; + private Preference mDirectory; - private CheckBoxPreference mRepoMaster; + private CheckBoxPreference mRepoMaster; - private PreferenceScreen mNodes; + private PreferenceScreen mNodes; - private CheckBoxPreference mVersioning; + private CheckBoxPreference mVersioning; - private EditTextPreference mVersioningKeep; + private EditTextPreference mVersioningKeep; - private boolean mIsCreate; + private boolean mIsCreate; - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - SettingsActivity activity = (SettingsActivity) getActivity(); - activity.registerOnServiceConnectedListener(this); - mIsCreate = activity.getIsCreate(); - setHasOptionsMenu(true); + SettingsActivity activity = (SettingsActivity) getActivity(); + activity.registerOnServiceConnectedListener(this); + mIsCreate = activity.getIsCreate(); + setHasOptionsMenu(true); - if (mIsCreate) { - addPreferencesFromResource(R.xml.repo_settings_create); - } - else { - addPreferencesFromResource(R.xml.repo_settings_edit); - } + if (mIsCreate) { + addPreferencesFromResource(R.xml.repo_settings_create); + } else { + addPreferencesFromResource(R.xml.repo_settings_edit); + } - mRepoId = (EditTextPreference) findPreference("repo_id"); - mRepoId.setOnPreferenceChangeListener(this); - mDirectory = findPreference("directory"); - mDirectory.setOnPreferenceClickListener(this); - mRepoMaster = (CheckBoxPreference) findPreference("repo_master"); - mRepoMaster.setOnPreferenceChangeListener(this); - mNodes = (PreferenceScreen) findPreference("nodes"); - mNodes.setOnPreferenceClickListener(this); - mVersioning = (CheckBoxPreference) findPreference("versioning"); - mVersioning.setOnPreferenceChangeListener(this); - mVersioningKeep = (EditTextPreference) findPreference("versioning_keep"); - mVersioningKeep.setOnPreferenceChangeListener(this); - } + mRepoId = (EditTextPreference) findPreference("repo_id"); + mRepoId.setOnPreferenceChangeListener(this); + mDirectory = findPreference("directory"); + mDirectory.setOnPreferenceClickListener(this); + mRepoMaster = (CheckBoxPreference) findPreference("repo_master"); + mRepoMaster.setOnPreferenceChangeListener(this); + mNodes = (PreferenceScreen) findPreference("nodes"); + mNodes.setOnPreferenceClickListener(this); + mVersioning = (CheckBoxPreference) findPreference("versioning"); + mVersioning.setOnPreferenceChangeListener(this); + mVersioningKeep = (EditTextPreference) findPreference("versioning_keep"); + mVersioningKeep.setOnPreferenceChangeListener(this); + } - @Override - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) { - getActivity().finish(); - return; - } + @Override + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE) { + getActivity().finish(); + return; + } - if (getActivity() == null || getActivity().isFinishing()) - return; + if (getActivity() == null || getActivity().isFinishing()) + return; - 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 { - 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( - getActivity().getIntent().getStringExtra(EXTRA_REPO_ID))) { - mRepo = repos.get(i); - break; - } - } - } + 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 { + 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( + getActivity().getIntent().getStringExtra(EXTRA_REPO_ID))) { + mRepo = repos.get(i); + break; + } + } + } - mRepoId.setText(mRepo.ID); - mRepoId.setSummary(mRepo.ID); - mDirectory.setSummary(mRepo.Directory); - mRepoMaster.setChecked(mRepo.ReadOnly); - List nodesList = mSyncthingService.getApi().getNodes(); - for (RestApi.Node n : nodesList) { - ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n); - cbp.setTitle(n.Name); - cbp.setKey(KEY_NODE_SHARED); - cbp.setOnPreferenceChangeListener(RepoSettingsFragment.this); - cbp.setChecked(false); - for (RestApi.Node n2 : mRepo.Nodes) { - if (n2.NodeID.equals(n.NodeID)) { - cbp.setChecked(true); - } - } - mNodes.addPreference(cbp); - } - mVersioning.setChecked(mRepo.Versioning instanceof RestApi.SimpleVersioning); - if (mVersioning.isChecked()) { - mVersioningKeep.setText(mRepo.Versioning.getParams().get("keep")); - mVersioningKeep.setSummary(mRepo.Versioning.getParams().get("keep")); - mVersioningKeep.setEnabled(true); - } - else { - mVersioningKeep.setEnabled(false); - } - } + mRepoId.setText(mRepo.ID); + mRepoId.setSummary(mRepo.ID); + mDirectory.setSummary(mRepo.Directory); + mRepoMaster.setChecked(mRepo.ReadOnly); + List nodesList = mSyncthingService.getApi().getNodes(); + for (RestApi.Node n : nodesList) { + ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n); + cbp.setTitle(n.Name); + cbp.setKey(KEY_NODE_SHARED); + cbp.setOnPreferenceChangeListener(RepoSettingsFragment.this); + cbp.setChecked(false); + for (RestApi.Node n2 : mRepo.Nodes) { + if (n2.NodeID.equals(n.NodeID)) { + cbp.setChecked(true); + } + } + mNodes.addPreference(cbp); + } + mVersioning.setChecked(mRepo.Versioning instanceof RestApi.SimpleVersioning); + if (mVersioning.isChecked()) { + mVersioningKeep.setText(mRepo.Versioning.getParams().get("keep")); + mVersioningKeep.setSummary(mRepo.Versioning.getParams().get("keep")); + mVersioningKeep.setEnabled(true); + } else { + mVersioningKeep.setEnabled(false); + } + } - @Override - public void onServiceConnected() { - mSyncthingService = ((SyncthingActivity) getActivity()).getService(); - mSyncthingService.registerOnApiChangeListener(this); - } + @Override + public void onServiceConnected() { + mSyncthingService = ((SyncthingActivity) getActivity()).getService(); + mSyncthingService.registerOnApiChangeListener(this); + } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.repo_settings, menu); - } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.repo_settings, menu); + } - @Override - public void onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.create).setVisible(mIsCreate); - menu.findItem(R.id.delete).setVisible(!mIsCreate); - } + @Override + public void onPrepareOptionsMenu(Menu menu) { + menu.findItem(R.id.create).setVisible(mIsCreate); + menu.findItem(R.id.delete).setVisible(!mIsCreate); + } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.create: - if (mRepo.ID.equals("")) { - Toast.makeText(getActivity(), R.string.repo_id_required, Toast.LENGTH_LONG) - .show(); - return true; - } - if (mRepo.Directory.equals("")) { - Toast.makeText(getActivity(), R.string.repo_path_required, Toast.LENGTH_LONG) - .show(); - return true; - } - mSyncthingService.getApi().editRepo(mRepo, true, getActivity()); - getActivity().finish(); - return true; - case R.id.delete: - 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, getActivity()); - getActivity().finish(); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); - return true; - case android.R.id.home: - getActivity().finish(); - return true; - } - return super.onOptionsItemSelected(item); - } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.create: + if (mRepo.ID.equals("")) { + Toast.makeText(getActivity(), R.string.repo_id_required, Toast.LENGTH_LONG) + .show(); + return true; + } + if (mRepo.Directory.equals("")) { + Toast.makeText(getActivity(), R.string.repo_path_required, Toast.LENGTH_LONG) + .show(); + return true; + } + mSyncthingService.getApi().editRepo(mRepo, true, getActivity()); + getActivity().finish(); + return true; + case R.id.delete: + 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, getActivity()); + getActivity().finish(); + } + }) + .setNegativeButton(android.R.string.no, null) + .show(); + return true; + case android.R.id.home: + getActivity().finish(); + return true; + } + return super.onOptionsItemSelected(item); + } - @Override - public boolean onPreferenceChange(Preference preference, Object o) { - if (preference instanceof EditTextPreference) { - EditTextPreference pref = (EditTextPreference) preference; - pref.setSummary((String) o); - } + @Override + public boolean onPreferenceChange(Preference preference, Object o) { + if (preference instanceof EditTextPreference) { + EditTextPreference pref = (EditTextPreference) preference; + pref.setSummary((String) o); + } - if (preference.equals(mRepoId)) { - mRepo.ID = (String) o; - repoUpdated(); - return true; - } - else if (preference.equals(mDirectory)) { - mRepo.Directory = (String) o; - repoUpdated(); - return true; - } - else if (preference.equals(mRepoMaster)) { - mRepo.ReadOnly = (Boolean) o; - repoUpdated(); - return true; - } - else if (preference.getKey().equals(KEY_NODE_SHARED)) { - ExtendedCheckBoxPreference pref = (ExtendedCheckBoxPreference) preference; - RestApi.Node node = (RestApi.Node) pref.getObject(); - if ((Boolean) o) { - mRepo.Nodes.add(node); - } - else { - for (RestApi.Node n : mRepo.Nodes) { - if (n.NodeID.equals(node.NodeID)) { - mRepo.Nodes.remove(n); - } - } - } - repoUpdated(); - return true; - } - else if (preference.equals(mVersioning)) { - mVersioningKeep.setEnabled((Boolean) o); - if ((Boolean) o) { - RestApi.SimpleVersioning v = new RestApi.SimpleVersioning(); - mRepo.Versioning = v; - v.setParams(5); - mVersioningKeep.setText("5"); - mVersioningKeep.setSummary("5"); - } - else { - mRepo.Versioning = new RestApi.Versioning(); - } - repoUpdated(); - return true; - } - else if (preference.equals(mVersioningKeep)) { - ((RestApi.SimpleVersioning) mRepo.Versioning) - .setParams(Integer.parseInt((String) o)); - repoUpdated(); - return true; - } + if (preference.equals(mRepoId)) { + mRepo.ID = (String) o; + repoUpdated(); + return true; + } else if (preference.equals(mDirectory)) { + mRepo.Directory = (String) o; + repoUpdated(); + return true; + } else if (preference.equals(mRepoMaster)) { + mRepo.ReadOnly = (Boolean) o; + repoUpdated(); + return true; + } else if (preference.getKey().equals(KEY_NODE_SHARED)) { + ExtendedCheckBoxPreference pref = (ExtendedCheckBoxPreference) preference; + RestApi.Node node = (RestApi.Node) pref.getObject(); + if ((Boolean) o) { + mRepo.Nodes.add(node); + } else { + for (RestApi.Node n : mRepo.Nodes) { + if (n.NodeID.equals(node.NodeID)) { + mRepo.Nodes.remove(n); + } + } + } + repoUpdated(); + return true; + } else if (preference.equals(mVersioning)) { + mVersioningKeep.setEnabled((Boolean) o); + if ((Boolean) o) { + RestApi.SimpleVersioning v = new RestApi.SimpleVersioning(); + mRepo.Versioning = v; + v.setParams(5); + mVersioningKeep.setText("5"); + mVersioningKeep.setSummary("5"); + } else { + mRepo.Versioning = new RestApi.Versioning(); + } + repoUpdated(); + return true; + } else if (preference.equals(mVersioningKeep)) { + ((RestApi.SimpleVersioning) mRepo.Versioning) + .setParams(Integer.parseInt((String) o)); + repoUpdated(); + return true; + } - return false; - } + return false; + } - @Override - public boolean onPreferenceClick(Preference preference) { - if (preference.equals(mDirectory)) { - Intent intent = new Intent(getActivity(), FolderPickerActivity.class) - .putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY, - (mRepo.Directory.length() != 0) - ? mRepo.Directory - : Environment.getExternalStorageDirectory().getAbsolutePath()); - startActivityForResult(intent, DIRECTORY_REQUEST_CODE); - } - else if (preference.equals(mNodes) && mSyncthingService.getApi().getNodes().isEmpty()) { - Toast.makeText(getActivity(), R.string.no_nodes, Toast.LENGTH_SHORT) - .show(); - } - return false; - } + @Override + public boolean onPreferenceClick(Preference preference) { + if (preference.equals(mDirectory)) { + Intent intent = new Intent(getActivity(), FolderPickerActivity.class) + .putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY, + (mRepo.Directory.length() != 0) + ? mRepo.Directory + : Environment.getExternalStorageDirectory().getAbsolutePath() + ); + startActivityForResult(intent, DIRECTORY_REQUEST_CODE); + } else if (preference.equals(mNodes) && mSyncthingService.getApi().getNodes().isEmpty()) { + Toast.makeText(getActivity(), R.string.no_nodes, Toast.LENGTH_SHORT) + .show(); + } + return false; + } - @Override - 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); - repoUpdated(); - } - } + @Override + 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); + repoUpdated(); + } + } - private void repoUpdated() { - if (!mIsCreate) { - mSyncthingService.getApi().editRepo(mRepo, false, getActivity()); - } - } + private void repoUpdated() { + if (!mIsCreate) { + mSyncthingService.getApi().editRepo(mRepo, false, getActivity()); + } + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/ReposFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/ReposFragment.java index 2d974fb9..099c64f7 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/ReposFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/ReposFragment.java @@ -19,80 +19,79 @@ import java.util.TimerTask; * Displays a list of all existing repositories. */ public class ReposFragment extends ListFragment implements SyncthingService.OnApiChangeListener, - AdapterView.OnItemClickListener { + AdapterView.OnItemClickListener { - private ReposAdapter mAdapter; + private ReposAdapter mAdapter; - private Timer mTimer; + private Timer mTimer; - @Override - public void onResume() { - super.onResume(); - setListShown(true); - } + @Override + public void onResume() { + super.onResume(); + setListShown(true); + } - @Override - public void onApiChange(SyncthingService.State currentState) { - if (currentState != SyncthingService.State.ACTIVE) - return; + @Override + public void onApiChange(SyncthingService.State currentState) { + if (currentState != SyncthingService.State.ACTIVE) + return; - initAdapter(); - } + initAdapter(); + } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); - initAdapter(); - } + initAdapter(); + } - private void initAdapter() { - MainActivity activity = (MainActivity) getActivity(); - if (activity == null || activity.getApi() == null) - return; + private void initAdapter() { + MainActivity activity = (MainActivity) getActivity(); + if (activity == null || activity.getApi() == null) + return; - mAdapter = new ReposAdapter(activity); - mAdapter.add(activity.getApi().getRepos()); - setListAdapter(mAdapter); - setEmptyText(getString(R.string.repositories_list_empty)); - getListView().setOnItemClickListener(this); - } + mAdapter = new ReposAdapter(activity); + mAdapter.add(activity.getApi().getRepos()); + setListAdapter(mAdapter); + setEmptyText(getString(R.string.repositories_list_empty)); + getListView().setOnItemClickListener(this); + } - private void updateList() { - if (mAdapter == null || getView() == null) - return; + private void updateList() { + if (mAdapter == null || getView() == null) + return; - MainActivity activity = (MainActivity) getActivity(); - mAdapter.updateModel(activity.getApi(), getListView()); - } + MainActivity activity = (MainActivity) getActivity(); + mAdapter.updateModel(activity.getApi(), getListView()); + } - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); - if (isVisibleToUser) { - mTimer = new Timer(); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - updateList(); - } + if (isVisibleToUser) { + mTimer = new Timer(); + mTimer.schedule(new TimerTask() { + @Override + public void run() { + updateList(); + } - }, 0, SyncthingService.GUI_UPDATE_INTERVAL); - } - else if (mTimer != null) { - mTimer.cancel(); - mTimer = null; - } - } + }, 0, SyncthingService.GUI_UPDATE_INTERVAL); + } else if (mTimer != null) { + mTimer.cancel(); + mTimer = null; + } + } - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - 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); - } + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + 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/fragments/SettingsFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java index 39eb866f..ad2ba7c2 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java @@ -16,139 +16,136 @@ import com.nutomic.syncthingandroid.syncthing.RestApi; import com.nutomic.syncthingandroid.syncthing.SyncthingService; public class SettingsFragment extends PreferenceFragment - implements SyncthingActivity.OnServiceConnectedListener, - SyncthingService.OnApiChangeListener, Preference.OnPreferenceChangeListener { + implements SyncthingActivity.OnServiceConnectedListener, + SyncthingService.OnApiChangeListener, Preference.OnPreferenceChangeListener { - private static final String SYNCTHING_OPTIONS_KEY = "syncthing_options"; + private static final String SYNCTHING_OPTIONS_KEY = "syncthing_options"; - private static final String SYNCTHING_GUI_KEY = "syncthing_gui"; + private static final String SYNCTHING_GUI_KEY = "syncthing_gui"; - private static final String SYNCTHING_VERSION_KEY = "syncthing_version"; + private static final String SYNCTHING_VERSION_KEY = "syncthing_version"; - private CheckBoxPreference mStopNotCharging; + private CheckBoxPreference mStopNotCharging; - private CheckBoxPreference mStopMobileData; + private CheckBoxPreference mStopMobileData; - private Preference mVersion; + private Preference mVersion; - private PreferenceScreen mOptionsScreen; + private PreferenceScreen mOptionsScreen; - private PreferenceScreen mGuiScreen; + private PreferenceScreen mGuiScreen; - private SyncthingService mSyncthingService; + private SyncthingService mSyncthingService; - @Override - public void onApiChange(SyncthingService.State currentState) { - mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE); - mGuiScreen.setEnabled(currentState == SyncthingService.State.ACTIVE); + @Override + public void onApiChange(SyncthingService.State currentState) { + mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE); + mGuiScreen.setEnabled(currentState == SyncthingService.State.ACTIVE); - mVersion.setSummary(mSyncthingService.getApi().getVersion()); + 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); - } + 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); - } - } - } + 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)); - } - } + /** + * 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); + /** + * 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); - ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); + ((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this); - 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); - } + 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 onServiceConnected() { - mSyncthingService = ((SyncthingActivity) getActivity()).getService(); - mSyncthingService.registerOnApiChangeListener(this); - } + @Override + public void onServiceConnected() { + mSyncthingService = ((SyncthingActivity) getActivity()).getService(); + mSyncthingService.registerOnApiChangeListener(this); + } - /** - * 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); - } - } + /** + * 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); - } - } + /** + * 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()); - } + 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; - } + return true; + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/BatteryReceiver.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/BatteryReceiver.java index 5dbe7d27..e26f8f20 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/BatteryReceiver.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/BatteryReceiver.java @@ -9,12 +9,12 @@ import android.content.Intent; */ public class BatteryReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - boolean isCharging = Intent.ACTION_POWER_CONNECTED.equals(intent.getAction()); - Intent i = new Intent(context, SyncthingService.class); - i.putExtra(DeviceStateHolder.EXTRA_IS_CHARGING, isCharging); - context.startService(i); - } + @Override + public void onReceive(Context context, Intent intent) { + boolean isCharging = Intent.ACTION_POWER_CONNECTED.equals(intent.getAction()); + Intent i = new Intent(context, SyncthingService.class); + i.putExtra(DeviceStateHolder.EXTRA_IS_CHARGING, isCharging); + context.startService(i); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java index 97c1f52c..277cc3c2 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java @@ -8,7 +8,7 @@ import android.os.BatteryManager; /** * Holds information about the current wifi and charging state of the device. - * + *

* This information is actively read on construction, and then updated from intents that are passed * to {@link #update(android.content.Intent)}. */ @@ -17,30 +17,30 @@ public class DeviceStateHolder extends BroadcastReceiver { /** * Intent extra containing a boolean saying whether wifi is connected or not. */ - public static final String EXTRA_HAS_WIFI = "has_wifi"; + public static final String EXTRA_HAS_WIFI = "has_wifi"; /** * Intent extra containging a boolean saying whether the device is * charging or not (any power source). */ - public static final String EXTRA_IS_CHARGING = "is_charging"; + public static final String EXTRA_IS_CHARGING = "is_charging"; - private boolean mIsInitialized = false; + private boolean mIsInitialized = false; - private boolean mIsWifiConnected = false; + private boolean mIsWifiConnected = false; - private boolean mIsCharging = false; + private boolean mIsCharging = false; private SyncthingService mService; - public DeviceStateHolder(SyncthingService service) { + public DeviceStateHolder(SyncthingService service) { mService = service; - ConnectivityManager cm = (ConnectivityManager) + ConnectivityManager cm = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE); - mIsWifiConnected = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected(); - } + mIsWifiConnected = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected(); + } - @Override + @Override public void onReceive(Context context, Intent intent) { context.unregisterReceiver(this); int status = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); @@ -48,16 +48,16 @@ public class DeviceStateHolder extends BroadcastReceiver { mIsInitialized = true; } - public boolean isCharging() { - return mIsCharging; - } + public boolean isCharging() { + return mIsCharging; + } - public boolean isWifiConnected() { + public boolean isWifiConnected() { return mIsWifiConnected; } - public void update(Intent intent) { - mIsWifiConnected = intent.getBooleanExtra(EXTRA_HAS_WIFI, mIsWifiConnected); - mIsCharging = intent.getBooleanExtra(EXTRA_IS_CHARGING, mIsCharging); - } + public void update(Intent intent) { + mIsWifiConnected = intent.getBooleanExtra(EXTRA_HAS_WIFI, mIsWifiConnected); + mIsCharging = intent.getBooleanExtra(EXTRA_IS_CHARGING, mIsCharging); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/GetTask.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/GetTask.java index 7b6d22eb..720e4d4b 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/GetTask.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/GetTask.java @@ -25,60 +25,59 @@ import java.util.LinkedList; */ public class GetTask extends AsyncTask { - private static final String TAG = "GetTask"; + private static final String TAG = "GetTask"; - public static final String URI_CONFIG = "/rest/config"; + public static final String URI_CONFIG = "/rest/config"; - public static final String URI_VERSION = "/rest/version"; + public static final String URI_VERSION = "/rest/version"; - public static final String URI_SYSTEM = "/rest/system"; + public static final String URI_SYSTEM = "/rest/system"; - public static final String URI_CONNECTIONS = "/rest/connections"; + public static final String URI_CONNECTIONS = "/rest/connections"; - public static final String URI_MODEL = "/rest/model"; + public static final String URI_MODEL = "/rest/model"; - public static final String URI_NODEID = "/rest/nodeid"; + public static final String URI_NODEID = "/rest/nodeid"; - /** - * params[0] Syncthing hostname - * params[1] URI to call - * params[2] Syncthing API key - * params[3] optional parameter key - * params[4] optional parameter value - */ - @Override - protected String doInBackground(String... params) { - String fullUri = params[0] + params[1]; - HttpClient httpclient = new DefaultHttpClient(); - if (params.length == 5) { - LinkedList urlParams = new LinkedList<>(); - urlParams.add(new BasicNameValuePair(params[3], params[4])); - fullUri += "?" + URLEncodedUtils.format(urlParams, "utf-8"); - } - HttpGet get = new HttpGet(fullUri); - get.addHeader(new BasicHeader("X-API-Key", params[2])); + /** + * params[0] Syncthing hostname + * params[1] URI to call + * params[2] Syncthing API key + * params[3] optional parameter key + * params[4] optional parameter value + */ + @Override + protected String doInBackground(String... params) { + String fullUri = params[0] + params[1]; + HttpClient httpclient = new DefaultHttpClient(); + if (params.length == 5) { + LinkedList urlParams = new LinkedList<>(); + urlParams.add(new BasicNameValuePair(params[3], params[4])); + fullUri += "?" + URLEncodedUtils.format(urlParams, "utf-8"); + } + HttpGet get = new HttpGet(fullUri); + get.addHeader(new BasicHeader("X-API-Key", params[2])); - try { - HttpResponse response = httpclient.execute(get); - HttpEntity entity = response.getEntity(); + try { + HttpResponse response = httpclient.execute(get); + HttpEntity entity = response.getEntity(); - if (entity != null) { - InputStream is = entity.getContent(); + if (entity != null) { + InputStream is = entity.getContent(); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String line; - String result = ""; - while((line = br.readLine()) != null) { - result += line; - } - br.close(); - return result; - } - } - catch (IOException e) { - Log.w(TAG, "Failed to call Rest API at " + fullUri, e); - } - return null; - } + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line; + String result = ""; + while ((line = br.readLine()) != null) { + result += line; + } + br.close(); + return result; + } + } catch (IOException e) { + Log.w(TAG, "Failed to call Rest API at " + fullUri, e); + } + return null; + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/NetworkReceiver.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/NetworkReceiver.java index 7a1c054c..3de4e374 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/NetworkReceiver.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/NetworkReceiver.java @@ -11,17 +11,17 @@ import android.net.NetworkInfo; */ public class NetworkReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - ConnectivityManager cm = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); - NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); - boolean isWifiConnected = (wifiInfo != null && wifiInfo.isConnected()) || - activeNetworkInfo == null; - Intent i = new Intent(context, SyncthingService.class); - i.putExtra(DeviceStateHolder.EXTRA_HAS_WIFI, isWifiConnected); - context.startService(i); - } + @Override + public void onReceive(Context context, Intent intent) { + ConnectivityManager cm = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); + boolean isWifiConnected = (wifiInfo != null && wifiInfo.isConnected()) || + activeNetworkInfo == null; + Intent i = new Intent(context, SyncthingService.class); + i.putExtra(DeviceStateHolder.EXTRA_HAS_WIFI, isWifiConnected); + context.startService(i); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/PostTask.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/PostTask.java index f593bdbd..102a933d 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/PostTask.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/PostTask.java @@ -16,37 +16,36 @@ import java.io.IOException; */ public class PostTask extends AsyncTask { - private static final String TAG = "PostTask"; + private static final String TAG = "PostTask"; - public static final String URI_CONFIG = "/rest/config"; + public static final String URI_CONFIG = "/rest/config"; - public static final String URI_RESTART = "/rest/restart"; + public static final String URI_RESTART = "/rest/restart"; - public static final String URI_SHUTDOWN = "/rest/shutdown"; + public static final String URI_SHUTDOWN = "/rest/shutdown"; - /** - * params[0] Syncthing hostname - * params[1] URI to call - * params[2] Syncthing API key - * params[3] The request content (optional) - */ - @Override - protected Void doInBackground(String... params) { - String fullUri = params[0] + params[1]; - HttpClient httpclient = new DefaultHttpClient(); - HttpPost post = new HttpPost(fullUri); - post.addHeader(new BasicHeader("X-API-Key", params[2])); + /** + * params[0] Syncthing hostname + * params[1] URI to call + * params[2] Syncthing API key + * params[3] The request content (optional) + */ + @Override + protected Void doInBackground(String... params) { + String fullUri = params[0] + params[1]; + HttpClient httpclient = new DefaultHttpClient(); + HttpPost post = new HttpPost(fullUri); + post.addHeader(new BasicHeader("X-API-Key", params[2])); - try { - if (params.length > 3) { - post.setEntity(new StringEntity(params[3])); - } - httpclient.execute(post); - } - catch (IOException e) { - Log.w(TAG, "Failed to call Rest API at " + fullUri, e); - } - return null; - } + try { + if (params.length > 3) { + post.setEntity(new StringEntity(params[3])); + } + httpclient.execute(post); + } catch (IOException e) { + Log.w(TAG, "Failed to call Rest API at " + fullUri, e); + } + return null; + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java index 8c34f996..62368f76 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java @@ -36,860 +36,838 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class RestApi implements SyncthingService.OnWebGuiAvailableListener { - private static final String TAG = "RestApi"; + private static final String TAG = "RestApi"; - /** - * Parameter for {@link #getValue} or {@link #setValue} referring to "options" config item. - */ - public static final String TYPE_OPTIONS = "Options"; + /** + * Parameter for {@link #getValue} or {@link #setValue} referring to "options" config item. + */ + public static final String TYPE_OPTIONS = "Options"; - /** - * Parameter for {@link #getValue} or {@link #setValue} referring to "gui" config item. - */ - public static final String TYPE_GUI = "GUI"; + /** + * Parameter for {@link #getValue} or {@link #setValue} referring to "gui" config item. + */ + public static final String TYPE_GUI = "GUI"; - /** - * Key of the map element containing connection info for the local node, in the return - * value of {@link #getConnections} - */ - public static final String LOCAL_NODE_CONNECTIONS = "total"; + /** + * Key of the map element containing connection info for the local node, in the return + * value of {@link #getConnections} + */ + public static final String LOCAL_NODE_CONNECTIONS = "total"; - public static class Node { - public String Addresses; - public String Name; - public String NodeID; - } + public static class Node { + public String Addresses; + public String Name; + public String NodeID; + } - public static class SystemInfo { - public long alloc; - public double cpuPercent; - public boolean extAnnounceOK; - public int goroutines; - public String myID; - public long sys; - } + public static class SystemInfo { + public long alloc; + public double cpuPercent; + public boolean extAnnounceOK; + public int goroutines; + public String myID; + public long sys; + } - public static class Repo { - public String Directory; - public String ID; - public String Invalid; - public List Nodes; - public boolean ReadOnly; - public Versioning Versioning; - } + public static class Repo { + public String Directory; + public String ID; + public String Invalid; + public List Nodes; + public boolean ReadOnly; + public Versioning Versioning; + } - public static class Versioning { - protected final Map mParams = new HashMap<>(); - public String getType() { - return ""; - } - public Map getParams() { - return mParams; - } - } + public static class Versioning { + protected final Map mParams = new HashMap<>(); - public static class SimpleVersioning extends Versioning { - @Override - public String getType() { - return "simple"; - } - public void setParams(int keep) { - mParams.put("keep", Integer.toString(keep)); - } - } + public String getType() { + return ""; + } - public static class Connection { - public String At; - public long InBytesTotal; - public long OutBytesTotal; - public long InBits; - public long OutBits; - public String Address; - public String ClientVersion; - public int Completion; - } + public Map getParams() { + return mParams; + } + } - public static class Model { - public long globalBytes; - public long globalDeleted; - public long globalFiles; - public long localBytes; - public long localDeleted; - public long localFiles; - public long inSyncBytes; - public long inSyncFiles; - public long needBytes; - public long needFiles; - public String state; - public String invalid; - } + public static class SimpleVersioning extends Versioning { + @Override + public String getType() { + return "simple"; + } - private static final int NOTIFICATION_RESTART = 2; + public void setParams(int keep) { + mParams.put("keep", Integer.toString(keep)); + } + } - private final SyncthingService mSyncthingService; + public static class Connection { + public String At; + public long InBytesTotal; + public long OutBytesTotal; + public long InBits; + public long OutBits; + public String Address; + public String ClientVersion; + public int Completion; + } - private String mVersion; + public static class Model { + public long globalBytes; + public long globalDeleted; + public long globalFiles; + public long localBytes; + public long localDeleted; + public long localFiles; + public long inSyncBytes; + public long inSyncFiles; + public long needBytes; + public long needFiles; + public String state; + public String invalid; + } - private final String mUrl; + private static final int NOTIFICATION_RESTART = 2; - private String mApiKey; + private final SyncthingService mSyncthingService; - private JSONObject mConfig; + private String mVersion; - private String mLocalNodeId; + private final String mUrl; - private final NotificationManager mNotificationManager; + private String mApiKey; - private boolean mRestartPostponed = false; + private JSONObject mConfig; - /** - * Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS}, - * or an empty HashMap. - */ - private HashMap mPreviousConnections = new HashMap(); + private String mLocalNodeId; - /** - * Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}. - */ - private long mPreviousConnectionTime = 0; + private final NotificationManager mNotificationManager; - /** - * Stores the latest result of {@link #getModel(String, OnReceiveModelListener)} for each repo, - * for calculating node percentage in {@link #getConnections(OnReceiveConnectionsListener)}. - */ - private HashMap mCachedModelInfo = new HashMap(); + private boolean mRestartPostponed = false; - public RestApi(SyncthingService syncthingService, String url, String apiKey) { - mSyncthingService = syncthingService; - mUrl = url; - mApiKey = apiKey; - mNotificationManager = (NotificationManager) - mSyncthingService.getSystemService(Context.NOTIFICATION_SERVICE); - } + /** + * Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS}, + * or an empty HashMap. + */ + private HashMap mPreviousConnections = new HashMap(); - /** - * Returns the full URL of the web gui. - */ - public String getUrl() { - return mUrl; - } + /** + * Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}. + */ + private long mPreviousConnectionTime = 0; - /** - * Returns the API key needed to access the Rest API. - */ - public String getApiKey() { - return mApiKey; - } + /** + * Stores the latest result of {@link #getModel(String, OnReceiveModelListener)} for each repo, + * for calculating node percentage in {@link #getConnections(OnReceiveConnectionsListener)}. + */ + private HashMap mCachedModelInfo = new HashMap(); - /** - * Number of previous calls to {@link #tryIsAvailable()}. - */ - private AtomicInteger mAvailableCount = new AtomicInteger(0); + public RestApi(SyncthingService syncthingService, String url, String apiKey) { + mSyncthingService = syncthingService; + mUrl = url; + mApiKey = apiKey; + mNotificationManager = (NotificationManager) + mSyncthingService.getSystemService(Context.NOTIFICATION_SERVICE); + } - /** - * Number of asynchronous calls performed in {@link #onWebGuiAvailable()}. - */ - private static final int TOTAL_STARTUP_CALLS = 3; + /** + * Returns the full URL of the web gui. + */ + public String getUrl() { + return mUrl; + } - /** - * Gets local node id, syncthing version and config, then calls all OnApiAvailableListeners. - */ - @Override - public void onWebGuiAvailable() { + /** + * Returns the API key needed to access the Rest API. + */ + public String getApiKey() { + return mApiKey; + } + + /** + * Number of previous calls to {@link #tryIsAvailable()}. + */ + private AtomicInteger mAvailableCount = new AtomicInteger(0); + + /** + * Number of asynchronous calls performed in {@link #onWebGuiAvailable()}. + */ + private static final int TOTAL_STARTUP_CALLS = 3; + + /** + * Gets local node id, syncthing version and config, then calls all OnApiAvailableListeners. + */ + @Override + public void onWebGuiAvailable() { mAvailableCount.set(0); - new GetTask() { - @Override - protected void onPostExecute(String version) { - mVersion = version; - Log.i(TAG, "Syncthing version is " + mVersion); - tryIsAvailable(); - } - }.execute(mUrl, GetTask.URI_VERSION, mApiKey); - new GetTask() { - @Override - protected void onPostExecute(String config) { - try { - mConfig = new JSONObject(config); - tryIsAvailable(); - } - catch (JSONException e) { - Log.w(TAG, "Failed to parse config", e); - } - } - }.execute(mUrl, GetTask.URI_CONFIG, mApiKey); - getSystemInfo(new OnReceiveSystemInfoListener() { - @Override - public void onReceiveSystemInfo(SystemInfo info) { - mLocalNodeId = info.myID; - tryIsAvailable(); - } - }); - } + new GetTask() { + @Override + protected void onPostExecute(String version) { + mVersion = version; + Log.i(TAG, "Syncthing version is " + mVersion); + tryIsAvailable(); + } + }.execute(mUrl, GetTask.URI_VERSION, mApiKey); + new GetTask() { + @Override + protected void onPostExecute(String config) { + try { + mConfig = new JSONObject(config); + tryIsAvailable(); + } catch (JSONException e) { + Log.w(TAG, "Failed to parse config", e); + } + } + }.execute(mUrl, GetTask.URI_CONFIG, mApiKey); + getSystemInfo(new OnReceiveSystemInfoListener() { + @Override + public void onReceiveSystemInfo(SystemInfo info) { + mLocalNodeId = info.myID; + tryIsAvailable(); + } + }); + } - /** - * Increments mAvailableCount by one, and, if it reached TOTAL_STARTUP_CALLS, - * calls {@link SyncthingService#onApiChange()}. - */ - private void tryIsAvailable() { - int value = mAvailableCount.incrementAndGet(); - if (BuildConfig.DEBUG && value > TOTAL_STARTUP_CALLS) { - throw new AssertionError("Too many startup calls"); - } - if (value == TOTAL_STARTUP_CALLS) { - mSyncthingService.onApiChange(); - } - } + /** + * Increments mAvailableCount by one, and, if it reached TOTAL_STARTUP_CALLS, + * calls {@link SyncthingService#onApiChange()}. + */ + private void tryIsAvailable() { + int value = mAvailableCount.incrementAndGet(); + if (BuildConfig.DEBUG && value > TOTAL_STARTUP_CALLS) { + throw new AssertionError("Too many startup calls"); + } + if (value == TOTAL_STARTUP_CALLS) { + mSyncthingService.onApiChange(); + } + } - /** - * Returns the version name, or a (text) error message on failure. - */ - public String getVersion() { - return mVersion; - } + /** + * Returns the version name, or a (text) error message on failure. + */ + public String getVersion() { + return mVersion; + } - /** - * Stops syncthing. You should probably use SyncthingService.stopService() instead. - */ - public void shutdown() { - mNotificationManager.cancel(NOTIFICATION_RESTART); - new PostTask().execute(mUrl, PostTask.URI_SHUTDOWN, mApiKey); - } + /** + * Stops syncthing. You should probably use SyncthingService.stopService() instead. + */ + public void shutdown() { + mNotificationManager.cancel(NOTIFICATION_RESTART); + new PostTask().execute(mUrl, PostTask.URI_SHUTDOWN, mApiKey); + } - /** - * Gets a value from config, - * - * Booleans are returned as {@link }Boolean#toString}, arrays as space seperated string. - * - * @param name {@link #TYPE_OPTIONS} or {@link #TYPE_GUI} - * @param key The key to read from. - * @return The value as a String, or null on failure. - */ - public String getValue(String name, String key) { - try { - Object value = mConfig.getJSONObject(name).get(key); - return (value instanceof JSONArray) - ? ((JSONArray) value).join(" ").replace("\"", "") - : String.valueOf(value); - } - catch (JSONException e) { - Log.w(TAG, "Failed to get value for " + key, e); - return null; - } - } + /** + * Gets a value from config, + *

+ * Booleans are returned as {@link }Boolean#toString}, arrays as space seperated string. + * + * @param name {@link #TYPE_OPTIONS} or {@link #TYPE_GUI} + * @param key The key to read from. + * @return The value as a String, or null on failure. + */ + public String getValue(String name, String key) { + try { + Object value = mConfig.getJSONObject(name).get(key); + return (value instanceof JSONArray) + ? ((JSONArray) value).join(" ").replace("\"", "") + : String.valueOf(value); + } catch (JSONException e) { + Log.w(TAG, "Failed to get value for " + key, e); + return null; + } + } - /** - * Sets a value to config and sends it via Rest API. - * - * Booleans must be passed as {@link Boolean}, arrays as space seperated string - * with isArray true. - * - * @param name {@link #TYPE_OPTIONS} or {@link #TYPE_GUI} - * @param key The key to write to. - * @param value The new value to set, either String, Boolean or Integer. - * @param isArray True iff value is a space seperated String that should be converted to array. - */ - public void setValue(String name, String key, T value, boolean isArray, Activity activity) { - try { - mConfig.getJSONObject(name).put(key, (isArray) - ? listToJson(((String) value).split(" ")) - : value); - configUpdated(activity); - } - catch (JSONException e) { - Log.w(TAG, "Failed to set value for " + key, e); - } - } + /** + * Sets a value to config and sends it via Rest API. + *

+ * Booleans must be passed as {@link Boolean}, arrays as space seperated string + * with isArray true. + * + * @param name {@link #TYPE_OPTIONS} or {@link #TYPE_GUI} + * @param key The key to write to. + * @param value The new value to set, either String, Boolean or Integer. + * @param isArray True iff value is a space seperated String that should be converted to array. + */ + public void setValue(String name, String key, T value, boolean isArray, Activity activity) { + try { + mConfig.getJSONObject(name).put(key, (isArray) + ? listToJson(((String) value).split(" ")) + : value); + configUpdated(activity); + } catch (JSONException e) { + Log.w(TAG, "Failed to set value for " + key, e); + } + } - /** - * Converts an array of strings to JSON array. Like JSONArray#JSONArray(Object array), but - * works on all API levels. - */ - private JSONArray listToJson(String[] list) { - JSONArray json = new JSONArray(); - for (String s : list) { - json.put(s); - } - return json; - } + /** + * Converts an array of strings to JSON array. Like JSONArray#JSONArray(Object array), but + * works on all API levels. + */ + private JSONArray listToJson(String[] list) { + JSONArray json = new JSONArray(); + for (String s : list) { + json.put(s); + } + return json; + } - /** - * Sends the updated mConfig via Rest API to syncthing and displays a "restart" notification. - */ - @TargetApi(11) - private void configUpdated(Context context) { - new PostTask().execute(mUrl, PostTask.URI_CONFIG, mApiKey, mConfig.toString()); + /** + * Sends the updated mConfig via Rest API to syncthing and displays a "restart" notification. + */ + @TargetApi(11) + private void configUpdated(Context context) { + new PostTask().execute(mUrl, PostTask.URI_CONFIG, mApiKey, mConfig.toString()); - if (mRestartPostponed) - return; + if (mRestartPostponed) + return; - final Intent intent = new Intent(mSyncthingService, SyncthingService.class) - .setAction(SyncthingService.ACTION_RESTART); + final Intent intent = new Intent(mSyncthingService, SyncthingService.class) + .setAction(SyncthingService.ACTION_RESTART); - AlertDialog.Builder builder = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) - ? new AlertDialog.Builder(context.getApplicationContext(), AlertDialog.THEME_HOLO_LIGHT) - : new AlertDialog.Builder(context.getApplicationContext()); - AlertDialog dialog = builder.setMessage(R.string.restart_title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - mSyncthingService.startService(intent); - } - }) - .setNegativeButton(R.string.restart_later, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - createRestartNotification(); - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - createRestartNotification(); - } - }) - .create(); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.show(); - } + AlertDialog.Builder builder = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + ? new AlertDialog.Builder(context.getApplicationContext(), AlertDialog.THEME_HOLO_LIGHT) + : new AlertDialog.Builder(context.getApplicationContext()); + AlertDialog dialog = builder.setMessage(R.string.restart_title) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mSyncthingService.startService(intent); + } + }) + .setNegativeButton(R.string.restart_later, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + createRestartNotification(); + } + }) + .setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + createRestartNotification(); + } + }) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } - /** - * Creates a notification prompting the user to restart the app. - */ - private void createRestartNotification() { - Intent intent = new Intent(mSyncthingService, SyncthingService.class) - .setAction(SyncthingService.ACTION_RESTART); - PendingIntent pi = PendingIntent.getService(mSyncthingService, 0, intent, 0); + /** + * Creates a notification prompting the user to restart the app. + */ + private void createRestartNotification() { + Intent intent = new Intent(mSyncthingService, SyncthingService.class) + .setAction(SyncthingService.ACTION_RESTART); + PendingIntent pi = PendingIntent.getService(mSyncthingService, 0, intent, 0); - Notification n = new NotificationCompat.Builder(mSyncthingService) - .setContentTitle(mSyncthingService.getString(R.string.restart_title)) - .setContentText(mSyncthingService.getString(R.string.restart_notification_text)) - .setSmallIcon(R.drawable.ic_launcher) - .setContentIntent(pi) - .build(); - n.flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL; - mNotificationManager.notify(NOTIFICATION_RESTART, n); - mRestartPostponed = true; - } + Notification n = new NotificationCompat.Builder(mSyncthingService) + .setContentTitle(mSyncthingService.getString(R.string.restart_title)) + .setContentText(mSyncthingService.getString(R.string.restart_notification_text)) + .setSmallIcon(R.drawable.ic_launcher) + .setContentIntent(pi) + .build(); + n.flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL; + mNotificationManager.notify(NOTIFICATION_RESTART, n); + mRestartPostponed = true; + } - /** - * Returns a list of all existing nodes. - */ - public List getNodes() { - if (mConfig == null) - return new ArrayList(); + /** + * Returns a list of all existing nodes. + */ + public List getNodes() { + if (mConfig == null) + return new ArrayList(); - try { - return getNodes(mConfig.getJSONArray("Nodes")); - } - catch (JSONException e) { - Log.w(TAG, "Failed to read nodes", e); - return new ArrayList(); - } - } + try { + return getNodes(mConfig.getJSONArray("Nodes")); + } catch (JSONException e) { + Log.w(TAG, "Failed to read nodes", e); + return new ArrayList(); + } + } - /** - * Result listener for {@link #getSystemInfo(OnReceiveSystemInfoListener)}. - */ - public interface OnReceiveSystemInfoListener { - public void onReceiveSystemInfo(SystemInfo info); - } + /** + * Result listener for {@link #getSystemInfo(OnReceiveSystemInfoListener)}. + */ + public interface OnReceiveSystemInfoListener { + public void onReceiveSystemInfo(SystemInfo info); + } - /** - * Requests and parses information about current system status and resource usage. - * - * @param listener Callback invoked when the result is received. - */ - public void getSystemInfo(final OnReceiveSystemInfoListener listener) { - new GetTask() { - @Override - protected void onPostExecute(String s) { - if (s == null) - return; + /** + * Requests and parses information about current system status and resource usage. + * + * @param listener Callback invoked when the result is received. + */ + public void getSystemInfo(final OnReceiveSystemInfoListener listener) { + new GetTask() { + @Override + protected void onPostExecute(String s) { + if (s == null) + return; - try { - JSONObject system = new JSONObject(s); - SystemInfo si = new SystemInfo(); - si.alloc = system.getLong("alloc"); - si.cpuPercent = system.getDouble("cpuPercent"); - si.extAnnounceOK = system.optBoolean("extAnnounceOK", false); - si.goroutines = system.getInt("goroutines"); - si.myID = system.getString("myID"); - si.sys = system.getLong("sys"); - listener.onReceiveSystemInfo(si); - } - catch (JSONException e) { - Log.w(TAG, "Failed to read system info", e); - } - } - }.execute(mUrl, GetTask.URI_SYSTEM, mApiKey); - } + try { + JSONObject system = new JSONObject(s); + SystemInfo si = new SystemInfo(); + si.alloc = system.getLong("alloc"); + si.cpuPercent = system.getDouble("cpuPercent"); + si.extAnnounceOK = system.optBoolean("extAnnounceOK", false); + si.goroutines = system.getInt("goroutines"); + si.myID = system.getString("myID"); + si.sys = system.getLong("sys"); + listener.onReceiveSystemInfo(si); + } catch (JSONException e) { + Log.w(TAG, "Failed to read system info", e); + } + } + }.execute(mUrl, GetTask.URI_SYSTEM, mApiKey); + } - /** - * Returns a list of all nodes in the array nodes, excluding the local node. - */ - private List getNodes(JSONArray nodes) throws JSONException { - List ret; - ret = new ArrayList(nodes.length()); - for (int i = 0; i < nodes.length(); i++) { - JSONObject json = nodes.getJSONObject(i); - Node n = new Node(); - if (!json.isNull("Addresses")) { - n.Addresses = json.getJSONArray("Addresses").join(" ").replace("\"", ""); - } - n.Name = json.getString("Name"); - n.NodeID = json.getString("NodeID"); - if (!n.NodeID.equals(mLocalNodeId)) { - ret.add(n); - } - } - return ret; - } + /** + * Returns a list of all nodes in the array nodes, excluding the local node. + */ + private List getNodes(JSONArray nodes) throws JSONException { + List ret; + ret = new ArrayList(nodes.length()); + for (int i = 0; i < nodes.length(); i++) { + JSONObject json = nodes.getJSONObject(i); + Node n = new Node(); + if (!json.isNull("Addresses")) { + n.Addresses = json.getJSONArray("Addresses").join(" ").replace("\"", ""); + } + n.Name = json.getString("Name"); + n.NodeID = json.getString("NodeID"); + if (!n.NodeID.equals(mLocalNodeId)) { + ret.add(n); + } + } + return ret; + } - /** - * Returns a list of all existing repositores. - */ - public List getRepos() { - if (mConfig == null) - return new ArrayList(); + /** + * Returns a list of all existing repositores. + */ + public List getRepos() { + if (mConfig == null) + return new ArrayList(); - List ret = null; - try { - JSONArray repos = mConfig.getJSONArray("Repositories"); - ret = new ArrayList(repos.length()); - for (int i = 0; i < repos.length(); i++) { - JSONObject json = repos.getJSONObject(i); - Repo r = new Repo(); - r.Directory = json.getString("Directory"); - r.ID = json.getString("ID"); - r.Invalid = json.getString("Invalid"); - r.Nodes = new ArrayList(); - JSONArray nodes = json.getJSONArray("Nodes"); - for (int j = 0; j < nodes.length(); j++) { - JSONObject n = nodes.getJSONObject(j); - String id = n.getString("NodeID"); - for (Node n2 : getNodes()) { - if (n2.NodeID.equals(id)) { - r.Nodes.add(n2); - } - } - } + List ret = null; + try { + JSONArray repos = mConfig.getJSONArray("Repositories"); + ret = new ArrayList(repos.length()); + for (int i = 0; i < repos.length(); i++) { + JSONObject json = repos.getJSONObject(i); + Repo r = new Repo(); + r.Directory = json.getString("Directory"); + r.ID = json.getString("ID"); + r.Invalid = json.getString("Invalid"); + r.Nodes = getNodes(json.getJSONArray("Nodes")); - r.ReadOnly = json.getBoolean("ReadOnly"); - JSONObject versioning = json.getJSONObject("Versioning"); - if (versioning.getString("Type").equals("simple")) { - SimpleVersioning sv = new SimpleVersioning(); - JSONObject params = versioning.getJSONObject("Params"); - sv.setParams(params.getInt("keep")); - r.Versioning = sv; - } - else { - r.Versioning = new Versioning(); - } + r.ReadOnly = json.getBoolean("ReadOnly"); + JSONObject versioning = json.getJSONObject("Versioning"); + if (versioning.getString("Type").equals("simple")) { + SimpleVersioning sv = new SimpleVersioning(); + JSONObject params = versioning.getJSONObject("Params"); + sv.setParams(params.getInt("keep")); + r.Versioning = sv; + } else { + r.Versioning = new Versioning(); + } - ret.add(r); - } - } - catch (JSONException e) { - Log.w(TAG, "Failed to read nodes", e); - } - return ret; - } + ret.add(r); + } + } catch (JSONException e) { + Log.w(TAG, "Failed to read nodes", e); + } + return ret; + } - /** - * Converts a number of bytes to a human readable file size (eg 3.5 GB). - */ - public static String readableFileSize(Context context, long bytes) { - final String[] units = context.getResources().getStringArray(R.array.file_size_units); - if (bytes <= 0) return "0 " + units[0]; - int digitGroups = (int) (Math.log10(bytes)/Math.log10(1024)); - return new DecimalFormat("#,##0.#") - .format(bytes/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; - } + /** + * Converts a number of bytes to a human readable file size (eg 3.5 GB). + */ + public static String readableFileSize(Context context, long bytes) { + final String[] units = context.getResources().getStringArray(R.array.file_size_units); + if (bytes <= 0) return "0 " + units[0]; + int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); + return new DecimalFormat("#,##0.#") + .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } - /** - * Converts a number of bytes to a human readable transfer rate in bits (eg 100 Kb/s). - */ - public static String readableTransferRate(Context context, long bits) { - final String[] units = context.getResources().getStringArray(R.array.transfer_rate_units); - if (bits <= 0) return "0 " + units[0]; - int digitGroups = (int) (Math.log10(bits)/Math.log10(1024)); - return new DecimalFormat("#,##0.#") - .format(bits/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; - } + /** + * Converts a number of bytes to a human readable transfer rate in bits (eg 100 Kb/s). + */ + public static String readableTransferRate(Context context, long bits) { + final String[] units = context.getResources().getStringArray(R.array.transfer_rate_units); + if (bits <= 0) return "0 " + units[0]; + int digitGroups = (int) (Math.log10(bits) / Math.log10(1024)); + return new DecimalFormat("#,##0.#") + .format(bits / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } - /** - * Listener for {@link #getConnections}. - */ - public interface OnReceiveConnectionsListener { + /** + * Listener for {@link #getConnections}. + */ + public interface OnReceiveConnectionsListener { - /** - * @param connections Map from Node ID to {@link Connection}. - * - * NOTE: The parameter connections is cached internally. Do not modify it or - * any of its contents. - */ - public void onReceiveConnections(Map connections); - } + /** + * @param connections Map from Node ID to {@link Connection}. + *

+ * NOTE: The parameter connections is cached internally. Do not modify it or + * any of its contents. + */ + public void onReceiveConnections(Map connections); + } - /** - * Returns connection info for the local node and all connected nodes. - * - * Use the key {@link #LOCAL_NODE_CONNECTIONS} to get connection info for the local node. - */ - public void getConnections(final OnReceiveConnectionsListener listener) { - new GetTask() { - @Override - protected void onPostExecute(String s) { - if (s == null) - return; + /** + * Returns connection info for the local node and all connected nodes. + *

+ * Use the key {@link #LOCAL_NODE_CONNECTIONS} to get connection info for the local node. + */ + public void getConnections(final OnReceiveConnectionsListener listener) { + new GetTask() { + @Override + protected void onPostExecute(String s) { + if (s == null) + return; - Long now = System.currentTimeMillis(); - Long difference = (now - mPreviousConnectionTime) / 1000; - if (difference < 1) { - listener.onReceiveConnections(mPreviousConnections); - return; - } + Long now = System.currentTimeMillis(); + Long difference = (now - mPreviousConnectionTime) / 1000; + if (difference < 1) { + listener.onReceiveConnections(mPreviousConnections); + return; + } - try { - JSONObject json = new JSONObject(s); - String[] names = json.names().join(" ").replace("\"", "").split(" "); - HashMap connections = new HashMap(); - for (String nodeId : names) { - Connection c = new Connection(); - JSONObject conn = json.getJSONObject(nodeId); - c.Address = nodeId; - c.At = conn.getString("At"); - c.InBytesTotal = conn.getLong("InBytesTotal"); - c.OutBytesTotal = conn.getLong("OutBytesTotal"); - c.Address = conn.getString("Address"); - c.ClientVersion = conn.getString("ClientVersion"); - c.Completion = getNodeCompletion(nodeId); + try { + JSONObject json = new JSONObject(s); + String[] names = json.names().join(" ").replace("\"", "").split(" "); + HashMap connections = new HashMap(); + for (String nodeId : names) { + Connection c = new Connection(); + JSONObject conn = json.getJSONObject(nodeId); + c.Address = nodeId; + c.At = conn.getString("At"); + c.InBytesTotal = conn.getLong("InBytesTotal"); + c.OutBytesTotal = conn.getLong("OutBytesTotal"); + c.Address = conn.getString("Address"); + c.ClientVersion = conn.getString("ClientVersion"); + c.Completion = getNodeCompletion(nodeId); - Connection prev = (mPreviousConnections.containsKey(nodeId)) - ? mPreviousConnections.get(nodeId) - : new Connection(); - mPreviousConnectionTime = now; - if (difference != 0) { - c.InBits = Math.max(0, 8 * - (conn.getLong("InBytesTotal") - prev.InBytesTotal) / difference); - c.OutBits = Math.max(0, 8 * - (conn.getLong("OutBytesTotal") - prev.OutBytesTotal) / difference); - } + Connection prev = (mPreviousConnections.containsKey(nodeId)) + ? mPreviousConnections.get(nodeId) + : new Connection(); + mPreviousConnectionTime = now; + if (difference != 0) { + c.InBits = Math.max(0, 8 * + (conn.getLong("InBytesTotal") - prev.InBytesTotal) / difference); + c.OutBits = Math.max(0, 8 * + (conn.getLong("OutBytesTotal") - prev.OutBytesTotal) / difference); + } - connections.put(nodeId, c); + connections.put(nodeId, c); - } - mPreviousConnections = connections; - listener.onReceiveConnections(mPreviousConnections); - } - catch (JSONException e) { - Log.w(TAG, "Failed to parse connections", e); - } - } - }.execute(mUrl, GetTask.URI_CONNECTIONS, mApiKey); - } + } + mPreviousConnections = connections; + listener.onReceiveConnections(mPreviousConnections); + } catch (JSONException e) { + Log.w(TAG, "Failed to parse connections", e); + } + } + }.execute(mUrl, GetTask.URI_CONNECTIONS, mApiKey); + } - /** - * Calculates completion percentage for the given node using {@link #mCachedModelInfo}. - */ - private int getNodeCompletion(String nodeId) { - int repoCount = 0; - float percentageSum = 0; - for (String id : mCachedModelInfo.keySet()) { - boolean isShared = false; - outerloop: - for (Repo r : getRepos()) { - for (Node n : r.Nodes) { - if (n.NodeID.equals(nodeId)) { - isShared = true; - break outerloop; - } + /** + * Calculates completion percentage for the given node using {@link #mCachedModelInfo}. + */ + private int getNodeCompletion(String nodeId) { + int repoCount = 0; + float percentageSum = 0; + for (String id : mCachedModelInfo.keySet()) { + boolean isShared = false; + outerloop: + for (Repo r : getRepos()) { + for (Node n : r.Nodes) { + if (n.NodeID.equals(nodeId)) { + isShared = true; + break outerloop; + } - } - } - if (isShared) { - long global = mCachedModelInfo.get(id).globalBytes; - long local = mCachedModelInfo.get(id).localBytes; - percentageSum += (global != 0) - ? (local * 100f) / global - : 100f; - repoCount++; - } - } - return (repoCount != 0) - ? (int) percentageSum / repoCount - : 100; - } + } + } + if (isShared) { + long global = mCachedModelInfo.get(id).globalBytes; + long local = mCachedModelInfo.get(id).localBytes; + percentageSum += (global != 0) + ? (local * 100f) / global + : 100f; + repoCount++; + } + } + return (repoCount != 0) + ? (int) percentageSum / repoCount + : 100; + } - /** - * Listener for {@link #getModel}. - */ - public interface OnReceiveModelListener { - public void onReceiveModel(String repoId, Model model); - } + /** + * Listener for {@link #getModel}. + */ + public interface OnReceiveModelListener { + public void onReceiveModel(String repoId, Model model); + } - /** - * Returns status information about the repo with the given ID. - */ - public void getModel(final String repoId, final OnReceiveModelListener listener) { - new GetTask() { - @Override - protected void onPostExecute(String s) { - if (s == null) - return; + /** + * Returns status information about the repo with the given ID. + */ + public void getModel(final String repoId, final OnReceiveModelListener listener) { + new GetTask() { + @Override + protected void onPostExecute(String s) { + if (s == null) + return; - try { - JSONObject json = new JSONObject(s); - Model m = new Model(); - m.globalBytes = json.getLong("globalBytes"); - m.globalDeleted = json.getLong("globalDeleted"); - m.globalFiles = json.getLong("globalFiles"); - m.localBytes = json.getLong("localBytes"); - m.localDeleted = json.getLong("localDeleted"); - m.localFiles = json.getLong("localFiles"); - m.inSyncBytes = json.getLong("inSyncBytes"); - m.inSyncFiles = json.getLong("inSyncFiles"); - m.needBytes = json.getLong("needBytes"); - m.needFiles = json.getLong("needFiles"); - m.state = json.getString("state"); - m.invalid = json.optString("invalid"); - mCachedModelInfo.put(repoId, m); - listener.onReceiveModel(repoId, m); - } - catch (JSONException e) { - Log.w(TAG, "Failed to read repository info", e); - } - } - }.execute(mUrl, GetTask.URI_MODEL, mApiKey, "repo", repoId); - } + try { + JSONObject json = new JSONObject(s); + Model m = new Model(); + m.globalBytes = json.getLong("globalBytes"); + m.globalDeleted = json.getLong("globalDeleted"); + m.globalFiles = json.getLong("globalFiles"); + m.localBytes = json.getLong("localBytes"); + m.localDeleted = json.getLong("localDeleted"); + m.localFiles = json.getLong("localFiles"); + m.inSyncBytes = json.getLong("inSyncBytes"); + m.inSyncFiles = json.getLong("inSyncFiles"); + m.needBytes = json.getLong("needBytes"); + m.needFiles = json.getLong("needFiles"); + m.state = json.getString("state"); + m.invalid = json.optString("invalid"); + mCachedModelInfo.put(repoId, m); + listener.onReceiveModel(repoId, m); + } catch (JSONException e) { + Log.w(TAG, "Failed to read repository info", e); + } + } + }.execute(mUrl, GetTask.URI_MODEL, mApiKey, "repo", repoId); + } - /** - * Updates or creates the given node, depending on whether it already exists. - * - * @param node Settings of the node to edit. To create a node, pass a non-existant node ID. - * @param listener {@link OnNodeIdNormalizedListener} for the normalized node ID. - */ - public void editNode(final Node node, - final OnNodeIdNormalizedListener listener) { - mSyncthingService.getApi().normalizeNodeId(node.NodeID, - new RestApi.OnNodeIdNormalizedListener() { - @Override - public void onNodeIdNormalized(String normalizedId, String error) { - listener.onNodeIdNormalized(normalizedId, error); - if (normalizedId == null) - return; + /** + * Updates or creates the given node, depending on whether it already exists. + * + * @param node Settings of the node to edit. To create a node, pass a non-existant node ID. + * @param listener {@link OnNodeIdNormalizedListener} for the normalized node ID. + */ + public void editNode(final Node node, + final OnNodeIdNormalizedListener listener) { + mSyncthingService.getApi().normalizeNodeId(node.NodeID, + new RestApi.OnNodeIdNormalizedListener() { + @Override + public void onNodeIdNormalized(String normalizedId, String error) { + listener.onNodeIdNormalized(normalizedId, error); + if (normalizedId == null) + return; - node.NodeID = normalizedId; - // If the node already exists, just update it. - boolean create = true; - for (RestApi.Node n : getNodes()) { - if (n.NodeID.equals(node.NodeID)) { - create = false; - } - } + node.NodeID = normalizedId; + // If the node already exists, just update it. + boolean create = true; + for (RestApi.Node n : getNodes()) { + if (n.NodeID.equals(node.NodeID)) { + create = false; + } + } - try { - JSONArray nodes = mConfig.getJSONArray("Nodes"); - JSONObject n = null; - if (create) { - n = new JSONObject(); - nodes.put(n); - } - else { - for (int i = 0; i < nodes.length(); i++) { - JSONObject json = nodes.getJSONObject(i); - if (node.NodeID.equals(json.getString("NodeID"))) { - n = nodes.getJSONObject(i); - break; - } - } - } - n.put("NodeID", node.NodeID); - n.put("Name", node.Name); - n.put("Addresses", listToJson(node.Addresses.split(" "))); - configUpdated(mSyncthingService); - } - catch (JSONException e) { - Log.w(TAG, "Failed to read nodes", e); - } - } - }); - } + try { + JSONArray nodes = mConfig.getJSONArray("Nodes"); + JSONObject n = null; + if (create) { + n = new JSONObject(); + nodes.put(n); + } else { + for (int i = 0; i < nodes.length(); i++) { + JSONObject json = nodes.getJSONObject(i); + if (node.NodeID.equals(json.getString("NodeID"))) { + n = nodes.getJSONObject(i); + break; + } + } + } + n.put("NodeID", node.NodeID); + n.put("Name", node.Name); + n.put("Addresses", listToJson(node.Addresses.split(" "))); + configUpdated(mSyncthingService); + } catch (JSONException e) { + Log.w(TAG, "Failed to read nodes", e); + } + } + } + ); + } - /** - * Deletes the given node from syncthing. - */ - public void deleteNode(Node node, Activity activity) { - try { - JSONArray nodes = mConfig.getJSONArray("Nodes"); + /** + * Deletes the given node from syncthing. + */ + public void deleteNode(Node node, Activity activity) { + try { + JSONArray nodes = mConfig.getJSONArray("Nodes"); - for (int i = 0; i < nodes.length(); i++) { - JSONObject json = nodes.getJSONObject(i); - if (node.NodeID.equals(json.getString("NodeID"))) { - mConfig.remove("Nodes"); - mConfig.put("Nodes", delete(nodes, nodes.getJSONObject(i))); - break; - } - } - configUpdated(activity); - } - catch (JSONException e) { - Log.w(TAG, "Failed to edit repo", e); - } - } + for (int i = 0; i < nodes.length(); i++) { + JSONObject json = nodes.getJSONObject(i); + if (node.NodeID.equals(json.getString("NodeID"))) { + mConfig.remove("Nodes"); + mConfig.put("Nodes", delete(nodes, nodes.getJSONObject(i))); + break; + } + } + configUpdated(activity); + } catch (JSONException e) { + Log.w(TAG, "Failed to edit repo", e); + } + } - /** - * Updates or creates the given node. - */ - public void editRepo(Repo repo, boolean create, Context context) { - try { - JSONArray repos = mConfig.getJSONArray("Repositories"); - JSONObject r = null; - if (create) { - r = new JSONObject(); - repos.put(r); - } - else { - for (int i = 0; i < repos.length(); i++) { - JSONObject json = repos.getJSONObject(i); - if (repo.ID.equals(json.getString("ID"))) { - r = repos.getJSONObject(i); - break; - } - } - } - r.put("Directory", repo.Directory); - r.put("ID", repo.ID); - r.put("IgnorePerms", true); - r.put("ReadOnly", repo.ReadOnly); - JSONArray nodes = new JSONArray(); - for (Node n : repo.Nodes) { - JSONObject element = new JSONObject(); - element.put("Addresses", listToJson(n.Addresses.split(" "))); - element.put("Name", n.Name); - element.put("NodeID", n.NodeID); - nodes.put(element); - } - r.put("Nodes", nodes); - JSONObject versioning = new JSONObject(); - versioning.put("Type", repo.Versioning.getType()); - JSONObject params = new JSONObject(); - versioning.put("Params", params); - for (String key : repo.Versioning.getParams().keySet()) { - params.put(key, repo.Versioning.getParams().get(key)); - } - r.put("Versioning", versioning); - configUpdated(context); - } - catch (JSONException e) { - Log.w(TAG, "Failed to edit repo " + repo.ID + " at " + repo.Directory, e); - } - } + /** + * Updates or creates the given node. + */ + public void editRepo(Repo repo, boolean create, Context context) { + try { + JSONArray repos = mConfig.getJSONArray("Repositories"); + JSONObject r = null; + if (create) { + r = new JSONObject(); + repos.put(r); + } else { + for (int i = 0; i < repos.length(); i++) { + JSONObject json = repos.getJSONObject(i); + if (repo.ID.equals(json.getString("ID"))) { + r = repos.getJSONObject(i); + break; + } + } + } + r.put("Directory", repo.Directory); + r.put("ID", repo.ID); + r.put("IgnorePerms", true); + r.put("ReadOnly", repo.ReadOnly); + JSONArray nodes = new JSONArray(); + for (Node n : repo.Nodes) { + JSONObject element = new JSONObject(); + element.put("Addresses", listToJson(n.Addresses.split(" "))); + element.put("Name", n.Name); + element.put("NodeID", n.NodeID); + nodes.put(element); + } + r.put("Nodes", nodes); + JSONObject versioning = new JSONObject(); + versioning.put("Type", repo.Versioning.getType()); + JSONObject params = new JSONObject(); + versioning.put("Params", params); + for (String key : repo.Versioning.getParams().keySet()) { + params.put(key, repo.Versioning.getParams().get(key)); + } + r.put("Versioning", versioning); + configUpdated(context); + } catch (JSONException e) { + Log.w(TAG, "Failed to edit repo " + repo.ID + " at " + repo.Directory, e); + } + } - /** - * Deletes the given repository from syncthing. - */ - public void deleteRepo(Repo repo, Activity activity) { - try { - JSONArray repos = mConfig.getJSONArray("Repositories"); + /** + * Deletes the given repository from syncthing. + */ + public void deleteRepo(Repo repo, Activity activity) { + try { + JSONArray repos = mConfig.getJSONArray("Repositories"); - for (int i = 0; i < repos.length(); i++) { - JSONObject json = repos.getJSONObject(i); - if (repo.ID.equals(json.getString("ID"))) { - mConfig.remove("Repositories"); - mConfig.put("Repositories", delete(repos, repos.getJSONObject(i))); - break; - } - } - configUpdated(activity); - } - catch (JSONException e) { - Log.w(TAG, "Failed to edit repo", e); - } - } + for (int i = 0; i < repos.length(); i++) { + JSONObject json = repos.getJSONObject(i); + if (repo.ID.equals(json.getString("ID"))) { + mConfig.remove("Repositories"); + mConfig.put("Repositories", delete(repos, repos.getJSONObject(i))); + break; + } + } + configUpdated(activity); + } catch (JSONException e) { + Log.w(TAG, "Failed to edit repo", e); + } + } - /** - * Replacement for {@link org.json.JSONArray#remove(int)}, which is not available on older APIs. - */ - private JSONArray delete(JSONArray array, JSONObject delete) throws JSONException { - JSONArray newArray = new JSONArray(); - for (int i = 0; i < array.length(); i++) { - if (!array.getJSONObject(i).equals(delete)) { - newArray.put(array.get(i)); - } - } - return newArray; - } + /** + * Replacement for {@link org.json.JSONArray#remove(int)}, which is not available on older APIs. + */ + private JSONArray delete(JSONArray array, JSONObject delete) throws JSONException { + JSONArray newArray = new JSONArray(); + for (int i = 0; i < array.length(); i++) { + if (!array.getJSONObject(i).equals(delete)) { + newArray.put(array.get(i)); + } + } + return newArray; + } - /** - * Result listener for {@link #normalizeNodeId(String, OnNodeIdNormalizedListener)}. - */ - public interface OnNodeIdNormalizedListener { - /** - * On any call, exactly one parameter will be null. - * - * @param normalizedId The normalized node ID, or null on error. - * @param error An error message, or null on success. - */ - public void onNodeIdNormalized(String normalizedId, String error); - } + /** + * Result listener for {@link #normalizeNodeId(String, OnNodeIdNormalizedListener)}. + */ + public interface OnNodeIdNormalizedListener { + /** + * On any call, exactly one parameter will be null. + * + * @param normalizedId The normalized node ID, or null on error. + * @param error An error message, or null on success. + */ + public void onNodeIdNormalized(String normalizedId, String error); + } - /** - * Normalizes a given node ID. - */ - public void normalizeNodeId(String id, final OnNodeIdNormalizedListener listener) { - new GetTask() { - @Override - protected void onPostExecute(String s) { - super.onPostExecute(s); - String normalized = null; - String error = null; - try { - JSONObject json = new JSONObject(s); - normalized = json.optString("id", null); - error = json.optString("error", null); - } - catch (JSONException e) { - Log.d(TAG, "Failed to parse normalized node ID JSON", e); - } - listener.onNodeIdNormalized(normalized, error); - } - }.execute(mUrl, GetTask.URI_NODEID, mApiKey, "id", id); - } + /** + * Normalizes a given node ID. + */ + public void normalizeNodeId(String id, final OnNodeIdNormalizedListener listener) { + new GetTask() { + @Override + protected void onPostExecute(String s) { + super.onPostExecute(s); + String normalized = null; + String error = null; + try { + JSONObject json = new JSONObject(s); + normalized = json.optString("id", null); + error = json.optString("error", null); + } catch (JSONException e) { + Log.d(TAG, "Failed to parse normalized node ID JSON", e); + } + listener.onNodeIdNormalized(normalized, error); + } + }.execute(mUrl, GetTask.URI_NODEID, mApiKey, "id", id); + } - /** - * Shares the given node id via Intent. Must be called from an Activity. - */ - public static void shareNodeId(Activity activity, String id) { - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.setType("text/plain"); - shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, id); - activity.startActivity(Intent.createChooser( - shareIntent, activity.getString(R.string.send_node_id_to))); - } + /** + * Shares the given node id via Intent. Must be called from an Activity. + */ + public static void shareNodeId(Activity activity, String id) { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.setType("text/plain"); + shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, id); + activity.startActivity(Intent.createChooser( + shareIntent, activity.getString(R.string.send_node_id_to))); + } - /** - * Copies the given node ID to the clipboard (and shows a Toast telling about it). - * - * @param id The node ID to copy. - */ - @TargetApi(11) - public void copyNodeId(String id) { - int sdk = android.os.Build.VERSION.SDK_INT; - if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) { - android.text.ClipboardManager clipboard = (android.text.ClipboardManager) - mSyncthingService.getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setText(id); - } else { - ClipboardManager clipboard = (ClipboardManager) - mSyncthingService.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(mSyncthingService.getString(R.string.node_id), id); - clipboard.setPrimaryClip(clip); - } - Toast.makeText(mSyncthingService, R.string.node_id_copied_to_clipboard, Toast.LENGTH_SHORT) - .show(); - } + /** + * Copies the given node ID to the clipboard (and shows a Toast telling about it). + * + * @param id The node ID to copy. + */ + @TargetApi(11) + public void copyNodeId(String id) { + int sdk = android.os.Build.VERSION.SDK_INT; + if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) + mSyncthingService.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText(id); + } else { + ClipboardManager clipboard = (ClipboardManager) + mSyncthingService.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(mSyncthingService.getString(R.string.node_id), id); + clipboard.setPrimaryClip(clip); + } + Toast.makeText(mSyncthingService, R.string.node_id_copied_to_clipboard, Toast.LENGTH_SHORT) + .show(); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java index 06f4a69e..3d5fb023 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java @@ -43,7 +43,7 @@ public class SyncthingRunnable implements Runnable { DataOutputStream dos = null; int ret = 1; Process process = null; - try { + try { process = Runtime.getRuntime().exec("sh"); dos = new DataOutputStream(process.getOutputStream()); // Set home directory to data folder for syncthing to use. @@ -57,22 +57,19 @@ public class SyncthingRunnable implements Runnable { log(process.getInputStream()); ret = process.waitFor(); - } - catch(IOException | InterruptedException e) { + } catch (IOException | InterruptedException e) { Log.e(TAG, "Failed to execute syncthing binary or read output", e); - } - finally { + } finally { try { dos.close(); - } - catch (IOException e) { + } catch (IOException e) { Log.w(TAG, "Failed to close shell stream", e); } process.destroy(); final int retVal = ret; if (ret != 0) { - Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " + Integer.toString(retVal)); - postCrashDialog(retVal); + Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " + Integer.toString(retVal)); + postCrashDialog(retVal); } } } @@ -95,7 +92,8 @@ public class SyncthingRunnable implements Runnable { int i) { System.exit(0); } - }) + } + ) .create(); dialog.getWindow() .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); @@ -120,8 +118,7 @@ public class SyncthingRunnable implements Runnable { while ((line = br.readLine()) != null) { Log.i(TAG_NATIVE, line); } - } - catch (IOException e) { + } catch (IOException e) { // NOTE: This is sometimes called on shutdown, as // Process.destroy() closes the stream. Log.w(TAG, "Failed to read syncthing command line output", e); diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java index 2897b12a..f73d6dbf 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java @@ -40,56 +40,56 @@ import java.util.Iterator; */ public class SyncthingService extends Service { - private static final String TAG = "SyncthingService"; + private static final String TAG = "SyncthingService"; - private static final int NOTIFICATION_RUNNING = 1; + private static final int NOTIFICATION_RUNNING = 1; - /** - * Intent action to perform a syncthing restart. - */ - public static final String ACTION_RESTART = "restart"; + /** + * Intent action to perform a syncthing restart. + */ + public static final String ACTION_RESTART = "restart"; - /** - * Interval in ms at which the GUI is updated (eg {@link }LocalNodeInfoFragment}). - */ - public static final int GUI_UPDATE_INTERVAL = 1000; + /** + * Interval in ms at which the GUI is updated (eg {@link }LocalNodeInfoFragment}). + */ + public static final int GUI_UPDATE_INTERVAL = 1000; - /** - * Interval in ms, at which connections to the web gui are performed on first start - * to find out if it's online. - */ - private static final long WEB_GUI_POLL_INTERVAL = 100; + /** + * Interval in ms, at which connections to the web gui are performed on first start + * to find out if it's online. + */ + private static final long WEB_GUI_POLL_INTERVAL = 100; - /** - * Name of the public key file in the data directory. - */ - private static final String PUBLIC_KEY_FILE = "cert.pem"; + /** + * Name of the public key file in the data directory. + */ + private static final String PUBLIC_KEY_FILE = "cert.pem"; - /** - * Name of the private key file in the data directory. - */ - private static final String PRIVATE_KEY_FILE = "key.pem"; + /** + * Name of the private key file in the data directory. + */ + private static final String PRIVATE_KEY_FILE = "key.pem"; - private RestApi mApi; + private RestApi mApi; - private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this); + private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this); - /** - * Callback for when the Syncthing web interface becomes first available after service start. - */ - public interface OnWebGuiAvailableListener { - public void onWebGuiAvailable(); - } + /** + * Callback for when the Syncthing web interface becomes first available after service start. + */ + public interface OnWebGuiAvailableListener { + public void onWebGuiAvailable(); + } - private final HashSet mOnWebGuiAvailableListeners = - new HashSet<>(); + private final HashSet mOnWebGuiAvailableListeners = + new HashSet<>(); - public interface OnApiChangeListener { - public void onApiChange(State currentState); - } + public interface OnApiChangeListener { + public void onApiChange(State currentState); + } - private final HashSet> mOnApiChangeListeners = - new HashSet<>(); + private final HashSet> mOnApiChangeListeners = + new HashSet<>(); /** * INIT: Service is starting up and initializing. @@ -97,334 +97,328 @@ public class SyncthingService extends Service { * ACTIVE: Syncthing binary is up and running. * DISABLED: Syncthing binary is stopped according to user preferences. */ - public enum State { + public enum State { INIT, - STARTING, - ACTIVE, - DISABLED - } + STARTING, + ACTIVE, + DISABLED + } - private State mCurrentState = State.INIT; + private State mCurrentState = State.INIT; - /** - * True if a stop was requested while syncthing is starting, in that case, perform stop in - * {@link PollWebGuiAvailableTask}. - */ - private boolean mStopScheduled = false; + /** + * True if a stop was requested while syncthing is starting, in that case, perform stop in + * {@link PollWebGuiAvailableTask}. + */ + private boolean mStopScheduled = false; - private DeviceStateHolder mDeviceStateHolder; + private DeviceStateHolder mDeviceStateHolder; - /** + /** * Handles intents, either {@link #ACTION_RESTART}, or intents having * {@link DeviceStateHolder.EXTRA_HAS_WIFI} or {@link DeviceStateHolder.EXTRA_IS_CHARGING} * (which are handled by {@link DeviceStateHolder}. - */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - // Just catch the empty intent and return. - if (intent == null) { - } - else if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) { - new PostTask() { - @Override - protected void onPostExecute(Void aVoid) { - ConfigXml config = new ConfigXml(SyncthingService.this); - mApi = new RestApi(SyncthingService.this, - config.getWebGuiUrl(), config.getApiKey()); - mCurrentState = State.STARTING; - registerOnWebGuiAvailableListener(mApi); - new PollWebGuiAvailableTask().execute(); - } - }.execute(mApi.getUrl(), PostTask.URI_RESTART, mApi.getApiKey()); - } - else if (mCurrentState != State.INIT) { - mDeviceStateHolder.update(intent); - updateState(); - } - return START_STICKY; - } + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // Just catch the empty intent and return. + if (intent == null) { + } else if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) { + new PostTask() { + @Override + protected void onPostExecute(Void aVoid) { + ConfigXml config = new ConfigXml(SyncthingService.this); + mApi = new RestApi(SyncthingService.this, + config.getWebGuiUrl(), config.getApiKey()); + mCurrentState = State.STARTING; + registerOnWebGuiAvailableListener(mApi); + new PollWebGuiAvailableTask().execute(); + } + }.execute(mApi.getUrl(), PostTask.URI_RESTART, mApi.getApiKey()); + } else if (mCurrentState != State.INIT) { + mDeviceStateHolder.update(intent); + updateState(); + } + return START_STICKY; + } - /** - * Checks according to preferences and charging/wifi state, whether syncthing should be enabled + /** + * Checks according to preferences and charging/wifi state, whether syncthing should be enabled * or not. - * + *

* Depending on the result, syncthing is started or stopped, and {@link #onApiChange()} is * called. - */ - public void updateState() { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean prefStopMobileData = prefs.getBoolean("stop_sync_on_mobile_data", true); - boolean prefStopNotCharging = prefs.getBoolean("stop_sync_while_not_charging", true); + */ + public void updateState() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean prefStopMobileData = prefs.getBoolean("stop_sync_on_mobile_data", true); + boolean prefStopNotCharging = prefs.getBoolean("stop_sync_while_not_charging", true); - // Start syncthing. - if ((mDeviceStateHolder.isCharging() || !prefStopNotCharging) && - (mDeviceStateHolder.isWifiConnected() || !prefStopMobileData)) { - if (mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) { - mStopScheduled = false; - return; - } + // Start syncthing. + if ((mDeviceStateHolder.isCharging() || !prefStopNotCharging) && + (mDeviceStateHolder.isWifiConnected() || !prefStopMobileData)) { + if (mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) { + mStopScheduled = false; + return; + } - mCurrentState = State.STARTING; - registerOnWebGuiAvailableListener(mApi); - new PollWebGuiAvailableTask().execute(); - new Thread(new SyncthingRunnable(this)).start(); - } - // Stop syncthing. - else { - if (mCurrentState == State.DISABLED) - return; + mCurrentState = State.STARTING; + registerOnWebGuiAvailableListener(mApi); + new PollWebGuiAvailableTask().execute(); + new Thread(new SyncthingRunnable(this)).start(); + } + // Stop syncthing. + else { + if (mCurrentState == State.DISABLED) + return; - mCurrentState = State.DISABLED; + mCurrentState = State.DISABLED; - // Syncthing is currently started, perform the stop later. - if (mCurrentState == State.STARTING) { - mStopScheduled = true; - } else if (mApi != null) { - mApi.shutdown(); - } - } - onApiChange(); - } + // Syncthing is currently started, perform the stop later. + if (mCurrentState == State.STARTING) { + mStopScheduled = true; + } else if (mApi != null) { + mApi.shutdown(); + } + } + onApiChange(); + } - /** - * Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners - * in mOnWebGuiAvailableListeners and clears it. - */ - private class PollWebGuiAvailableTask extends AsyncTask { - @Override - protected Void doInBackground(Void... voids) { - int status = 0; - HttpClient httpclient = new DefaultHttpClient(); - HttpHead head = new HttpHead(mApi.getUrl()); - do { - try { - Thread.sleep(WEB_GUI_POLL_INTERVAL); - HttpResponse response = httpclient.execute(head); - // NOTE: status is not really needed, as HttpHostConnectException is thrown - // earlier. - status = response.getStatusLine().getStatusCode(); - } - catch (HttpHostConnectException e) { - // We catch this in every call, as long as the service is not online, - // so we ignore and continue. - } - catch (IOException e) { - Log.w(TAG, "Failed to poll for web interface", e); - } - catch (InterruptedException e) { - Log.w(TAG, "Failed to poll for web interface", e); - } - } while(status != HttpStatus.SC_OK); - return null; - } + /** + * Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners + * in mOnWebGuiAvailableListeners and clears it. + */ + private class PollWebGuiAvailableTask extends AsyncTask { + @Override + protected Void doInBackground(Void... voids) { + int status = 0; + HttpClient httpclient = new DefaultHttpClient(); + HttpHead head = new HttpHead(mApi.getUrl()); + do { + try { + Thread.sleep(WEB_GUI_POLL_INTERVAL); + HttpResponse response = httpclient.execute(head); + // NOTE: status is not really needed, as HttpHostConnectException is thrown + // earlier. + status = response.getStatusLine().getStatusCode(); + } catch (HttpHostConnectException e) { + // We catch this in every call, as long as the service is not online, + // so we ignore and continue. + } catch (IOException e) { + Log.w(TAG, "Failed to poll for web interface", e); + } catch (InterruptedException e) { + Log.w(TAG, "Failed to poll for web interface", e); + } + } while (status != HttpStatus.SC_OK); + return null; + } - @Override - protected void onPostExecute(Void aVoid) { - if (mStopScheduled) { - mCurrentState = State.DISABLED; - onApiChange(); - mApi.shutdown(); - mStopScheduled = false; - return; - } - Log.i(TAG, "Web GUI has come online at " + mApi.getUrl()); - mCurrentState = State.ACTIVE; - for (OnWebGuiAvailableListener listener : mOnWebGuiAvailableListeners) { - listener.onWebGuiAvailable(); - } - mOnWebGuiAvailableListeners.clear(); - } - } + @Override + protected void onPostExecute(Void aVoid) { + if (mStopScheduled) { + mCurrentState = State.DISABLED; + onApiChange(); + mApi.shutdown(); + mStopScheduled = false; + return; + } + Log.i(TAG, "Web GUI has come online at " + mApi.getUrl()); + mCurrentState = State.ACTIVE; + for (OnWebGuiAvailableListener listener : mOnWebGuiAvailableListeners) { + listener.onWebGuiAvailable(); + } + mOnWebGuiAvailableListeners.clear(); + } + } - /** - * Move config file, keys, and index files to "official" folder - * - * Intended to bring the file locations in older installs in line with - * newer versions. - */ - private void moveConfigFiles() { - FilenameFilter idxFilter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".idx.gz"); - } - }; + /** + * Move config file, keys, and index files to "official" folder + *

+ * Intended to bring the file locations in older installs in line with + * newer versions. + */ + private void moveConfigFiles() { + FilenameFilter idxFilter = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".idx.gz"); + } + }; - if (new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE).exists()) { - File publicKey = new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE); - publicKey.renameTo(new File(getFilesDir(), PUBLIC_KEY_FILE)); - File privateKey = new File(getApplicationInfo().dataDir, PRIVATE_KEY_FILE); - privateKey.renameTo(new File(getFilesDir(), PRIVATE_KEY_FILE)); - File config = new File(getApplicationInfo().dataDir, ConfigXml.CONFIG_FILE); - config.renameTo(new File(getFilesDir(), ConfigXml.CONFIG_FILE)); + if (new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE).exists()) { + File publicKey = new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE); + publicKey.renameTo(new File(getFilesDir(), PUBLIC_KEY_FILE)); + File privateKey = new File(getApplicationInfo().dataDir, PRIVATE_KEY_FILE); + privateKey.renameTo(new File(getFilesDir(), PRIVATE_KEY_FILE)); + File config = new File(getApplicationInfo().dataDir, ConfigXml.CONFIG_FILE); + config.renameTo(new File(getFilesDir(), ConfigXml.CONFIG_FILE)); - File oldStorageDir = new File(getApplicationInfo().dataDir); - File[] files = oldStorageDir.listFiles(idxFilter); - for (File file : files) { - if (file.isFile()) { - file.renameTo(new File(getFilesDir(), file.getName())); - } - } - } - } + File oldStorageDir = new File(getApplicationInfo().dataDir); + File[] files = oldStorageDir.listFiles(idxFilter); + for (File file : files) { + if (file.isFile()) { + file.renameTo(new File(getFilesDir(), file.getName())); + } + } + } + } - /** - * Creates notification, starts native binary. - */ - @Override - public void onCreate() { - PendingIntent pi = PendingIntent.getActivity( - this, 0, new Intent(this, MainActivity.class), - PendingIntent.FLAG_UPDATE_CURRENT); - Notification n = new NotificationCompat.Builder(this) - .setContentTitle(getString(R.string.app_name)) - .setSmallIcon(R.drawable.ic_launcher) - .setContentIntent(pi) - .setPriority(NotificationCompat.PRIORITY_MIN) - .build(); - n.flags |= Notification.FLAG_ONGOING_EVENT; - startForeground(NOTIFICATION_RUNNING, n); + /** + * Creates notification, starts native binary. + */ + @Override + public void onCreate() { + PendingIntent pi = PendingIntent.getActivity( + this, 0, new Intent(this, MainActivity.class), + PendingIntent.FLAG_UPDATE_CURRENT); + Notification n = new NotificationCompat.Builder(this) + .setContentTitle(getString(R.string.app_name)) + .setSmallIcon(R.drawable.ic_launcher) + .setContentIntent(pi) + .setPriority(NotificationCompat.PRIORITY_MIN) + .build(); + n.flags |= Notification.FLAG_ONGOING_EVENT; + startForeground(NOTIFICATION_RUNNING, n); mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this); registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - new StartupTask().execute(); - } + new StartupTask().execute(); + } - /** - * Sets up the initial configuration, updates the config when coming from an old - * version, and reads syncthing URL and API key (these are passed internally as - * {@code Pair}. - */ - private class StartupTask extends AsyncTask> { - @Override - protected Pair doInBackground(Void... voids) { - moveConfigFiles(); - ConfigXml config = new ConfigXml(SyncthingService.this); - config.updateIfNeeded(); + /** + * Sets up the initial configuration, updates the config when coming from an old + * version, and reads syncthing URL and API key (these are passed internally as + * {@code Pair}. + */ + private class StartupTask extends AsyncTask> { + @Override + protected Pair doInBackground(Void... voids) { + moveConfigFiles(); + ConfigXml config = new ConfigXml(SyncthingService.this); + config.updateIfNeeded(); - if (isFirstStart()) { - Log.i(TAG, "App started for the first time. " + - "Copying default config, keys will be generated automatically"); - config.createCameraRepo(); - } + if (isFirstStart()) { + Log.i(TAG, "App started for the first time. " + + "Copying default config, keys will be generated automatically"); + config.createCameraRepo(); + } - return new Pair<>(config.getWebGuiUrl(), config.getApiKey()); - } + return new Pair<>(config.getWebGuiUrl(), config.getApiKey()); + } - @Override - protected void onPostExecute(Pair urlAndKey) { - mApi = new RestApi(SyncthingService.this, urlAndKey.first, urlAndKey.second); - Log.i(TAG, "Web GUI will be available at " + mApi.getUrl()); + @Override + protected void onPostExecute(Pair urlAndKey) { + mApi = new RestApi(SyncthingService.this, urlAndKey.first, urlAndKey.second); + Log.i(TAG, "Web GUI will be available at " + mApi.getUrl()); - // HACK: Make sure there is no syncthing binary left running from an improper - // shutdown (eg Play Store updateIfNeeded). - // NOTE: This will log an exception if syncthing is not actually running. - mApi.shutdown(); + // HACK: Make sure there is no syncthing binary left running from an improper + // shutdown (eg Play Store updateIfNeeded). + // NOTE: This will log an exception if syncthing is not actually running. + mApi.shutdown(); updateState(); - } - } + } + } - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } - /** - * Stops the native binary. - */ - @Override - public void onDestroy() { - super.onDestroy(); - Log.i(TAG, "Shutting down service"); - mApi.shutdown(); - } + /** + * Stops the native binary. + */ + @Override + public void onDestroy() { + super.onDestroy(); + Log.i(TAG, "Shutting down service"); + mApi.shutdown(); + } - /** - * Register a listener for the web gui becoming available.. - * - * If the web gui is already available, listener will be called immediately. - * Listeners are unregistered automatically after being called. - */ - public void registerOnWebGuiAvailableListener(OnWebGuiAvailableListener listener) { - if (mCurrentState == State.ACTIVE) { - listener.onWebGuiAvailable(); - } - else { - mOnWebGuiAvailableListeners.add(listener); - } - } + /** + * Register a listener for the web gui becoming available.. + *

+ * If the web gui is already available, listener will be called immediately. + * Listeners are unregistered automatically after being called. + */ + public void registerOnWebGuiAvailableListener(OnWebGuiAvailableListener listener) { + if (mCurrentState == State.ACTIVE) { + listener.onWebGuiAvailable(); + } else { + mOnWebGuiAvailableListeners.add(listener); + } + } - /** - * Returns true if this service has not been started before (ie config.xml does not exist). - * - * This will return true until the public key file has been generated. - */ - public boolean isFirstStart() { - return !new File(getFilesDir(), PUBLIC_KEY_FILE).exists(); - } + /** + * Returns true if this service has not been started before (ie config.xml does not exist). + *

+ * This will return true until the public key file has been generated. + */ + public boolean isFirstStart() { + return !new File(getFilesDir(), PUBLIC_KEY_FILE).exists(); + } - public RestApi getApi() { - return mApi; - } + public RestApi getApi() { + return mApi; + } - /** - * Register a listener for the syncthing API state changing. - * - * The listener is called immediately with the current state, and again whenever the state - * changes. - */ - public void registerOnApiChangeListener(OnApiChangeListener listener) { + /** + * Register a listener for the syncthing API state changing. + *

+ * The listener is called immediately with the current state, and again whenever the state + * changes. + */ + public void registerOnApiChangeListener(OnApiChangeListener listener) { // Make sure we don't send an invalid state or syncthing might shwow a "disabled" message // when it's just starting up. - listener.onApiChange(mCurrentState); - mOnApiChangeListeners.add(new WeakReference(listener)); - } + listener.onApiChange(mCurrentState); + mOnApiChangeListeners.add(new WeakReference(listener)); + } - /** - * Called to notifiy listeners of an API change. - * + /** + * Called to notifiy listeners of an API change. + *

* Must only be called from SyncthingService or {@link RestApi}. - */ - public void onApiChange() { - for (Iterator> i = mOnApiChangeListeners.iterator(); + */ + public void onApiChange() { + for (Iterator> i = mOnApiChangeListeners.iterator(); i.hasNext(); ) { - WeakReference listener = i.next(); - if (listener.get() != null) { - listener.get().onApiChange(mCurrentState); - } - else { - i.remove(); - } - } - } + WeakReference listener = i.next(); + if (listener.get() != null) { + listener.get().onApiChange(mCurrentState); + } else { + i.remove(); + } + } + } - /** - * Dialog to be shown when attempting to start syncthing while it is disabled according - * to settings (because the device is not charging or wifi is disconnected). - */ - public static void showDisabledDialog(final Activity activity) { - new AlertDialog.Builder(activity) + /** + * Dialog to be shown when attempting to start syncthing while it is disabled according + * to settings (because the device is not charging or wifi is disconnected). + */ + public static void showDisabledDialog(final Activity activity) { + new AlertDialog.Builder(activity) .setTitle(R.string.syncthing_disabled_title) - .setMessage(R.string.syncthing_disabled_message) - .setPositiveButton(R.string.syncthing_disabled_change_settings, + .setMessage(R.string.syncthing_disabled_message) + .setPositiveButton(R.string.syncthing_disabled_change_settings, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - activity.finish(); - Intent intent = new Intent(activity, SettingsActivity.class) - .setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT); - activity.startActivity(intent); - } - }) - .setNegativeButton(R.string.exit, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - activity.finish(); - } - } - ) - .show() - .setCancelable(false); - } + @Override + public void onClick(DialogInterface dialogInterface, int i) { + activity.finish(); + Intent intent = new Intent(activity, SettingsActivity.class) + .setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT); + activity.startActivity(intent); + } + } + ) + .setNegativeButton(R.string.exit, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + activity.finish(); + } + } + ) + .show() + .setCancelable(false); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingServiceBinder.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingServiceBinder.java index b1a56224..79b280d9 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingServiceBinder.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingServiceBinder.java @@ -4,14 +4,14 @@ import android.os.Binder; public class SyncthingServiceBinder extends Binder { - private final SyncthingService mService; + private final SyncthingService mService; - public SyncthingServiceBinder(SyncthingService service) { - mService = service; - } + public SyncthingServiceBinder(SyncthingService service) { + mService = service; + } - public SyncthingService getService() { - return mService; - } + public SyncthingService getService() { + return mService; + } -} \ No newline at end of file +} diff --git a/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java b/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java index 81f34173..3f9fd604 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java @@ -28,184 +28,180 @@ import javax.xml.transform.stream.StreamResult; /** * Provides direct access to the config.xml file in the file system. - * + *

* This class should only be used if the syncthing API is not available (usually during startup). */ public class ConfigXml { - private static final String TAG = "ConfigXml"; + private static final String TAG = "ConfigXml"; - /** - * File in the config folder that contains configuration. - */ - public static final String CONFIG_FILE = "config.xml"; + /** + * File in the config folder that contains configuration. + */ + public static final String CONFIG_FILE = "config.xml"; - private File mConfigFile; + private File mConfigFile; - private Document mConfig; + private Document mConfig; - public ConfigXml(Context context) { - mConfigFile = new File(context.getFilesDir(), CONFIG_FILE); - if (!mConfigFile.exists()) { - copyDefaultConfig(context); - } - try { - DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - mConfig = db.parse(mConfigFile); - } catch (SAXException | ParserConfigurationException | IOException e) { - throw new RuntimeException("Failed to open config file", e); - } - } + public ConfigXml(Context context) { + mConfigFile = new File(context.getFilesDir(), CONFIG_FILE); + if (!mConfigFile.exists()) { + copyDefaultConfig(context); + } + try { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + mConfig = db.parse(mConfigFile); + } catch (SAXException | ParserConfigurationException | IOException e) { + throw new RuntimeException("Failed to open config file", e); + } + } - public String getWebGuiUrl() { - return "http://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent(); - } + public String getWebGuiUrl() { + return "http://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent(); + } - public String getApiKey() { - return getGuiElement().getElementsByTagName("apikey").item(0).getTextContent(); - } + public String getApiKey() { + return getGuiElement().getElementsByTagName("apikey").item(0).getTextContent(); + } - /** - * Updates the config file. - * - * Coming from 0.2.0 and earlier, globalAnnounceServer value "announce.syncthing.net:22025" is - * replaced with "194.126.249.5:22025" (as domain resolve is broken). - * - * Coming from 0.3.0 and earlier, the ignorePerms flag is set to true on every repository. - */ - @SuppressWarnings("SdCardPath") - public void updateIfNeeded() { - Log.i(TAG, "Checking for needed config updates"); - boolean changed = false; - Element options = (Element) mConfig.getDocumentElement() - .getElementsByTagName("options").item(0); - Element gui = (Element) mConfig.getDocumentElement() - .getElementsByTagName("gui").item(0); + /** + * Updates the config file. + *

+ * Coming from 0.2.0 and earlier, globalAnnounceServer value "announce.syncthing.net:22025" is + * replaced with "194.126.249.5:22025" (as domain resolve is broken). + *

+ * Coming from 0.3.0 and earlier, the ignorePerms flag is set to true on every repository. + */ + @SuppressWarnings("SdCardPath") + public void updateIfNeeded() { + Log.i(TAG, "Checking for needed config updates"); + boolean changed = false; + Element options = (Element) mConfig.getDocumentElement() + .getElementsByTagName("options").item(0); + Element gui = (Element) mConfig.getDocumentElement() + .getElementsByTagName("gui").item(0); - // Create an API key if it does not exist. - if (gui.getElementsByTagName("apikey").getLength() == 0) { - Log.i(TAG, "Initializing API key with random string"); - char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); - StringBuilder sb = new StringBuilder(); - Random random = new Random(); - for (int i = 0; i < 20; i++) { - sb.append(chars[random.nextInt(chars.length)]); - } - Element apiKey = mConfig.createElement("apikey"); - apiKey.setTextContent(sb.toString()); - gui.appendChild(apiKey); - changed = true; - } + // Create an API key if it does not exist. + if (gui.getElementsByTagName("apikey").getLength() == 0) { + Log.i(TAG, "Initializing API key with random string"); + char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 20; i++) { + sb.append(chars[random.nextInt(chars.length)]); + } + Element apiKey = mConfig.createElement("apikey"); + apiKey.setTextContent(sb.toString()); + gui.appendChild(apiKey); + changed = true; + } - // Hardcode default globalAnnounceServer ip. - Element globalAnnounceServer = (Element) - options.getElementsByTagName("globalAnnounceServer").item(0); - if (globalAnnounceServer.getTextContent().equals("announce.syncthing.net:22025")) { - Log.i(TAG, "Replacing globalAnnounceServer host with ip"); - globalAnnounceServer.setTextContent("194.126.249.5:22025"); - changed = true; - } + // Hardcode default globalAnnounceServer ip. + Element globalAnnounceServer = (Element) + options.getElementsByTagName("globalAnnounceServer").item(0); + if (globalAnnounceServer.getTextContent().equals("announce.syncthing.net:22025")) { + Log.i(TAG, "Replacing globalAnnounceServer host with ip"); + globalAnnounceServer.setTextContent("194.126.249.5:22025"); + changed = true; + } - NodeList repos = mConfig.getDocumentElement().getElementsByTagName("repository"); - for (int i = 0; i < repos.getLength(); i++) { - Element r = (Element) repos.item(i); - // Set ignorePerms attribute. - if (!r.hasAttribute("ignorePerms") || - !Boolean.parseBoolean(r.getAttribute("ignorePerms"))) { - Log.i(TAG, "Set 'ignorePerms' on repository " + r.getAttribute("id")); - r.setAttribute("ignorePerms", Boolean.toString(true)); - changed = true; - } + NodeList repos = mConfig.getDocumentElement().getElementsByTagName("repository"); + for (int i = 0; i < repos.getLength(); i++) { + Element r = (Element) repos.item(i); + // Set ignorePerms attribute. + if (!r.hasAttribute("ignorePerms") || + !Boolean.parseBoolean(r.getAttribute("ignorePerms"))) { + Log.i(TAG, "Set 'ignorePerms' on repository " + r.getAttribute("id")); + r.setAttribute("ignorePerms", Boolean.toString(true)); + changed = true; + } - // Replace /sdcard/ in repository path with proper path. - String dir = r.getAttribute("directory"); - if (dir.startsWith("/sdcard")) { - String newDir = dir.replace("/sdcard", - Environment.getExternalStorageDirectory().getAbsolutePath()); - r.setAttribute("directory", newDir); - changed = true; - } - } + // Replace /sdcard/ in repository path with proper path. + String dir = r.getAttribute("directory"); + if (dir.startsWith("/sdcard")) { + String newDir = dir.replace("/sdcard", + Environment.getExternalStorageDirectory().getAbsolutePath()); + r.setAttribute("directory", newDir); + changed = true; + } + } - // Change global announce server port to 22026 for syncthing v0.9.0. - if (globalAnnounceServer.getTextContent().equals("194.126.249.5:22025")) { - Log.i(TAG, "Changing announce server port for v0.9.0"); - globalAnnounceServer.setTextContent("194.126.249.5:22026"); - changed = true; - } + // Change global announce server port to 22026 for syncthing v0.9.0. + if (globalAnnounceServer.getTextContent().equals("194.126.249.5:22025")) { + Log.i(TAG, "Changing announce server port for v0.9.0"); + globalAnnounceServer.setTextContent("194.126.249.5:22026"); + changed = true; + } - if (changed) { - saveChanges(); - } - } + if (changed) { + saveChanges(); + } + } - private Element getGuiElement() { - return (Element) mConfig.getDocumentElement() - .getElementsByTagName("gui").item(0); - } + private Element getGuiElement() { + return (Element) mConfig.getDocumentElement() + .getElementsByTagName("gui").item(0); + } - /** - * Creates a repository for the default camera folder. - */ - public void createCameraRepo() { - File cameraFolder = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); + /** + * Creates a repository for the default camera folder. + */ + public void createCameraRepo() { + File cameraFolder = + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); - Element cameraRepo = mConfig.createElement("repository"); - cameraRepo.setAttribute("id", "camera"); - cameraRepo.setAttribute("directory", cameraFolder.getAbsolutePath()); - cameraRepo.setAttribute("ro", "true"); - cameraRepo.setAttribute("ignorePerms", "true"); - mConfig.getDocumentElement().appendChild(cameraRepo); + Element cameraRepo = mConfig.createElement("repository"); + cameraRepo.setAttribute("id", "camera"); + cameraRepo.setAttribute("directory", cameraFolder.getAbsolutePath()); + cameraRepo.setAttribute("ro", "true"); + cameraRepo.setAttribute("ignorePerms", "true"); + mConfig.getDocumentElement().appendChild(cameraRepo); - saveChanges(); - } + saveChanges(); + } - /** - * Writes updated mConfig back to file. - */ - private void saveChanges() { - try { - Log.i(TAG, "Writing updated config back to file"); - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - DOMSource domSource = new DOMSource(mConfig); - StreamResult streamResult = new StreamResult(mConfigFile); - transformer.transform(domSource, streamResult); - } - catch (TransformerException e) { - Log.w(TAG, "Failed to save updated config", e); - } - } + /** + * Writes updated mConfig back to file. + */ + private void saveChanges() { + try { + Log.i(TAG, "Writing updated config back to file"); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource domSource = new DOMSource(mConfig); + StreamResult streamResult = new StreamResult(mConfigFile); + transformer.transform(domSource, streamResult); + } catch (TransformerException e) { + Log.w(TAG, "Failed to save updated config", e); + } + } - /** - * Copies the default config file from res/raw/config_default.xml to (data folder)/config.xml. - */ - private void copyDefaultConfig(Context context) { - InputStream in = null; - FileOutputStream out = null; - try { - in = context.getResources().openRawResource(R.raw.config_default); - out = new FileOutputStream(mConfigFile); - byte[] buff = new byte[1024]; - int read; + /** + * Copies the default config file from res/raw/config_default.xml to (data folder)/config.xml. + */ + private void copyDefaultConfig(Context context) { + InputStream in = null; + FileOutputStream out = null; + try { + in = context.getResources().openRawResource(R.raw.config_default); + out = new FileOutputStream(mConfigFile); + byte[] buff = new byte[1024]; + int read; - while ((read = in.read(buff)) > 0) { - out.write(buff, 0, read); - } - } - catch (IOException e) { - throw new RuntimeException("Failed to write config file", e); - } - finally { - try { - in.close(); - out.close(); - } - catch (IOException e) { - Log.w(TAG, "Failed to close stream while copying config", e); - } - } - } + while ((read = in.read(buff)) > 0) { + out.write(buff, 0, read); + } + } catch (IOException e) { + throw new RuntimeException("Failed to write config file", e); + } finally { + try { + in.close(); + out.close(); + } catch (IOException e) { + Log.w(TAG, "Failed to close stream while copying config", e); + } + } + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/util/ExtendedCheckBoxPreference.java b/src/main/java/com/nutomic/syncthingandroid/util/ExtendedCheckBoxPreference.java index 3ef31c1b..d99cd5d2 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/ExtendedCheckBoxPreference.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/ExtendedCheckBoxPreference.java @@ -8,15 +8,15 @@ import android.preference.CheckBoxPreference; */ public class ExtendedCheckBoxPreference extends CheckBoxPreference { - private final Object mObject; + private final Object mObject; - public ExtendedCheckBoxPreference(Context context, Object object) { - super(context); - mObject = object; - } + public ExtendedCheckBoxPreference(Context context, Object object) { + super(context); + mObject = object; + } - public Object getObject() { - return mObject; - } + public Object getObject() { + return mObject; + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/util/NodesAdapter.java b/src/main/java/com/nutomic/syncthingandroid/util/NodesAdapter.java index bc05c397..5e57879f 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/NodesAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/NodesAdapter.java @@ -20,79 +20,77 @@ import java.util.Map; * Generates item views for node items. */ public class NodesAdapter extends ArrayAdapter - implements RestApi.OnReceiveConnectionsListener { + implements RestApi.OnReceiveConnectionsListener { - private Map mConnections = - new HashMap<>(); + private Map mConnections = + new HashMap<>(); - public NodesAdapter(Context context) { - super(context, R.layout.node_list_item); - } + public NodesAdapter(Context context) { + super(context, R.layout.node_list_item); + } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - convertView = inflater.inflate(R.layout.node_list_item, parent, false); - } + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + LayoutInflater inflater = (LayoutInflater) getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.node_list_item, parent, false); + } - TextView name = (TextView) convertView.findViewById(R.id.name); - TextView status = (TextView) convertView.findViewById(R.id.status); - TextView download = (TextView) convertView.findViewById(R.id.download); - TextView upload = (TextView) convertView.findViewById(R.id.upload); + TextView name = (TextView) convertView.findViewById(R.id.name); + TextView status = (TextView) convertView.findViewById(R.id.status); + TextView download = (TextView) convertView.findViewById(R.id.download); + TextView upload = (TextView) convertView.findViewById(R.id.upload); - name.setText(getItem(position).Name); - final String nodeId = getItem(position).NodeID; + name.setText(getItem(position).Name); + final String nodeId = getItem(position).NodeID; - RestApi.Connection conn = mConnections.get(nodeId); - Resources res = getContext().getResources(); - if (conn != null) { - if (conn.Completion == 100) { - status.setText(res.getString(R.string.node_up_to_date)); - status.setTextColor(res.getColor(R.color.text_green)); - } - else { - status.setText(res.getString(R.string.node_syncing, conn.Completion)); - status.setTextColor(res.getColor(R.color.text_blue)); - } - download.setText(RestApi.readableTransferRate(getContext(), conn.InBits)); - upload.setText(RestApi.readableTransferRate(getContext(), conn.OutBits)); - } - else { - download.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]); - upload.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]); - status.setText(res.getString(R.string.node_disconnected)); - status.setTextColor(res.getColor(R.color.text_red)); - } + RestApi.Connection conn = mConnections.get(nodeId); + Resources res = getContext().getResources(); + if (conn != null) { + if (conn.Completion == 100) { + status.setText(res.getString(R.string.node_up_to_date)); + status.setTextColor(res.getColor(R.color.text_green)); + } else { + status.setText(res.getString(R.string.node_syncing, conn.Completion)); + status.setTextColor(res.getColor(R.color.text_blue)); + } + download.setText(RestApi.readableTransferRate(getContext(), conn.InBits)); + upload.setText(RestApi.readableTransferRate(getContext(), conn.OutBits)); + } else { + download.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]); + upload.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]); + status.setText(res.getString(R.string.node_disconnected)); + status.setTextColor(res.getColor(R.color.text_red)); + } - return convertView; - } + return convertView; + } - /** - * Replacement for addAll, which is not implemented on lower API levels. - */ - public void add(List nodes) { - for (RestApi.Node n : nodes) { - add(n); - } - } + /** + * Replacement for addAll, which is not implemented on lower API levels. + */ + public void add(List nodes) { + for (RestApi.Node n : nodes) { + add(n); + } + } - /** - * Requests new connection info for all nodes visible in listView. - */ - public void updateConnections(RestApi api, ListView listView) { - for (int i = 0; i < getCount(); i++) { - if ( i >= listView.getFirstVisiblePosition() && - i <= listView.getLastVisiblePosition()) { - api.getConnections(this); - } - } - } + /** + * Requests new connection info for all nodes visible in listView. + */ + public void updateConnections(RestApi api, ListView listView) { + for (int i = 0; i < getCount(); i++) { + if (i >= listView.getFirstVisiblePosition() && + i <= listView.getLastVisiblePosition()) { + api.getConnections(this); + } + } + } - @Override - public void onReceiveConnections(Map connections) { - mConnections = connections; - notifyDataSetInvalidated(); - } + @Override + public void onReceiveConnections(Map connections) { + mConnections = connections; + notifyDataSetInvalidated(); + } } diff --git a/src/main/java/com/nutomic/syncthingandroid/util/ReposAdapter.java b/src/main/java/com/nutomic/syncthingandroid/util/ReposAdapter.java index e8347a77..23b82e03 100644 --- a/src/main/java/com/nutomic/syncthingandroid/util/ReposAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/util/ReposAdapter.java @@ -18,77 +18,77 @@ import java.util.List; * Generates item views for repository items. */ public class ReposAdapter extends ArrayAdapter - implements RestApi.OnReceiveModelListener { + implements RestApi.OnReceiveModelListener { - private HashMap mModels = new HashMap<>(); + private HashMap mModels = new HashMap<>(); - public ReposAdapter(Context context) { - super(context, R.layout.repo_list_item); - } + public ReposAdapter(Context context) { + super(context, R.layout.repo_list_item); + } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - convertView = inflater.inflate(R.layout.repo_list_item, parent, false); - } + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + LayoutInflater inflater = (LayoutInflater) getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.repo_list_item, parent, false); + } - TextView id = (TextView) convertView.findViewById(R.id.id); + TextView id = (TextView) convertView.findViewById(R.id.id); - TextView state = (TextView) convertView.findViewById(R.id.state); - TextView folder = (TextView) convertView.findViewById(R.id.folder); - TextView items = (TextView) convertView.findViewById(R.id.items); - TextView size = (TextView) convertView.findViewById(R.id.size); - TextView invalid = (TextView) convertView.findViewById(R.id.invalid); + TextView state = (TextView) convertView.findViewById(R.id.state); + TextView folder = (TextView) convertView.findViewById(R.id.folder); + TextView items = (TextView) convertView.findViewById(R.id.items); + TextView size = (TextView) convertView.findViewById(R.id.size); + TextView invalid = (TextView) convertView.findViewById(R.id.invalid); - id.setText(getItem(position).ID); - state.setTextColor(getContext().getResources().getColor(R.color.text_green)); - folder.setText((getItem(position).Directory)); - RestApi.Model model = mModels.get(getItem(position).ID); - if (model != null) { - state.setText(getContext().getString(R.string.repo_progress_format, model.state, - (model.globalBytes <= 0) - ? 100 - : (int) ((model.localBytes / (float) model.globalBytes) * 100))); - items.setText(getContext() - .getString(R.string.files, model.localFiles, model.globalFiles)); - size.setText(RestApi.readableFileSize(getContext(), model.localBytes) + " / " + - RestApi.readableFileSize(getContext(), model.globalBytes)); - invalid.setText(model.invalid); - invalid.setVisibility((model.invalid.equals("")) ? View.GONE : View.VISIBLE); - } - else { - invalid.setVisibility(View.GONE); - } + id.setText(getItem(position).ID); + state.setTextColor(getContext().getResources().getColor(R.color.text_green)); + folder.setText((getItem(position).Directory)); + RestApi.Model model = mModels.get(getItem(position).ID); + if (model != null) { + state.setText(getContext().getString(R.string.repo_progress_format, model.state, + (model.globalBytes <= 0) + ? 100 + : (int) ((model.localBytes / (float) model.globalBytes) * 100) + )); + items.setText(getContext() + .getString(R.string.files, model.localFiles, model.globalFiles)); + size.setText(RestApi.readableFileSize(getContext(), model.localBytes) + " / " + + RestApi.readableFileSize(getContext(), model.globalBytes)); + invalid.setText(model.invalid); + invalid.setVisibility((model.invalid.equals("")) ? View.GONE : View.VISIBLE); + } else { + invalid.setVisibility(View.GONE); + } - return convertView; - } + return convertView; + } - /** - * Replacement for addAll, which is not implemented on lower API levels. - */ - public void add(List nodes) { - for (RestApi.Repo r : nodes) { - add(r); - } - } + /** + * Replacement for addAll, which is not implemented on lower API levels. + */ + public void add(List nodes) { + for (RestApi.Repo r : nodes) { + add(r); + } + } - /** - * Requests updated model info from the api for all visible items. - */ - public void updateModel(RestApi api, ListView listView) { - for (int i = 0; i < getCount(); i++) { - if ( i >= listView.getFirstVisiblePosition() && - i <= listView.getLastVisiblePosition()) { - api.getModel(getItem(i).ID, this); - } - } - } + /** + * Requests updated model info from the api for all visible items. + */ + public void updateModel(RestApi api, ListView listView) { + for (int i = 0; i < getCount(); i++) { + if (i >= listView.getFirstVisiblePosition() && + i <= listView.getLastVisiblePosition()) { + api.getModel(getItem(i).ID, this); + } + } + } - @Override - public void onReceiveModel(String repoId, RestApi.Model model) { - mModels.put(repoId, model); - notifyDataSetChanged(); - } + @Override + public void onReceiveModel(String repoId, RestApi.Model model) { + mModels.put(repoId, model); + notifyDataSetChanged(); + } } diff --git a/src/main/res/layout/folder_picker_activity.xml b/src/main/res/layout/folder_picker_activity.xml index 83c003de..43ad82b3 100644 --- a/src/main/res/layout/folder_picker_activity.xml +++ b/src/main/res/layout/folder_picker_activity.xml @@ -1,17 +1,17 @@ + android:layout_width="match_parent" + android:layout_height="match_parent"> - + - + diff --git a/src/main/res/layout/loading_dialog.xml b/src/main/res/layout/loading_dialog.xml index 91dcc3ed..40a535e1 100644 --- a/src/main/res/layout/loading_dialog.xml +++ b/src/main/res/layout/loading_dialog.xml @@ -1,24 +1,24 @@ + android:layout_gravity="center" + android:padding="10dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> - + - + - \ No newline at end of file + diff --git a/src/main/res/layout/local_node_info_fragment.xml b/src/main/res/layout/local_node_info_fragment.xml index 33f679a8..03f3226a 100644 --- a/src/main/res/layout/local_node_info_fragment.xml +++ b/src/main/res/layout/local_node_info_fragment.xml @@ -1,117 +1,123 @@ + android:orientation="vertical" + android:padding="10dip" + android:layout_width="match_parent" + android:layout_height="match_parent"> - - + - - + - - + + - - + - - + - - + + - - + - - + - - + + - - + - - + - - + + - \ No newline at end of file + + + + + + + + + + + + + + + diff --git a/src/main/res/layout/main_activity.xml b/src/main/res/layout/main_activity.xml index 1ac9878d..20af07a8 100644 --- a/src/main/res/layout/main_activity.xml +++ b/src/main/res/layout/main_activity.xml @@ -1,23 +1,22 @@ - + - + - + - \ No newline at end of file + diff --git a/src/main/res/layout/node_list_item.xml b/src/main/res/layout/node_list_item.xml index b1ea566b..bbd84eb3 100644 --- a/src/main/res/layout/node_list_item.xml +++ b/src/main/res/layout/node_list_item.xml @@ -1,59 +1,59 @@ + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="4dip"> - + - + - + - + - + - + + >>>>>>> Changed code style to use spaces instead of tabs. diff --git a/src/main/res/layout/repo_list_item.xml b/src/main/res/layout/repo_list_item.xml index 069e6e0e..6b57d0d3 100644 --- a/src/main/res/layout/repo_list_item.xml +++ b/src/main/res/layout/repo_list_item.xml @@ -1,55 +1,55 @@ + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="4dip"> - + - + - + - + - + - + diff --git a/src/main/res/layout/scan_qr_code_widget.xml b/src/main/res/layout/scan_qr_code_widget.xml index ab875919..5412c17a 100644 --- a/src/main/res/layout/scan_qr_code_widget.xml +++ b/src/main/res/layout/scan_qr_code_widget.xml @@ -1,8 +1,8 @@ + android:layout_width="48dip" + android:layout_height="48dip" + android:src="@drawable/ic_qrcode" + android:onClick="onClick" + android:contentDescription="@string/scan_qr_code_description" /> diff --git a/src/main/res/layout/web_gui_activity.xml b/src/main/res/layout/web_gui_activity.xml index 02c6d93c..e2db67b3 100644 --- a/src/main/res/layout/web_gui_activity.xml +++ b/src/main/res/layout/web_gui_activity.xml @@ -1,37 +1,36 @@ - + - + - + - + - + - + diff --git a/src/main/res/menu/folder_picker.xml b/src/main/res/menu/folder_picker.xml index 7d1a044c..11f0941c 100644 --- a/src/main/res/menu/folder_picker.xml +++ b/src/main/res/menu/folder_picker.xml @@ -1,17 +1,16 @@ -

+ - + - + diff --git a/src/main/res/menu/main.xml b/src/main/res/menu/main.xml index 028cfe46..a5c00729 100644 --- a/src/main/res/menu/main.xml +++ b/src/main/res/menu/main.xml @@ -1,32 +1,31 @@ - + - + - + - + - + - + diff --git a/src/main/res/menu/node_settings.xml b/src/main/res/menu/node_settings.xml index 95adce26..908ef729 100644 --- a/src/main/res/menu/node_settings.xml +++ b/src/main/res/menu/node_settings.xml @@ -1,23 +1,23 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - + - + - + diff --git a/src/main/res/menu/repo_settings.xml b/src/main/res/menu/repo_settings.xml index 2162c78e..85f0207a 100644 --- a/src/main/res/menu/repo_settings.xml +++ b/src/main/res/menu/repo_settings.xml @@ -1,17 +1,17 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - + - + diff --git a/src/main/res/raw/config_default.xml b/src/main/res/raw/config_default.xml index 6378302f..7f549f51 100644 --- a/src/main/res/raw/config_default.xml +++ b/src/main/res/raw/config_default.xml @@ -1,18 +1,18 @@ - -
127.0.0.1:8080
-
- - 0.0.0.0:22000 - 194.126.249.5:22026 - true - true - 16 - 0 - 60 - 60 - 1000 - false - true - + +
127.0.0.1:8080
+
+ + 0.0.0.0:22000 + 194.126.249.5:22026 + true + true + 16 + 0 + 60 + 60 + 1000 + false + true +
diff --git a/src/main/res/values-v11/style.xml b/src/main/res/values-v11/style.xml index 6b9e50dc..6ff94782 100644 --- a/src/main/res/values-v11/style.xml +++ b/src/main/res/values-v11/style.xml @@ -1,4 +1,5 @@ -