mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-12-23 11:21:29 +00:00
Changed code style to use spaces instead of tabs.
It is impossible to add a custom code style in Android Studio that is stored in the project repository. So change style to something that's easy to use in practice now rather than later.
This commit is contained in:
parent
c3b027e8b5
commit
b1749ce7cb
49 changed files with 3611 additions and 3668 deletions
|
@ -41,6 +41,6 @@ screenshots: *link to file* (only for UI problems)
|
||||||
|
|
||||||
Always welcome.
|
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.
|
Lint warnings should be fixed. If that's not possible, they should be ignored as specifically as possible.
|
||||||
|
|
190
build.gradle
190
build.gradle
|
@ -1,12 +1,12 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:0.12.+'
|
classpath 'com.android.tools.build:gradle:0.12.+'
|
||||||
classpath 'com.alexvasilkov:android_sign:0.2+'
|
classpath 'com.alexvasilkov:android_sign:0.2+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
@ -15,126 +15,126 @@ apply plugin: 'com.android.application'
|
||||||
apply plugin: 'android_sign'
|
apply plugin: 'android_sign'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:appcompat-v7:19.1.+'
|
compile 'com.android.support:appcompat-v7:19.1.+'
|
||||||
compile project(':android-support-v4-preferencefragment')
|
compile project(':android-support-v4-preferencefragment')
|
||||||
}
|
}
|
||||||
|
|
||||||
preBuild {
|
preBuild {
|
||||||
dependsOn 'buildNative'
|
dependsOn 'buildNative'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 19
|
compileSdkVersion 19
|
||||||
buildToolsVersion "19.1.0"
|
buildToolsVersion "19.1.0"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode getVersionCodeFromManifest()
|
versionCode getVersionCodeFromManifest()
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
jniLibs.srcDir file("libs/")
|
jniLibs.srcDir file("libs/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
release {
|
release {
|
||||||
// Android Studio does not pass environment variables.
|
// Android Studio does not pass environment variables.
|
||||||
// This means you have to use the command line for release builds.
|
// This means you have to use the command line for release builds.
|
||||||
def ks = System.getenv("KEYSTORE")
|
def ks = System.getenv("KEYSTORE")
|
||||||
def ka = System.getenv("KEY_ALIAS")
|
def ka = System.getenv("KEY_ALIAS")
|
||||||
if (ks != null && ka != null) {
|
if (ks != null && ka != null) {
|
||||||
storeFile file(ks)
|
storeFile file(ks)
|
||||||
keyAlias ka
|
keyAlias ka
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
debuggable true
|
debuggable true
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
x86 {
|
x86 {
|
||||||
versionCode Integer.parseInt("4" + defaultConfig.versionCode)
|
versionCode Integer.parseInt("4" + defaultConfig.versionCode)
|
||||||
ndk {
|
ndk {
|
||||||
abiFilter "x86"
|
abiFilter "x86"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
armeabi_v7a {
|
armeabi_v7a {
|
||||||
versionCode Integer.parseInt("3" + defaultConfig.versionCode)
|
versionCode Integer.parseInt("3" + defaultConfig.versionCode)
|
||||||
ndk {
|
ndk {
|
||||||
abiFilter "armeabi-v7a"
|
abiFilter "armeabi-v7a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
armeabi {
|
armeabi {
|
||||||
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
|
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
|
||||||
ndk {
|
ndk {
|
||||||
abiFilter "armeabi"
|
abiFilter "armeabi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mips {
|
mips {
|
||||||
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
|
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
|
||||||
ndk {
|
ndk {
|
||||||
abiFilter "mips"
|
abiFilter "mips"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fat {
|
fat {
|
||||||
versionCode Integer.parseInt("0" + defaultConfig.versionCode)
|
versionCode Integer.parseInt("0" + defaultConfig.versionCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVersionCodeFromManifest() {
|
def getVersionCodeFromManifest() {
|
||||||
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
|
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
|
||||||
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
|
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
|
||||||
def matcher = pattern.matcher(manifestFile.getText())
|
def matcher = pattern.matcher(manifestFile.getText())
|
||||||
matcher.find()
|
matcher.find()
|
||||||
return Integer.parseInt(matcher.group(1))
|
return Integer.parseInt(matcher.group(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildNative(type: Exec) {
|
task buildNative(type: Exec) {
|
||||||
outputs.upToDateWhen { false }
|
outputs.upToDateWhen { false }
|
||||||
executable = './build-syncthing.sh'
|
executable = './build-syncthing.sh'
|
||||||
}
|
}
|
||||||
|
|
||||||
task copyNative(type: Copy) {
|
task copyNative(type: Copy) {
|
||||||
def lib_dir = "libs/"
|
def lib_dir = "libs/"
|
||||||
new File(lib_dir).mkdirs()
|
new File(lib_dir).mkdirs()
|
||||||
def st_dir = "bin/";
|
def st_dir = "bin/";
|
||||||
from st_dir + 'syncthing-x86', st_dir + 'syncthing-armeabi', st_dir + 'syncthing-armeabi-v7a';
|
from st_dir + 'syncthing-x86', st_dir + 'syncthing-armeabi', st_dir + 'syncthing-armeabi-v7a';
|
||||||
into lib_dir
|
into lib_dir
|
||||||
rename('syncthing-x86', 'x86/libsyncthing.so')
|
rename('syncthing-x86', 'x86/libsyncthing.so')
|
||||||
rename('syncthing-armeabi-v7a', 'armeabi-v7a/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
|
buildNative.finalizedBy copyNative
|
||||||
|
|
||||||
task cleanBin(type: Delete) {
|
task cleanBin(type: Delete) {
|
||||||
delete 'bin/'
|
delete 'bin/'
|
||||||
}
|
}
|
||||||
copyNative.finalizedBy cleanBin
|
copyNative.finalizedBy cleanBin
|
||||||
|
|
||||||
task cleanNative(type: Delete) {
|
task cleanNative(type: Delete) {
|
||||||
delete 'bin/'
|
delete 'bin/'
|
||||||
delete 'build/'
|
delete 'build/'
|
||||||
delete 'libs/'
|
delete 'libs/'
|
||||||
delete 'ext/syncthing/bin/'
|
delete 'ext/syncthing/bin/'
|
||||||
delete 'ext/syncthing/pkg/'
|
delete 'ext/syncthing/pkg/'
|
||||||
}
|
}
|
||||||
clean.dependsOn cleanNative
|
clean.dependsOn cleanNative
|
||||||
|
|
||||||
|
|
|
@ -1,75 +1,75 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.nutomic.syncthingandroid"
|
package="com.nutomic.syncthingandroid"
|
||||||
android:versionCode="33"
|
android:versionCode="33"
|
||||||
android:versionName="0.4.19"
|
android:versionName="0.4.19"
|
||||||
tools:ignore="GradleOverrides" >
|
tools:ignore="GradleOverrides" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="8"
|
android:minSdkVersion="8"
|
||||||
android:targetSdkVersion="19" />
|
android:targetSdkVersion="19" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme" >
|
android:theme="@style/AppTheme">
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.WebGuiActivity"
|
android:name=".activities.WebGuiActivity"
|
||||||
android:label="@string/web_gui_title" >
|
android:label="@string/web_gui_title">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".gui.MainActivity" />
|
android:value=".gui.MainActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity android:name=".activities.SettingsActivity">
|
||||||
android:name=".activities.SettingsActivity" >
|
<meta-data
|
||||||
<meta-data
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:value=".gui.MainActivity" />
|
||||||
android:value=".gui.MainActivity" />
|
</activity>
|
||||||
</activity>
|
|
||||||
|
|
||||||
<service android:name=".syncthing.SyncthingService" />
|
<service android:name=".syncthing.SyncthingService" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.FolderPickerActivity"
|
android:name=".activities.FolderPickerActivity"
|
||||||
android:label="@string/folder_picker_title" >
|
android:label="@string/folder_picker_title">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.UI_OPTIONS"
|
android:name="android.support.UI_OPTIONS"
|
||||||
android:value="splitActionBarWhenNarrow" />
|
android:value="splitActionBarWhenNarrow" />
|
||||||
</activity>
|
</activity>
|
||||||
<receiver android:name=".syncthing.NetworkReceiver" >
|
|
||||||
<intent-filter>
|
<receiver android:name=".syncthing.NetworkReceiver">
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
<intent-filter>
|
||||||
</intent-filter>
|
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||||
</receiver>
|
</intent-filter>
|
||||||
<receiver android:name=".syncthing.BatteryReceiver" >
|
</receiver>
|
||||||
<intent-filter>
|
<receiver android:name=".syncthing.BatteryReceiver">
|
||||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
|
||||||
</intent-filter>
|
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
|
||||||
</receiver>
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<receiver android:name=".syncthing.BootReceiver">
|
<receiver android:name=".syncthing.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -32,42 +32,42 @@ import java.util.Arrays;
|
||||||
* Activity that allows selecting a directory in the local file system.
|
* Activity that allows selecting a directory in the local file system.
|
||||||
*/
|
*/
|
||||||
public class FolderPickerActivity extends SyncthingActivity
|
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) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
setContentView(R.layout.folder_picker_activity);
|
setContentView(R.layout.folder_picker_activity);
|
||||||
mListView = (ListView) findViewById(android.R.id.list);
|
mListView = (ListView) findViewById(android.R.id.list);
|
||||||
mListView.setOnItemClickListener(this);
|
mListView.setOnItemClickListener(this);
|
||||||
mListView.setEmptyView(findViewById(android.R.id.empty));
|
mListView.setEmptyView(findViewById(android.R.id.empty));
|
||||||
mAdapter = new FileAdapter(this);
|
mAdapter = new FileAdapter(this);
|
||||||
mListView.setAdapter(mAdapter);
|
mListView.setAdapter(mAdapter);
|
||||||
|
|
||||||
mLocation = new File(getIntent().getStringExtra(EXTRA_INITIAL_DIRECTORY));
|
mLocation = new File(getIntent().getStringExtra(EXTRA_INITIAL_DIRECTORY));
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||||
super.onServiceConnected(componentName, iBinder);
|
super.onServiceConnected(componentName, iBinder);
|
||||||
getService().registerOnApiChangeListener(this);
|
getService().registerOnApiChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
@ -78,116 +78,116 @@ public class FolderPickerActivity extends SyncthingActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.create_folder:
|
case R.id.create_folder:
|
||||||
final EditText et = new EditText(this);
|
final EditText et = new EditText(this);
|
||||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.create_folder)
|
.setTitle(R.string.create_folder)
|
||||||
.setView(et)
|
.setView(et)
|
||||||
.setPositiveButton(android.R.string.ok,
|
.setPositiveButton(android.R.string.ok,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
createFolder(et.getText().toString());
|
createFolder(et.getText().toString());
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
)
|
||||||
.create();
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
.create();
|
||||||
@Override
|
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||||
public void onShow(DialogInterface dialogInterface) {
|
@Override
|
||||||
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
|
public void onShow(DialogInterface dialogInterface) {
|
||||||
.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT);
|
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
|
||||||
}
|
.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT);
|
||||||
});
|
}
|
||||||
dialog.show();
|
});
|
||||||
return true;
|
dialog.show();
|
||||||
case R.id.select:
|
return true;
|
||||||
Intent intent = new Intent()
|
case R.id.select:
|
||||||
.putExtra(EXTRA_RESULT_DIRECTORY, mLocation.getAbsolutePath());
|
Intent intent = new Intent()
|
||||||
setResult(Activity.RESULT_OK, intent);
|
.putExtra(EXTRA_RESULT_DIRECTORY, mLocation.getAbsolutePath());
|
||||||
finish();
|
setResult(Activity.RESULT_OK, intent);
|
||||||
return true;
|
finish();
|
||||||
case android.R.id.home:
|
return true;
|
||||||
finish();
|
case android.R.id.home:
|
||||||
return true;
|
finish();
|
||||||
default:
|
return true;
|
||||||
return super.onOptionsItemSelected(item);
|
default:
|
||||||
}
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new folder with the given name and enters it.
|
* Creates a new folder with the given name and enters it.
|
||||||
*/
|
*/
|
||||||
private void createFolder(String name) {
|
private void createFolder(String name) {
|
||||||
File newFolder = new File(mLocation, name);
|
File newFolder = new File(mLocation, name);
|
||||||
newFolder.mkdir();
|
newFolder.mkdir();
|
||||||
mLocation = newFolder;
|
mLocation = newFolder;
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the ListView to show the contents of the folder in {@code }mLocation.peek()}.
|
* Refreshes the ListView to show the contents of the folder in {@code }mLocation.peek()}.
|
||||||
*/
|
*/
|
||||||
private void refresh() {
|
private void refresh() {
|
||||||
mAdapter.clear();
|
mAdapter.clear();
|
||||||
File[] contents = mLocation.listFiles(new FileFilter() {
|
File[] contents = mLocation.listFiles(new FileFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File file) {
|
public boolean accept(File file) {
|
||||||
return file.isDirectory();
|
return file.isDirectory();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Arrays.sort(contents);
|
Arrays.sort(contents);
|
||||||
for (File f : contents) {
|
for (File f : contents) {
|
||||||
mAdapter.add(f);
|
mAdapter.add(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
mLocation = mAdapter.getItem(i);
|
mLocation = mAdapter.getItem(i);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FileAdapter extends ArrayAdapter<File> {
|
private class FileAdapter extends ArrayAdapter<File> {
|
||||||
|
|
||||||
public FileAdapter(Context context) {
|
public FileAdapter(Context context) {
|
||||||
super(context, android.R.layout.simple_list_item_1);
|
super(context, android.R.layout.simple_list_item_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
LayoutInflater inflater = (LayoutInflater) getContext()
|
LayoutInflater inflater = (LayoutInflater) getContext()
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
|
convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView title = (TextView) convertView.findViewById(android.R.id.text1);
|
TextView title = (TextView) convertView.findViewById(android.R.id.text1);
|
||||||
title.setText(getItem(position).getName());
|
title.setText(getItem(position).getName());
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if (!mLocation.equals(Environment.getExternalStorageDirectory())) {
|
if (!mLocation.equals(Environment.getExternalStorageDirectory())) {
|
||||||
mLocation = mLocation.getParentFile();
|
mLocation = mLocation.getParentFile();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
} else {
|
||||||
else {
|
setResult(Activity.RESULT_CANCELED);
|
||||||
setResult(Activity.RESULT_CANCELED);
|
finish();
|
||||||
finish();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE) {
|
if (currentState != SyncthingService.State.ACTIVE) {
|
||||||
setResult(Activity.RESULT_CANCELED);
|
setResult(Activity.RESULT_CANCELED);
|
||||||
SyncthingService.showDisabledDialog(this);
|
SyncthingService.showDisabledDialog(this);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,253 +37,254 @@ import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||||
* {@link com.nutomic.syncthingandroid.fragments.LocalNodeInfoFragment} in the navigation drawer.
|
* {@link com.nutomic.syncthingandroid.fragments.LocalNodeInfoFragment} in the navigation drawer.
|
||||||
*/
|
*/
|
||||||
public class MainActivity extends SyncthingActivity
|
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.
|
* Causes population of repo and node lists, unlocks info drawer.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) {
|
if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) {
|
||||||
if (currentState == SyncthingService.State.DISABLED) {
|
if (currentState == SyncthingService.State.DISABLED) {
|
||||||
if (mLoadingDialog != null) {
|
if (mLoadingDialog != null) {
|
||||||
mLoadingDialog.dismiss();
|
mLoadingDialog.dismiss();
|
||||||
}
|
}
|
||||||
SyncthingService.showDisabledDialog(this);
|
SyncthingService.showDisabledDialog(this);
|
||||||
}
|
} else if (mLoadingDialog == null) {
|
||||||
else if (mLoadingDialog == null) {
|
final SharedPreferences prefs =
|
||||||
final SharedPreferences prefs =
|
PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
|
||||||
PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
|
|
||||||
|
|
||||||
LayoutInflater inflater = getLayoutInflater();
|
LayoutInflater inflater = getLayoutInflater();
|
||||||
View dialogLayout = inflater.inflate(R.layout.loading_dialog, null);
|
View dialogLayout = inflater.inflate(R.layout.loading_dialog, null);
|
||||||
TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text);
|
TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text);
|
||||||
loadingText.setText((getService().isFirstStart())
|
loadingText.setText((getService().isFirstStart())
|
||||||
? R.string.web_gui_creating_key
|
? R.string.web_gui_creating_key
|
||||||
: R.string.api_loading);
|
: R.string.api_loading);
|
||||||
|
|
||||||
mLoadingDialog = new AlertDialog.Builder(this)
|
mLoadingDialog = new AlertDialog.Builder(this)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setView(dialogLayout)
|
.setView(dialogLayout)
|
||||||
.show();
|
.show();
|
||||||
|
|
||||||
// Make sure the first start dialog is shown on top.
|
// Make sure the first start dialog is shown on top.
|
||||||
if (prefs.getBoolean("first_start", true)) {
|
if (prefs.getBoolean("first_start", true)) {
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.welcome_title)
|
.setTitle(R.string.welcome_title)
|
||||||
.setMessage(R.string.welcome_text)
|
.setMessage(R.string.welcome_text)
|
||||||
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
prefs.edit().putBoolean("first_start", false).commit();
|
prefs.edit().putBoolean("first_start", false).commit();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLoadingDialog != null) {
|
if (mLoadingDialog != null) {
|
||||||
mLoadingDialog.dismiss();
|
mLoadingDialog.dismiss();
|
||||||
}
|
}
|
||||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
||||||
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final FragmentPagerAdapter mSectionsPagerAdapter =
|
private final FragmentPagerAdapter mSectionsPagerAdapter =
|
||||||
new FragmentPagerAdapter(getSupportFragmentManager()) {
|
new FragmentPagerAdapter(getSupportFragmentManager()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 0: return mRepositoriesFragment;
|
case 0:
|
||||||
case 1: return mNodesFragment;
|
return mRepositoriesFragment;
|
||||||
default: return null;
|
case 1:
|
||||||
}
|
return mNodesFragment;
|
||||||
}
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return 2;
|
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.
|
* Initializes tab navigation.
|
||||||
*/
|
*/
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
final ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
|
|
||||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
setContentView(R.layout.main_activity);
|
setContentView(R.layout.main_activity);
|
||||||
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||||
|
|
||||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
mViewPager = (ViewPager) findViewById(R.id.pager);
|
||||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||||
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPageSelected(int position) {
|
public void onPageSelected(int position) {
|
||||||
actionBar.setSelectedNavigationItem(position);
|
actionBar.setSelectedNavigationItem(position);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
TabListener tabListener = new TabListener() {
|
TabListener tabListener = new TabListener() {
|
||||||
public void onTabSelected(Tab tab, FragmentTransaction ft) {
|
public void onTabSelected(Tab tab, FragmentTransaction ft) {
|
||||||
mViewPager.setCurrentItem(tab.getPosition());
|
mViewPager.setCurrentItem(tab.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabReselected(Tab tab, FragmentTransaction ft) {
|
public void onTabReselected(Tab tab, FragmentTransaction ft) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
|
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
actionBar.addTab(actionBar.newTab()
|
actionBar.addTab(actionBar.newTab()
|
||||||
.setText(R.string.repositories_fragment_title)
|
.setText(R.string.repositories_fragment_title)
|
||||||
.setTabListener(tabListener));
|
.setTabListener(tabListener));
|
||||||
actionBar.addTab(actionBar.newTab()
|
actionBar.addTab(actionBar.newTab()
|
||||||
.setText(R.string.nodes_fragment_title)
|
.setText(R.string.nodes_fragment_title)
|
||||||
.setTabListener(tabListener));
|
.setTabListener(tabListener));
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
mRepositoriesFragment = (ReposFragment) fm.getFragment(
|
mRepositoriesFragment = (ReposFragment) fm.getFragment(
|
||||||
savedInstanceState, ReposFragment.class.getName());
|
savedInstanceState, ReposFragment.class.getName());
|
||||||
mNodesFragment = (NodesFragment) fm.getFragment(
|
mNodesFragment = (NodesFragment) fm.getFragment(
|
||||||
savedInstanceState, NodesFragment.class.getName());
|
savedInstanceState, NodesFragment.class.getName());
|
||||||
mLocalNodeInfoFragment = (LocalNodeInfoFragment) fm.getFragment(
|
mLocalNodeInfoFragment = (LocalNodeInfoFragment) fm.getFragment(
|
||||||
savedInstanceState, LocalNodeInfoFragment.class.getName());
|
savedInstanceState, LocalNodeInfoFragment.class.getName());
|
||||||
mViewPager.setCurrentItem(savedInstanceState.getInt("currentTab"));
|
mViewPager.setCurrentItem(savedInstanceState.getInt("currentTab"));
|
||||||
}
|
} else {
|
||||||
else {
|
mRepositoriesFragment = new ReposFragment();
|
||||||
mRepositoriesFragment = new ReposFragment();
|
mNodesFragment = new NodesFragment();
|
||||||
mNodesFragment = new NodesFragment();
|
mLocalNodeInfoFragment = new LocalNodeInfoFragment();
|
||||||
mLocalNodeInfoFragment = new LocalNodeInfoFragment();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.drawer, mLocalNodeInfoFragment)
|
.replace(R.id.drawer, mLocalNodeInfoFragment)
|
||||||
.commit();
|
.commit();
|
||||||
mDrawerToggle = mLocalNodeInfoFragment.new Toggle(this, mDrawerLayout,
|
mDrawerToggle = mLocalNodeInfoFragment.new Toggle(this, mDrawerLayout,
|
||||||
R.drawable.ic_drawer);
|
R.drawable.ic_drawer);
|
||||||
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (mLoadingDialog != null) {
|
if (mLoadingDialog != null) {
|
||||||
mLoadingDialog.dismiss();
|
mLoadingDialog.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||||
super.onServiceConnected(componentName, iBinder);
|
super.onServiceConnected(componentName, iBinder);
|
||||||
getService().registerOnApiChangeListener(mRepositoriesFragment);
|
getService().registerOnApiChangeListener(mRepositoriesFragment);
|
||||||
getService().registerOnApiChangeListener(mNodesFragment);
|
getService().registerOnApiChangeListener(mNodesFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves fragment states.
|
* Saves fragment states.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
// Avoid crash if called during startup.
|
// Avoid crash if called during startup.
|
||||||
if (mRepositoriesFragment != null && mNodesFragment != null &&
|
if (mRepositoriesFragment != null && mNodesFragment != null &&
|
||||||
mLocalNodeInfoFragment != null) {
|
mLocalNodeInfoFragment != null) {
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
fm.putFragment(outState, ReposFragment.class.getName(), mRepositoriesFragment);
|
fm.putFragment(outState, ReposFragment.class.getName(), mRepositoriesFragment);
|
||||||
fm.putFragment(outState, NodesFragment.class.getName(), mNodesFragment);
|
fm.putFragment(outState, NodesFragment.class.getName(), mNodesFragment);
|
||||||
fm.putFragment(outState, LocalNodeInfoFragment.class.getName(), mLocalNodeInfoFragment);
|
fm.putFragment(outState, LocalNodeInfoFragment.class.getName(), mLocalNodeInfoFragment);
|
||||||
outState.putInt("currentTab", mViewPager.getCurrentItem());
|
outState.putInt("currentTab", mViewPager.getCurrentItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.main, menu);
|
getMenuInflater().inflate(R.menu.main, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows menu only once syncthing service is running, and shows "share" option only when
|
* Shows menu only once syncthing service is running, and shows "share" option only when
|
||||||
* drawer is open.
|
* drawer is open.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
boolean drawerOpen = mDrawerLayout.isDrawerOpen(findViewById(R.id.drawer));
|
boolean drawerOpen = mDrawerLayout.isDrawerOpen(findViewById(R.id.drawer));
|
||||||
menu.findItem(R.id.share_node_id).setVisible(drawerOpen);
|
menu.findItem(R.id.share_node_id).setVisible(drawerOpen);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if (mLocalNodeInfoFragment.onOptionsItemSelected(item) ||
|
if (mLocalNodeInfoFragment.onOptionsItemSelected(item) ||
|
||||||
mDrawerToggle.onOptionsItemSelected(item)) {
|
mDrawerToggle.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.add_repo:
|
case R.id.add_repo:
|
||||||
Intent intent = new Intent(this, SettingsActivity.class)
|
Intent intent = new Intent(this, SettingsActivity.class)
|
||||||
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
|
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
|
||||||
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
|
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.add_node:
|
case R.id.add_node:
|
||||||
intent = new Intent(this, SettingsActivity.class)
|
intent = new Intent(this, SettingsActivity.class)
|
||||||
.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT)
|
.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT)
|
||||||
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
|
.putExtra(SettingsActivity.EXTRA_IS_CREATE, true);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.web_gui:
|
case R.id.web_gui:
|
||||||
startActivity(new Intent(this, WebGuiActivity.class));
|
startActivity(new Intent(this, WebGuiActivity.class));
|
||||||
return true;
|
return true;
|
||||||
case R.id.settings:
|
case R.id.settings:
|
||||||
startActivity(new Intent(this, SettingsActivity.class)
|
startActivity(new Intent(this, SettingsActivity.class)
|
||||||
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT));
|
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT));
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
super.onPostCreate(savedInstanceState);
|
super.onPostCreate(savedInstanceState);
|
||||||
mDrawerToggle.syncState();
|
mDrawerToggle.syncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
mDrawerToggle.onConfigurationChanged(newConfig);
|
mDrawerToggle.onConfigurationChanged(newConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,75 +14,74 @@ import com.nutomic.syncthingandroid.fragments.SettingsFragment;
|
||||||
*/
|
*/
|
||||||
public class SettingsActivity extends SyncthingActivity {
|
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
|
* Must be set for {@link #ACTION_NODE_SETTINGS_FRAGMENT} and
|
||||||
* {@link #ACTION_REPO_SETTINGS_FRAGMENT} to determine if an existing repo/node should be
|
* {@link #ACTION_REPO_SETTINGS_FRAGMENT} to determine if an existing repo/node should be
|
||||||
* edited or a new one created.
|
* edited or a new one created.
|
||||||
*
|
* <p/>
|
||||||
* If this is false, {@link com.nutomic.syncthingandroid.fragments.RepoSettingsFragment#EXTRA_REPO_ID} or
|
* 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).
|
* {@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";
|
public static final String EXTRA_IS_CREATE = "create";
|
||||||
|
|
||||||
private Fragment mFragment;
|
private Fragment mFragment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mFragment = fm.getFragment(savedInstanceState,
|
mFragment = fm.getFragment(savedInstanceState,
|
||||||
savedInstanceState.getString("fragment_name"));
|
savedInstanceState.getString("fragment_name"));
|
||||||
}
|
} else {
|
||||||
else {
|
switch (getIntent().getAction()) {
|
||||||
switch (getIntent().getAction()) {
|
case ACTION_APP_SETTINGS_FRAGMENT:
|
||||||
case ACTION_APP_SETTINGS_FRAGMENT:
|
setTitle(R.string.settings_title);
|
||||||
setTitle(R.string.settings_title);
|
mFragment = new SettingsFragment();
|
||||||
mFragment = new SettingsFragment();
|
break;
|
||||||
break;
|
case ACTION_NODE_SETTINGS_FRAGMENT:
|
||||||
case ACTION_NODE_SETTINGS_FRAGMENT:
|
mFragment = new NodeSettingsFragment();
|
||||||
mFragment = new NodeSettingsFragment();
|
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
|
||||||
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
|
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
|
||||||
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case ACTION_REPO_SETTINGS_FRAGMENT:
|
||||||
case ACTION_REPO_SETTINGS_FRAGMENT:
|
mFragment = new RepoSettingsFragment();
|
||||||
mFragment = new RepoSettingsFragment();
|
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
|
||||||
if (!getIntent().hasExtra(EXTRA_IS_CREATE)) {
|
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
|
||||||
throw new IllegalArgumentException("EXTRA_IS_CREATE must be set");
|
}
|
||||||
}
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw new IllegalArgumentException(
|
||||||
throw new IllegalArgumentException(
|
"You must provide the requested fragment type as an extra.");
|
||||||
"You must provide the requested fragment type as an extra.");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fm.beginTransaction()
|
fm.beginTransaction()
|
||||||
.replace(android.R.id.content, mFragment)
|
.replace(android.R.id.content, mFragment)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
String fragmentClassName = mFragment.getClass().getName();
|
String fragmentClassName = mFragment.getClass().getName();
|
||||||
outState.putString("fragment_name", fragmentClassName);
|
outState.putString("fragment_name", fragmentClassName);
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
fm.putFragment(outState, fragmentClassName, mFragment);
|
fm.putFragment(outState, fragmentClassName, mFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsCreate() {
|
public boolean getIsCreate() {
|
||||||
return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false);
|
return getIntent().getBooleanExtra(EXTRA_IS_CREATE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,71 +19,70 @@ import java.util.LinkedList;
|
||||||
*/
|
*/
|
||||||
public class SyncthingActivity extends ActionBarActivity implements ServiceConnection {
|
public class SyncthingActivity extends ActionBarActivity implements ServiceConnection {
|
||||||
|
|
||||||
private SyncthingService mSyncthingService;
|
private SyncthingService mSyncthingService;
|
||||||
|
|
||||||
private LinkedList<OnServiceConnectedListener> mServiceConnectedListeners = new LinkedList<>();
|
private LinkedList<OnServiceConnectedListener> mServiceConnectedListeners = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be used for Fragments.
|
* To be used for Fragments.
|
||||||
*/
|
*/
|
||||||
public interface OnServiceConnectedListener {
|
public interface OnServiceConnectedListener {
|
||||||
public void onServiceConnected();
|
public void onServiceConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
bindService(new Intent(this, SyncthingService.class),
|
bindService(new Intent(this, SyncthingService.class),
|
||||||
this, Context.BIND_AUTO_CREATE);
|
this, Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
unbindService(this);
|
unbindService(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||||
SyncthingServiceBinder binder = (SyncthingServiceBinder) iBinder;
|
SyncthingServiceBinder binder = (SyncthingServiceBinder) iBinder;
|
||||||
mSyncthingService = binder.getService();
|
mSyncthingService = binder.getService();
|
||||||
for (OnServiceConnectedListener listener : mServiceConnectedListeners) {
|
for (OnServiceConnectedListener listener : mServiceConnectedListeners) {
|
||||||
listener.onServiceConnected();
|
listener.onServiceConnected();
|
||||||
}
|
}
|
||||||
mServiceConnectedListeners.clear();
|
mServiceConnectedListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName componentName) {
|
public void onServiceDisconnected(ComponentName componentName) {
|
||||||
mSyncthingService = null;
|
mSyncthingService = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for Fragments to use the Activity's service connection.
|
* Used for Fragments to use the Activity's service connection.
|
||||||
*/
|
*/
|
||||||
public void registerOnServiceConnectedListener(OnServiceConnectedListener listener) {
|
public void registerOnServiceConnectedListener(OnServiceConnectedListener listener) {
|
||||||
if (mSyncthingService != null) {
|
if (mSyncthingService != null) {
|
||||||
listener.onServiceConnected();
|
listener.onServiceConnected();
|
||||||
}
|
} else {
|
||||||
else {
|
mServiceConnectedListeners.addLast(listener);
|
||||||
mServiceConnectedListeners.addLast(listener);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns service object (or null if not bound).
|
* Returns service object (or null if not bound).
|
||||||
*/
|
*/
|
||||||
public SyncthingService getService() {
|
public SyncthingService getService() {
|
||||||
return mSyncthingService;
|
return mSyncthingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns RestApi instance, or null if SyncthingService is not yet connected.
|
* Returns RestApi instance, or null if SyncthingService is not yet connected.
|
||||||
*/
|
*/
|
||||||
public RestApi getApi() {
|
public RestApi getApi() {
|
||||||
return (getService() != null)
|
return (getService() != null)
|
||||||
? getService().getApi()
|
? getService().getApi()
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,56 +17,56 @@ import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||||
*/
|
*/
|
||||||
public class WebGuiActivity extends SyncthingActivity implements SyncthingService.OnWebGuiAvailableListener {
|
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.
|
* Hides the loading screen and shows the WebView once it is fully loaded.
|
||||||
*/
|
*/
|
||||||
private final WebViewClient mWebViewClient = new WebViewClient() {
|
private final WebViewClient mWebViewClient = new WebViewClient() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
mWebView.setVisibility(View.VISIBLE);
|
mWebView.setVisibility(View.VISIBLE);
|
||||||
mLoadingView.setVisibility(View.GONE);
|
mLoadingView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize WebView.
|
* Initialize WebView.
|
||||||
*
|
* <p/>
|
||||||
* Ignore lint javascript warning as js is loaded only from our known, local service.
|
* Ignore lint javascript warning as js is loaded only from our known, local service.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.web_gui_activity);
|
setContentView(R.layout.web_gui_activity);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
mLoadingView = findViewById(R.id.loading);
|
mLoadingView = findViewById(R.id.loading);
|
||||||
ProgressBar pb = (ProgressBar) mLoadingView.findViewById(R.id.progress);
|
ProgressBar pb = (ProgressBar) mLoadingView.findViewById(R.id.progress);
|
||||||
pb.setIndeterminate(true);
|
pb.setIndeterminate(true);
|
||||||
|
|
||||||
mWebView = (WebView) findViewById(R.id.webview);
|
mWebView = (WebView) findViewById(R.id.webview);
|
||||||
mWebView.getSettings().setJavaScriptEnabled(true);
|
mWebView.getSettings().setJavaScriptEnabled(true);
|
||||||
mWebView.setWebViewClient(mWebViewClient);
|
mWebView.setWebViewClient(mWebViewClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
||||||
super.onServiceConnected(componentName, iBinder);
|
super.onServiceConnected(componentName, iBinder);
|
||||||
getService().registerOnWebGuiAvailableListener(WebGuiActivity.this);
|
getService().registerOnWebGuiAvailableListener(WebGuiActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads and shows WebView, hides loading view.
|
* Loads and shows WebView, hides loading view.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onWebGuiAvailable() {
|
public void onWebGuiAvailable() {
|
||||||
mWebView.loadUrl(getApi().getUrl());
|
mWebView.loadUrl(getApi().getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,152 +26,153 @@ import java.util.TimerTask;
|
||||||
* Displays information about the local node.
|
* Displays information about the local node.
|
||||||
*/
|
*/
|
||||||
public class LocalNodeInfoFragment extends Fragment
|
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.
|
* Starts polling for status when opened, stops when closed.
|
||||||
*/
|
*/
|
||||||
public class Toggle extends ActionBarDrawerToggle {
|
public class Toggle extends ActionBarDrawerToggle {
|
||||||
public Toggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes) {
|
public Toggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes) {
|
||||||
super(activity, drawerLayout, drawerImageRes, R.string.app_name, R.string.system_info);
|
super(activity, drawerLayout, drawerImageRes, R.string.app_name, R.string.system_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrawerClosed(View view) {
|
public void onDrawerClosed(View view) {
|
||||||
super.onDrawerClosed(view);
|
super.onDrawerClosed(view);
|
||||||
mTimer.cancel();
|
mTimer.cancel();
|
||||||
mTimer = null;
|
mTimer = null;
|
||||||
mActivity.getSupportActionBar().setTitle(R.string.app_name);
|
mActivity.getSupportActionBar().setTitle(R.string.app_name);
|
||||||
mActivity.supportInvalidateOptionsMenu();
|
mActivity.supportInvalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrawerOpened(View drawerView) {
|
public void onDrawerOpened(View drawerView) {
|
||||||
super.onDrawerOpened(drawerView);
|
super.onDrawerOpened(drawerView);
|
||||||
LocalNodeInfoFragment.this.onDrawerOpened();
|
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
|
return view;
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
}
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
mActivity = (MainActivity) getActivity();
|
|
||||||
|
|
||||||
if (savedInstanceState != null && savedInstanceState.getBoolean("active")) {
|
@Override
|
||||||
onDrawerOpened();
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
}
|
super.onActivityCreated(savedInstanceState);
|
||||||
}
|
mActivity = (MainActivity) getActivity();
|
||||||
|
|
||||||
@Override
|
if (savedInstanceState != null && savedInstanceState.getBoolean("active")) {
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
onDrawerOpened();
|
||||||
super.onSaveInstanceState(outState);
|
}
|
||||||
outState.putBoolean("active", mTimer != null);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrawerOpened() {
|
@Override
|
||||||
// FIXME: never called
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
mTimer = new Timer();
|
super.onSaveInstanceState(outState);
|
||||||
mTimer.schedule(new TimerTask() {
|
outState.putBoolean("active", mTimer != null);
|
||||||
@Override
|
}
|
||||||
public void run() {
|
|
||||||
updateGui();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
private void onDrawerOpened() {
|
||||||
mActivity.getSupportActionBar().setTitle(R.string.system_info);
|
// FIXME: never called
|
||||||
mActivity.supportInvalidateOptionsMenu();
|
mTimer = new Timer();
|
||||||
}
|
mTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateGui();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
||||||
* Invokes status callbacks.
|
mActivity.getSupportActionBar().setTitle(R.string.system_info);
|
||||||
*/
|
mActivity.supportInvalidateOptionsMenu();
|
||||||
private void updateGui() {
|
}
|
||||||
if (mActivity.getApi() != null) {
|
|
||||||
mActivity.getApi().getSystemInfo(this);
|
|
||||||
mActivity.getApi().getConnections(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates views with status received via {@link RestApi#getSystemInfo}.
|
* Invokes status callbacks.
|
||||||
*/
|
*/
|
||||||
@Override
|
private void updateGui() {
|
||||||
public void onReceiveSystemInfo(RestApi.SystemInfo info) {
|
if (mActivity.getApi() != null) {
|
||||||
if (getActivity() == null)
|
mActivity.getApi().getSystemInfo(this);
|
||||||
return;
|
mActivity.getApi().getConnections(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mNodeId.setText(info.myID);
|
/**
|
||||||
mNodeId.setOnTouchListener(new View.OnTouchListener() {
|
* Populates views with status received via {@link RestApi#getSystemInfo}.
|
||||||
@Override
|
*/
|
||||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
@Override
|
||||||
mActivity.getApi().copyNodeId(mNodeId.getText().toString());
|
public void onReceiveSystemInfo(RestApi.SystemInfo info) {
|
||||||
view.performClick();
|
if (getActivity() == null)
|
||||||
return true;
|
return;
|
||||||
}
|
|
||||||
});
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
mNodeId.setText(info.myID);
|
||||||
* Populates views with status received via {@link RestApi#getConnections}.
|
mNodeId.setOnTouchListener(new View.OnTouchListener() {
|
||||||
*/
|
@Override
|
||||||
@Override
|
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||||
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
mActivity.getApi().copyNodeId(mNodeId.getText().toString());
|
||||||
RestApi.Connection c = connections.get(RestApi.LOCAL_NODE_CONNECTIONS);
|
view.performClick();
|
||||||
mDownload.setText(RestApi.readableTransferRate(mActivity, c.InBits));
|
return true;
|
||||||
mUpload.setText(RestApi.readableTransferRate(mActivity, c.OutBits));
|
}
|
||||||
}
|
});
|
||||||
|
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.
|
* Populates views with status received via {@link RestApi#getConnections}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
||||||
switch (item.getItemId()) {
|
RestApi.Connection c = connections.get(RestApi.LOCAL_NODE_CONNECTIONS);
|
||||||
case R.id.share_node_id:
|
mDownload.setText(RestApi.readableTransferRate(mActivity, c.InBits));
|
||||||
RestApi.shareNodeId(getActivity(), mNodeId.getText().toString());
|
mUpload.setText(RestApi.readableTransferRate(mActivity, c.OutBits));
|
||||||
return true;
|
}
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
/**
|
||||||
}
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.nutomic.syncthingandroid.fragments;
|
package com.nutomic.syncthingandroid.fragments;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
@ -29,259 +28,253 @@ import java.util.Map;
|
||||||
* Shows node details and allows changing them.
|
* Shows node details and allows changing them.
|
||||||
*/
|
*/
|
||||||
public class NodeSettingsFragment extends PreferenceFragment implements
|
public class NodeSettingsFragment extends PreferenceFragment implements
|
||||||
SyncthingActivity.OnServiceConnectedListener, Preference.OnPreferenceChangeListener,
|
SyncthingActivity.OnServiceConnectedListener, Preference.OnPreferenceChangeListener,
|
||||||
Preference.OnPreferenceClickListener, RestApi.OnReceiveConnectionsListener,
|
Preference.OnPreferenceClickListener, RestApi.OnReceiveConnectionsListener,
|
||||||
SyncthingService.OnApiChangeListener, RestApi.OnNodeIdNormalizedListener {
|
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
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
|
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
|
||||||
|
|
||||||
mIsCreate = ((SettingsActivity) getActivity()).getIsCreate();
|
mIsCreate = ((SettingsActivity) getActivity()).getIsCreate();
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
if (mIsCreate) {
|
if (mIsCreate) {
|
||||||
addPreferencesFromResource(R.xml.node_settings_create);
|
addPreferencesFromResource(R.xml.node_settings_create);
|
||||||
}
|
} else {
|
||||||
else {
|
addPreferencesFromResource(R.xml.node_settings_edit);
|
||||||
addPreferencesFromResource(R.xml.node_settings_edit);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mNodeId = findPreference("node_id");
|
mNodeId = findPreference("node_id");
|
||||||
mNodeId.setOnPreferenceChangeListener(this);
|
mNodeId.setOnPreferenceChangeListener(this);
|
||||||
mName = (EditTextPreference) findPreference("name");
|
mName = (EditTextPreference) findPreference("name");
|
||||||
mName.setOnPreferenceChangeListener(this);
|
mName.setOnPreferenceChangeListener(this);
|
||||||
mAddresses = (EditTextPreference) findPreference("addresses");
|
mAddresses = (EditTextPreference) findPreference("addresses");
|
||||||
mAddresses.setOnPreferenceChangeListener(this);
|
mAddresses.setOnPreferenceChangeListener(this);
|
||||||
if (!mIsCreate) {
|
if (!mIsCreate) {
|
||||||
mVersion = findPreference("version");
|
mVersion = findPreference("version");
|
||||||
mVersion.setSummary("?");
|
mVersion.setSummary("?");
|
||||||
mCurrentAddress = findPreference("current_address");
|
mCurrentAddress = findPreference("current_address");
|
||||||
mCurrentAddress.setSummary("?");
|
mCurrentAddress.setSummary("?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected() {
|
public void onServiceConnected() {
|
||||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||||
mSyncthingService.registerOnApiChangeListener(this);
|
mSyncthingService.registerOnApiChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE) {
|
if (currentState != SyncthingService.State.ACTIVE) {
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getActivity() == null || getActivity().isFinishing())
|
if (getActivity() == null || getActivity().isFinishing())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mIsCreate) {
|
if (mIsCreate) {
|
||||||
getActivity().setTitle(R.string.add_node);
|
getActivity().setTitle(R.string.add_node);
|
||||||
mNode = new RestApi.Node();
|
mNode = new RestApi.Node();
|
||||||
mNode.Name = "";
|
mNode.Name = "";
|
||||||
mNode.NodeID = "";
|
mNode.NodeID = "";
|
||||||
mNode.Addresses = "dynamic";
|
mNode.Addresses = "dynamic";
|
||||||
((EditTextPreference) mNodeId).setText(mNode.NodeID);
|
((EditTextPreference) mNodeId).setText(mNode.NodeID);
|
||||||
}
|
} else {
|
||||||
else {
|
getActivity().setTitle(R.string.edit_node);
|
||||||
getActivity().setTitle(R.string.edit_node);
|
List<RestApi.Node> nodes = mSyncthingService.getApi().getNodes();
|
||||||
List<RestApi.Node> nodes = mSyncthingService.getApi().getNodes();
|
for (int i = 0; i < nodes.size(); i++) {
|
||||||
for (int i = 0; i < nodes.size(); i++) {
|
if (nodes.get(i).NodeID.equals(
|
||||||
if (nodes.get(i).NodeID.equals(
|
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {
|
||||||
getActivity().getIntent().getStringExtra(EXTRA_NODE_ID))) {
|
mNode = nodes.get(i);
|
||||||
mNode = nodes.get(i);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
mNodeId.setOnPreferenceClickListener(this);
|
||||||
mNodeId.setOnPreferenceClickListener(this);
|
}
|
||||||
}
|
mSyncthingService.getApi().getConnections(NodeSettingsFragment.this);
|
||||||
mSyncthingService.getApi().getConnections(NodeSettingsFragment.this);
|
|
||||||
|
|
||||||
mNodeId.setSummary(mNode.NodeID);
|
mNodeId.setSummary(mNode.NodeID);
|
||||||
mName.setText((mNode.Name));
|
mName.setText((mNode.Name));
|
||||||
mName.setSummary(mNode.Name);
|
mName.setSummary(mNode.Name);
|
||||||
mAddresses.setText(mNode.Addresses);
|
mAddresses.setText(mNode.Addresses);
|
||||||
mAddresses.setSummary(mNode.Addresses);
|
mAddresses.setSummary(mNode.Addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
inflater.inflate(R.menu.node_settings, menu);
|
inflater.inflate(R.menu.node_settings, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
menu.findItem(R.id.create).setVisible(mIsCreate);
|
menu.findItem(R.id.create).setVisible(mIsCreate);
|
||||||
menu.findItem(R.id.share_node_id).setVisible(!mIsCreate);
|
menu.findItem(R.id.share_node_id).setVisible(!mIsCreate);
|
||||||
menu.findItem(R.id.delete).setVisible(!mIsCreate);
|
menu.findItem(R.id.delete).setVisible(!mIsCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.create:
|
case R.id.create:
|
||||||
if (mNode.NodeID.equals("")) {
|
if (mNode.NodeID.equals("")) {
|
||||||
Toast.makeText(getActivity(), R.string.node_id_required, Toast.LENGTH_LONG)
|
Toast.makeText(getActivity(), R.string.node_id_required, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mNode.Name.equals("")) {
|
if (mNode.Name.equals("")) {
|
||||||
Toast.makeText(getActivity(), R.string.node_name_required, Toast.LENGTH_LONG)
|
Toast.makeText(getActivity(), R.string.node_name_required, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
mSyncthingService.getApi().editNode(mNode, this);
|
mSyncthingService.getApi().editNode(mNode, this);
|
||||||
return true;
|
return true;
|
||||||
case R.id.share_node_id:
|
case R.id.share_node_id:
|
||||||
RestApi.shareNodeId(getActivity(), mNode.NodeID);
|
RestApi.shareNodeId(getActivity(), mNode.NodeID);
|
||||||
return true;
|
return true;
|
||||||
case R.id.delete:
|
case R.id.delete:
|
||||||
new AlertDialog.Builder(getActivity())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setMessage(R.string.delete_node_confirm)
|
.setMessage(R.string.delete_node_confirm)
|
||||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
mSyncthingService.getApi().deleteNode(mNode, getActivity());
|
mSyncthingService.getApi().deleteNode(mNode, getActivity());
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.no, null)
|
.setNegativeButton(android.R.string.no, null)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||||
if (preference instanceof EditTextPreference) {
|
if (preference instanceof EditTextPreference) {
|
||||||
EditTextPreference pref = (EditTextPreference) preference;
|
EditTextPreference pref = (EditTextPreference) preference;
|
||||||
pref.setSummary((String) o);
|
pref.setSummary((String) o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preference.equals(mNodeId)) {
|
if (preference.equals(mNodeId)) {
|
||||||
mNode.NodeID = (String) o;
|
mNode.NodeID = (String) o;
|
||||||
nodeUpdated();
|
nodeUpdated();
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (preference.equals(mName)) {
|
||||||
else if (preference.equals(mName)) {
|
mNode.Name = (String) o;
|
||||||
mNode.Name = (String) o;
|
nodeUpdated();
|
||||||
nodeUpdated();
|
return true;
|
||||||
return true;
|
} else if (preference.equals(mAddresses)) {
|
||||||
}
|
mNode.Addresses = (String) o;
|
||||||
else if (preference.equals(mAddresses)) {
|
nodeUpdated();
|
||||||
mNode.Addresses = (String) o;
|
return true;
|
||||||
nodeUpdated();
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
if (preference.equals(mNodeId)) {
|
if (preference.equals(mNodeId)) {
|
||||||
mSyncthingService.getApi().copyNodeId(mNode.NodeID);
|
mSyncthingService.getApi().copyNodeId(mNode.NodeID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets version and current address of the node.
|
* Sets version and current address of the node.
|
||||||
*
|
* <p/>
|
||||||
* NOTE: This is only called once on startup, should be called more often to properly display
|
* NOTE: This is only called once on startup, should be called more often to properly display
|
||||||
* version/address changes.
|
* version/address changes.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
||||||
if (connections.containsKey(mNode.NodeID)) {
|
if (connections.containsKey(mNode.NodeID)) {
|
||||||
mVersion.setSummary(connections.get(mNode.NodeID).ClientVersion);
|
mVersion.setSummary(connections.get(mNode.NodeID).ClientVersion);
|
||||||
mCurrentAddress.setSummary(connections.get(mNode.NodeID).Address);
|
mCurrentAddress.setSummary(connections.get(mNode.NodeID).Address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the updated node info if in edit mode.
|
* Sends the updated node info if in edit mode.
|
||||||
*/
|
*/
|
||||||
private void nodeUpdated() {
|
private void nodeUpdated() {
|
||||||
if (!mIsCreate) {
|
if (!mIsCreate) {
|
||||||
mSyncthingService.getApi().editNode(mNode, this);
|
mSyncthingService.getApi().editNode(mNode, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends QR code scanning intent when clicking the qrcode icon.
|
* Sends QR code scanning intent when clicking the qrcode icon.
|
||||||
*/
|
*/
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
|
Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
|
||||||
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
|
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||||
try {
|
try {
|
||||||
startActivityForResult(intentScan, SCAN_QR_REQUEST_CODE);
|
startActivityForResult(intentScan, SCAN_QR_REQUEST_CODE);
|
||||||
}
|
} catch (ActivityNotFoundException e) {
|
||||||
catch (ActivityNotFoundException e) {
|
Toast.makeText(getActivity(), R.string.no_qr_scanner_installed,
|
||||||
Toast.makeText(getActivity(), R.string.no_qr_scanner_installed,
|
Toast.LENGTH_LONG).show();
|
||||||
Toast.LENGTH_LONG).show();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives value of scanned QR code and sets it as node ID.
|
* Receives value of scanned QR code and sets it as node ID.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (requestCode == SCAN_QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
if (requestCode == SCAN_QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||||
mNode.NodeID = data.getStringExtra("SCAN_RESULT");
|
mNode.NodeID = data.getStringExtra("SCAN_RESULT");
|
||||||
((EditTextPreference) mNodeId).setText(mNode.NodeID);
|
((EditTextPreference) mNodeId).setText(mNode.NodeID);
|
||||||
mNodeId.setSummary(mNode.NodeID);
|
mNodeId.setSummary(mNode.NodeID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for {@link RestApi#editNode(RestApi.Node, RestApi.OnNodeIdNormalizedListener)}.
|
* Callback for {@link RestApi#editNode(RestApi.Node, RestApi.OnNodeIdNormalizedListener)}.
|
||||||
* Displays an error message if present, or finishes the Activity on success in edit mode.
|
* 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 normalizedId The normalized node ID, or null on error.
|
||||||
* @param error An error message, or null on success.
|
* @param error An error message, or null on success.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onNodeIdNormalized(String normalizedId, String error) {
|
public void onNodeIdNormalized(String normalizedId, String error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show();
|
||||||
}
|
} else if (mIsCreate) {
|
||||||
else if (mIsCreate) {
|
getActivity().finish();
|
||||||
getActivity().finish();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,80 +21,79 @@ import java.util.TimerTask;
|
||||||
* Displays a list of all existing nodes.
|
* Displays a list of all existing nodes.
|
||||||
*/
|
*/
|
||||||
public class NodesFragment extends ListFragment implements SyncthingService.OnApiChangeListener,
|
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
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE)
|
if (currentState != SyncthingService.State.ACTIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
initAdapter();
|
initAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
initAdapter();
|
initAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initAdapter() {
|
private void initAdapter() {
|
||||||
SyncthingActivity activity = (SyncthingActivity) getActivity();
|
SyncthingActivity activity = (SyncthingActivity) getActivity();
|
||||||
if (activity == null || activity.getApi() == null)
|
if (activity == null || activity.getApi() == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mAdapter = new NodesAdapter(activity);
|
mAdapter = new NodesAdapter(activity);
|
||||||
mAdapter.add(activity.getApi().getNodes());
|
mAdapter.add(activity.getApi().getNodes());
|
||||||
setListAdapter(mAdapter);
|
setListAdapter(mAdapter);
|
||||||
setEmptyText(getString(R.string.nodes_list_empty));
|
setEmptyText(getString(R.string.nodes_list_empty));
|
||||||
getListView().setOnItemClickListener(this);
|
getListView().setOnItemClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateList() {
|
private void updateList() {
|
||||||
if (mAdapter == null || getView() == null)
|
if (mAdapter == null || getView() == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MainActivity activity = (MainActivity) getActivity();
|
MainActivity activity = (MainActivity) getActivity();
|
||||||
mAdapter.updateConnections(activity.getApi(), getListView());
|
mAdapter.updateConnections(activity.getApi(), getListView());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
|
|
||||||
if (isVisibleToUser) {
|
if (isVisibleToUser) {
|
||||||
mTimer = new Timer();
|
mTimer = new Timer();
|
||||||
mTimer.schedule(new TimerTask() {
|
mTimer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
updateList();
|
updateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
||||||
}
|
} else if (mTimer != null) {
|
||||||
else if (mTimer != null) {
|
mTimer.cancel();
|
||||||
mTimer.cancel();
|
mTimer = null;
|
||||||
mTimer = null;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
||||||
intent.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT);
|
intent.setAction(SettingsActivity.ACTION_NODE_SETTINGS_FRAGMENT);
|
||||||
intent.putExtra(SettingsActivity.EXTRA_IS_CREATE, false);
|
intent.putExtra(SettingsActivity.EXTRA_IS_CREATE, false);
|
||||||
intent.putExtra(NodeSettingsFragment.EXTRA_NODE_ID, mAdapter.getItem(i).NodeID);
|
intent.putExtra(NodeSettingsFragment.EXTRA_NODE_ID, mAdapter.getItem(i).NodeID);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,275 +31,265 @@ import java.util.List;
|
||||||
* Shows repo details and allows changing them.
|
* Shows repo details and allows changing them.
|
||||||
*/
|
*/
|
||||||
public class RepoSettingsFragment extends PreferenceFragment
|
public class RepoSettingsFragment extends PreferenceFragment
|
||||||
implements SyncthingActivity.OnServiceConnectedListener,
|
implements SyncthingActivity.OnServiceConnectedListener,
|
||||||
Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
|
Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
|
||||||
SyncthingService.OnApiChangeListener {
|
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}
|
* The ID of the repo to be edited. To be used with {@link com.nutomic.syncthingandroid.activities.SettingsActivity#EXTRA_IS_CREATE}
|
||||||
* set to false.
|
* set to false.
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_REPO_ID = "repo_id";
|
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
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
SettingsActivity activity = (SettingsActivity) getActivity();
|
SettingsActivity activity = (SettingsActivity) getActivity();
|
||||||
activity.registerOnServiceConnectedListener(this);
|
activity.registerOnServiceConnectedListener(this);
|
||||||
mIsCreate = activity.getIsCreate();
|
mIsCreate = activity.getIsCreate();
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
if (mIsCreate) {
|
if (mIsCreate) {
|
||||||
addPreferencesFromResource(R.xml.repo_settings_create);
|
addPreferencesFromResource(R.xml.repo_settings_create);
|
||||||
}
|
} else {
|
||||||
else {
|
addPreferencesFromResource(R.xml.repo_settings_edit);
|
||||||
addPreferencesFromResource(R.xml.repo_settings_edit);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mRepoId = (EditTextPreference) findPreference("repo_id");
|
mRepoId = (EditTextPreference) findPreference("repo_id");
|
||||||
mRepoId.setOnPreferenceChangeListener(this);
|
mRepoId.setOnPreferenceChangeListener(this);
|
||||||
mDirectory = findPreference("directory");
|
mDirectory = findPreference("directory");
|
||||||
mDirectory.setOnPreferenceClickListener(this);
|
mDirectory.setOnPreferenceClickListener(this);
|
||||||
mRepoMaster = (CheckBoxPreference) findPreference("repo_master");
|
mRepoMaster = (CheckBoxPreference) findPreference("repo_master");
|
||||||
mRepoMaster.setOnPreferenceChangeListener(this);
|
mRepoMaster.setOnPreferenceChangeListener(this);
|
||||||
mNodes = (PreferenceScreen) findPreference("nodes");
|
mNodes = (PreferenceScreen) findPreference("nodes");
|
||||||
mNodes.setOnPreferenceClickListener(this);
|
mNodes.setOnPreferenceClickListener(this);
|
||||||
mVersioning = (CheckBoxPreference) findPreference("versioning");
|
mVersioning = (CheckBoxPreference) findPreference("versioning");
|
||||||
mVersioning.setOnPreferenceChangeListener(this);
|
mVersioning.setOnPreferenceChangeListener(this);
|
||||||
mVersioningKeep = (EditTextPreference) findPreference("versioning_keep");
|
mVersioningKeep = (EditTextPreference) findPreference("versioning_keep");
|
||||||
mVersioningKeep.setOnPreferenceChangeListener(this);
|
mVersioningKeep.setOnPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE) {
|
if (currentState != SyncthingService.State.ACTIVE) {
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getActivity() == null || getActivity().isFinishing())
|
if (getActivity() == null || getActivity().isFinishing())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mIsCreate) {
|
if (mIsCreate) {
|
||||||
getActivity().setTitle(R.string.create_repo);
|
getActivity().setTitle(R.string.create_repo);
|
||||||
mRepo = new RestApi.Repo();
|
mRepo = new RestApi.Repo();
|
||||||
mRepo.ID = "";
|
mRepo.ID = "";
|
||||||
mRepo.Directory = "";
|
mRepo.Directory = "";
|
||||||
mRepo.Nodes = new ArrayList<RestApi.Node>();
|
mRepo.Nodes = new ArrayList<RestApi.Node>();
|
||||||
mRepo.Versioning = new RestApi.Versioning();
|
mRepo.Versioning = new RestApi.Versioning();
|
||||||
}
|
} else {
|
||||||
else {
|
getActivity().setTitle(R.string.edit_repo);
|
||||||
getActivity().setTitle(R.string.edit_repo);
|
List<RestApi.Repo> repos = mSyncthingService.getApi().getRepos();
|
||||||
List<RestApi.Repo> repos = mSyncthingService.getApi().getRepos();
|
for (int i = 0; i < repos.size(); i++) {
|
||||||
for (int i = 0; i < repos.size(); i++) {
|
if (repos.get(i).ID.equals(
|
||||||
if (repos.get(i).ID.equals(
|
getActivity().getIntent().getStringExtra(EXTRA_REPO_ID))) {
|
||||||
getActivity().getIntent().getStringExtra(EXTRA_REPO_ID))) {
|
mRepo = repos.get(i);
|
||||||
mRepo = repos.get(i);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mRepoId.setText(mRepo.ID);
|
mRepoId.setText(mRepo.ID);
|
||||||
mRepoId.setSummary(mRepo.ID);
|
mRepoId.setSummary(mRepo.ID);
|
||||||
mDirectory.setSummary(mRepo.Directory);
|
mDirectory.setSummary(mRepo.Directory);
|
||||||
mRepoMaster.setChecked(mRepo.ReadOnly);
|
mRepoMaster.setChecked(mRepo.ReadOnly);
|
||||||
List<RestApi.Node> nodesList = mSyncthingService.getApi().getNodes();
|
List<RestApi.Node> nodesList = mSyncthingService.getApi().getNodes();
|
||||||
for (RestApi.Node n : nodesList) {
|
for (RestApi.Node n : nodesList) {
|
||||||
ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n);
|
ExtendedCheckBoxPreference cbp = new ExtendedCheckBoxPreference(getActivity(), n);
|
||||||
cbp.setTitle(n.Name);
|
cbp.setTitle(n.Name);
|
||||||
cbp.setKey(KEY_NODE_SHARED);
|
cbp.setKey(KEY_NODE_SHARED);
|
||||||
cbp.setOnPreferenceChangeListener(RepoSettingsFragment.this);
|
cbp.setOnPreferenceChangeListener(RepoSettingsFragment.this);
|
||||||
cbp.setChecked(false);
|
cbp.setChecked(false);
|
||||||
for (RestApi.Node n2 : mRepo.Nodes) {
|
for (RestApi.Node n2 : mRepo.Nodes) {
|
||||||
if (n2.NodeID.equals(n.NodeID)) {
|
if (n2.NodeID.equals(n.NodeID)) {
|
||||||
cbp.setChecked(true);
|
cbp.setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mNodes.addPreference(cbp);
|
mNodes.addPreference(cbp);
|
||||||
}
|
}
|
||||||
mVersioning.setChecked(mRepo.Versioning instanceof RestApi.SimpleVersioning);
|
mVersioning.setChecked(mRepo.Versioning instanceof RestApi.SimpleVersioning);
|
||||||
if (mVersioning.isChecked()) {
|
if (mVersioning.isChecked()) {
|
||||||
mVersioningKeep.setText(mRepo.Versioning.getParams().get("keep"));
|
mVersioningKeep.setText(mRepo.Versioning.getParams().get("keep"));
|
||||||
mVersioningKeep.setSummary(mRepo.Versioning.getParams().get("keep"));
|
mVersioningKeep.setSummary(mRepo.Versioning.getParams().get("keep"));
|
||||||
mVersioningKeep.setEnabled(true);
|
mVersioningKeep.setEnabled(true);
|
||||||
}
|
} else {
|
||||||
else {
|
mVersioningKeep.setEnabled(false);
|
||||||
mVersioningKeep.setEnabled(false);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected() {
|
public void onServiceConnected() {
|
||||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||||
mSyncthingService.registerOnApiChangeListener(this);
|
mSyncthingService.registerOnApiChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
inflater.inflate(R.menu.repo_settings, menu);
|
inflater.inflate(R.menu.repo_settings, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
menu.findItem(R.id.create).setVisible(mIsCreate);
|
menu.findItem(R.id.create).setVisible(mIsCreate);
|
||||||
menu.findItem(R.id.delete).setVisible(!mIsCreate);
|
menu.findItem(R.id.delete).setVisible(!mIsCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.create:
|
case R.id.create:
|
||||||
if (mRepo.ID.equals("")) {
|
if (mRepo.ID.equals("")) {
|
||||||
Toast.makeText(getActivity(), R.string.repo_id_required, Toast.LENGTH_LONG)
|
Toast.makeText(getActivity(), R.string.repo_id_required, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mRepo.Directory.equals("")) {
|
if (mRepo.Directory.equals("")) {
|
||||||
Toast.makeText(getActivity(), R.string.repo_path_required, Toast.LENGTH_LONG)
|
Toast.makeText(getActivity(), R.string.repo_path_required, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
mSyncthingService.getApi().editRepo(mRepo, true, getActivity());
|
mSyncthingService.getApi().editRepo(mRepo, true, getActivity());
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return true;
|
return true;
|
||||||
case R.id.delete:
|
case R.id.delete:
|
||||||
new AlertDialog.Builder(getActivity())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setMessage(R.string.delete_repo_confirm)
|
.setMessage(R.string.delete_repo_confirm)
|
||||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
mSyncthingService.getApi().deleteRepo(mRepo, getActivity());
|
mSyncthingService.getApi().deleteRepo(mRepo, getActivity());
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.no, null)
|
.setNegativeButton(android.R.string.no, null)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||||
if (preference instanceof EditTextPreference) {
|
if (preference instanceof EditTextPreference) {
|
||||||
EditTextPreference pref = (EditTextPreference) preference;
|
EditTextPreference pref = (EditTextPreference) preference;
|
||||||
pref.setSummary((String) o);
|
pref.setSummary((String) o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preference.equals(mRepoId)) {
|
if (preference.equals(mRepoId)) {
|
||||||
mRepo.ID = (String) o;
|
mRepo.ID = (String) o;
|
||||||
repoUpdated();
|
repoUpdated();
|
||||||
return true;
|
return true;
|
||||||
}
|
} else if (preference.equals(mDirectory)) {
|
||||||
else if (preference.equals(mDirectory)) {
|
mRepo.Directory = (String) o;
|
||||||
mRepo.Directory = (String) o;
|
repoUpdated();
|
||||||
repoUpdated();
|
return true;
|
||||||
return true;
|
} else if (preference.equals(mRepoMaster)) {
|
||||||
}
|
mRepo.ReadOnly = (Boolean) o;
|
||||||
else if (preference.equals(mRepoMaster)) {
|
repoUpdated();
|
||||||
mRepo.ReadOnly = (Boolean) o;
|
return true;
|
||||||
repoUpdated();
|
} else if (preference.getKey().equals(KEY_NODE_SHARED)) {
|
||||||
return true;
|
ExtendedCheckBoxPreference pref = (ExtendedCheckBoxPreference) preference;
|
||||||
}
|
RestApi.Node node = (RestApi.Node) pref.getObject();
|
||||||
else if (preference.getKey().equals(KEY_NODE_SHARED)) {
|
if ((Boolean) o) {
|
||||||
ExtendedCheckBoxPreference pref = (ExtendedCheckBoxPreference) preference;
|
mRepo.Nodes.add(node);
|
||||||
RestApi.Node node = (RestApi.Node) pref.getObject();
|
} else {
|
||||||
if ((Boolean) o) {
|
for (RestApi.Node n : mRepo.Nodes) {
|
||||||
mRepo.Nodes.add(node);
|
if (n.NodeID.equals(node.NodeID)) {
|
||||||
}
|
mRepo.Nodes.remove(n);
|
||||||
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);
|
||||||
repoUpdated();
|
if ((Boolean) o) {
|
||||||
return true;
|
RestApi.SimpleVersioning v = new RestApi.SimpleVersioning();
|
||||||
}
|
mRepo.Versioning = v;
|
||||||
else if (preference.equals(mVersioning)) {
|
v.setParams(5);
|
||||||
mVersioningKeep.setEnabled((Boolean) o);
|
mVersioningKeep.setText("5");
|
||||||
if ((Boolean) o) {
|
mVersioningKeep.setSummary("5");
|
||||||
RestApi.SimpleVersioning v = new RestApi.SimpleVersioning();
|
} else {
|
||||||
mRepo.Versioning = v;
|
mRepo.Versioning = new RestApi.Versioning();
|
||||||
v.setParams(5);
|
}
|
||||||
mVersioningKeep.setText("5");
|
repoUpdated();
|
||||||
mVersioningKeep.setSummary("5");
|
return true;
|
||||||
}
|
} else if (preference.equals(mVersioningKeep)) {
|
||||||
else {
|
((RestApi.SimpleVersioning) mRepo.Versioning)
|
||||||
mRepo.Versioning = new RestApi.Versioning();
|
.setParams(Integer.parseInt((String) o));
|
||||||
}
|
repoUpdated();
|
||||||
repoUpdated();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
else if (preference.equals(mVersioningKeep)) {
|
|
||||||
((RestApi.SimpleVersioning) mRepo.Versioning)
|
|
||||||
.setParams(Integer.parseInt((String) o));
|
|
||||||
repoUpdated();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
if (preference.equals(mDirectory)) {
|
if (preference.equals(mDirectory)) {
|
||||||
Intent intent = new Intent(getActivity(), FolderPickerActivity.class)
|
Intent intent = new Intent(getActivity(), FolderPickerActivity.class)
|
||||||
.putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY,
|
.putExtra(FolderPickerActivity.EXTRA_INITIAL_DIRECTORY,
|
||||||
(mRepo.Directory.length() != 0)
|
(mRepo.Directory.length() != 0)
|
||||||
? mRepo.Directory
|
? mRepo.Directory
|
||||||
: Environment.getExternalStorageDirectory().getAbsolutePath());
|
: Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
startActivityForResult(intent, DIRECTORY_REQUEST_CODE);
|
);
|
||||||
}
|
startActivityForResult(intent, DIRECTORY_REQUEST_CODE);
|
||||||
else if (preference.equals(mNodes) && mSyncthingService.getApi().getNodes().isEmpty()) {
|
} else if (preference.equals(mNodes) && mSyncthingService.getApi().getNodes().isEmpty()) {
|
||||||
Toast.makeText(getActivity(), R.string.no_nodes, Toast.LENGTH_SHORT)
|
Toast.makeText(getActivity(), R.string.no_nodes, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (resultCode == Activity.RESULT_OK && requestCode == DIRECTORY_REQUEST_CODE) {
|
if (resultCode == Activity.RESULT_OK && requestCode == DIRECTORY_REQUEST_CODE) {
|
||||||
mRepo.Directory = data.getStringExtra(FolderPickerActivity.EXTRA_RESULT_DIRECTORY);
|
mRepo.Directory = data.getStringExtra(FolderPickerActivity.EXTRA_RESULT_DIRECTORY);
|
||||||
mDirectory.setSummary(mRepo.Directory);
|
mDirectory.setSummary(mRepo.Directory);
|
||||||
repoUpdated();
|
repoUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void repoUpdated() {
|
private void repoUpdated() {
|
||||||
if (!mIsCreate) {
|
if (!mIsCreate) {
|
||||||
mSyncthingService.getApi().editRepo(mRepo, false, getActivity());
|
mSyncthingService.getApi().editRepo(mRepo, false, getActivity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,80 +19,79 @@ import java.util.TimerTask;
|
||||||
* Displays a list of all existing repositories.
|
* Displays a list of all existing repositories.
|
||||||
*/
|
*/
|
||||||
public class ReposFragment extends ListFragment implements SyncthingService.OnApiChangeListener,
|
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
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
if (currentState != SyncthingService.State.ACTIVE)
|
if (currentState != SyncthingService.State.ACTIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
initAdapter();
|
initAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
initAdapter();
|
initAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initAdapter() {
|
private void initAdapter() {
|
||||||
MainActivity activity = (MainActivity) getActivity();
|
MainActivity activity = (MainActivity) getActivity();
|
||||||
if (activity == null || activity.getApi() == null)
|
if (activity == null || activity.getApi() == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mAdapter = new ReposAdapter(activity);
|
mAdapter = new ReposAdapter(activity);
|
||||||
mAdapter.add(activity.getApi().getRepos());
|
mAdapter.add(activity.getApi().getRepos());
|
||||||
setListAdapter(mAdapter);
|
setListAdapter(mAdapter);
|
||||||
setEmptyText(getString(R.string.repositories_list_empty));
|
setEmptyText(getString(R.string.repositories_list_empty));
|
||||||
getListView().setOnItemClickListener(this);
|
getListView().setOnItemClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateList() {
|
private void updateList() {
|
||||||
if (mAdapter == null || getView() == null)
|
if (mAdapter == null || getView() == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MainActivity activity = (MainActivity) getActivity();
|
MainActivity activity = (MainActivity) getActivity();
|
||||||
mAdapter.updateModel(activity.getApi(), getListView());
|
mAdapter.updateModel(activity.getApi(), getListView());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
|
|
||||||
if (isVisibleToUser) {
|
if (isVisibleToUser) {
|
||||||
mTimer = new Timer();
|
mTimer = new Timer();
|
||||||
mTimer.schedule(new TimerTask() {
|
mTimer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
updateList();
|
updateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
}, 0, SyncthingService.GUI_UPDATE_INTERVAL);
|
||||||
}
|
} else if (mTimer != null) {
|
||||||
else if (mTimer != null) {
|
mTimer.cancel();
|
||||||
mTimer.cancel();
|
mTimer = null;
|
||||||
mTimer = null;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
Intent intent = new Intent(getActivity(), SettingsActivity.class)
|
Intent intent = new Intent(getActivity(), SettingsActivity.class)
|
||||||
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
|
.setAction(SettingsActivity.ACTION_REPO_SETTINGS_FRAGMENT)
|
||||||
.putExtra(SettingsActivity.EXTRA_IS_CREATE, false)
|
.putExtra(SettingsActivity.EXTRA_IS_CREATE, false)
|
||||||
.putExtra(RepoSettingsFragment.EXTRA_REPO_ID, mAdapter.getItem(i).ID);
|
.putExtra(RepoSettingsFragment.EXTRA_REPO_ID, mAdapter.getItem(i).ID);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,139 +16,136 @@ import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceFragment
|
public class SettingsFragment extends PreferenceFragment
|
||||||
implements SyncthingActivity.OnServiceConnectedListener,
|
implements SyncthingActivity.OnServiceConnectedListener,
|
||||||
SyncthingService.OnApiChangeListener, Preference.OnPreferenceChangeListener {
|
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
|
@Override
|
||||||
public void onApiChange(SyncthingService.State currentState) {
|
public void onApiChange(SyncthingService.State currentState) {
|
||||||
mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
|
mOptionsScreen.setEnabled(currentState == SyncthingService.State.ACTIVE);
|
||||||
mGuiScreen.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) {
|
if (currentState == SyncthingService.State.ACTIVE) {
|
||||||
for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) {
|
for (int i = 0; i < mOptionsScreen.getPreferenceCount(); i++) {
|
||||||
Preference pref = mOptionsScreen.getPreference(i);
|
Preference pref = mOptionsScreen.getPreference(i);
|
||||||
pref.setOnPreferenceChangeListener(SettingsFragment.this);
|
pref.setOnPreferenceChangeListener(SettingsFragment.this);
|
||||||
String value = mSyncthingService.getApi()
|
String value = mSyncthingService.getApi()
|
||||||
.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
|
.getValue(RestApi.TYPE_OPTIONS, pref.getKey());
|
||||||
applyPreference(pref, value);
|
applyPreference(pref, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) {
|
for (int i = 0; i < mGuiScreen.getPreferenceCount(); i++) {
|
||||||
Preference pref = mGuiScreen.getPreference(i);
|
Preference pref = mGuiScreen.getPreference(i);
|
||||||
pref.setOnPreferenceChangeListener(SettingsFragment.this);
|
pref.setOnPreferenceChangeListener(SettingsFragment.this);
|
||||||
String value = mSyncthingService.getApi()
|
String value = mSyncthingService.getApi()
|
||||||
.getValue(RestApi.TYPE_GUI, pref.getKey());
|
.getValue(RestApi.TYPE_GUI, pref.getKey());
|
||||||
applyPreference(pref, value);
|
applyPreference(pref, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the given value to the preference.
|
* Applies the given value to the preference.
|
||||||
*
|
* <p/>
|
||||||
* If pref is an EditTextPreference, setText is used and the value shown as summary. If pref is
|
* 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).
|
* a CheckBoxPreference, setChecked is used (by parsing value as Boolean).
|
||||||
*/
|
*/
|
||||||
private void applyPreference(Preference pref, String value) {
|
private void applyPreference(Preference pref, String value) {
|
||||||
if (pref instanceof EditTextPreference) {
|
if (pref instanceof EditTextPreference) {
|
||||||
((EditTextPreference) pref).setText(value);
|
((EditTextPreference) pref).setText(value);
|
||||||
pref.setSummary(value);
|
pref.setSummary(value);
|
||||||
}
|
} else if (pref instanceof CheckBoxPreference) {
|
||||||
else if (pref instanceof CheckBoxPreference) {
|
((CheckBoxPreference) pref).setChecked(Boolean.parseBoolean(value));
|
||||||
((CheckBoxPreference) pref).setChecked(Boolean.parseBoolean(value));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads layout, sets version from Rest API.
|
* Loads layout, sets version from Rest API.
|
||||||
*
|
* <p/>
|
||||||
* Manual target API as we manually check if ActionBar is available (for ActionBar back button).
|
* Manual target API as we manually check if ActionBar is available (for ActionBar back button).
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
|
((SyncthingActivity) getActivity()).registerOnServiceConnectedListener(this);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.app_settings);
|
addPreferencesFromResource(R.xml.app_settings);
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
mStopNotCharging = (CheckBoxPreference) findPreference("stop_sync_on_mobile_data");
|
mStopNotCharging = (CheckBoxPreference) findPreference("stop_sync_on_mobile_data");
|
||||||
mStopNotCharging.setOnPreferenceChangeListener(this);
|
mStopNotCharging.setOnPreferenceChangeListener(this);
|
||||||
mStopMobileData = (CheckBoxPreference) findPreference("stop_sync_while_not_charging");
|
mStopMobileData = (CheckBoxPreference) findPreference("stop_sync_while_not_charging");
|
||||||
mStopMobileData.setOnPreferenceChangeListener(this);
|
mStopMobileData.setOnPreferenceChangeListener(this);
|
||||||
mVersion = screen.findPreference(SYNCTHING_VERSION_KEY);
|
mVersion = screen.findPreference(SYNCTHING_VERSION_KEY);
|
||||||
mOptionsScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_OPTIONS_KEY);
|
mOptionsScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_OPTIONS_KEY);
|
||||||
mGuiScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_GUI_KEY);
|
mGuiScreen = (PreferenceScreen) screen.findPreference(SYNCTHING_GUI_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected() {
|
public void onServiceConnected() {
|
||||||
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
mSyncthingService = ((SyncthingActivity) getActivity()).getService();
|
||||||
mSyncthingService.registerOnApiChangeListener(this);
|
mSyncthingService.registerOnApiChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles ActionBar back selected.
|
* Handles ActionBar back selected.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
NavUtils.navigateUpFromSameTask(getActivity());
|
NavUtils.navigateUpFromSameTask(getActivity());
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the updated value to {@link }RestApi}, and sets it as the summary
|
* Sends the updated value to {@link }RestApi}, and sets it as the summary
|
||||||
* for EditTextPreference.
|
* for EditTextPreference.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||||
if (preference instanceof EditTextPreference) {
|
if (preference instanceof EditTextPreference) {
|
||||||
String value = (String) o;
|
String value = (String) o;
|
||||||
preference.setSummary(value);
|
preference.setSummary(value);
|
||||||
EditTextPreference etp = (EditTextPreference) preference;
|
EditTextPreference etp = (EditTextPreference) preference;
|
||||||
if (etp.getEditText().getInputType() == InputType.TYPE_CLASS_NUMBER) {
|
if (etp.getEditText().getInputType() == InputType.TYPE_CLASS_NUMBER) {
|
||||||
o = Integer.parseInt((String) o);
|
o = Integer.parseInt((String) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preference.equals(mStopNotCharging) || preference.equals(mStopMobileData)) {
|
if (preference.equals(mStopNotCharging) || preference.equals(mStopMobileData)) {
|
||||||
mSyncthingService.updateState();
|
mSyncthingService.updateState();
|
||||||
}
|
} else if (mOptionsScreen.findPreference(preference.getKey()) != null) {
|
||||||
else if (mOptionsScreen.findPreference(preference.getKey()) != null) {
|
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o,
|
||||||
mSyncthingService.getApi().setValue(RestApi.TYPE_OPTIONS, preference.getKey(), o,
|
preference.getKey().equals("ListenAddress"), getActivity());
|
||||||
preference.getKey().equals("ListenAddress"), getActivity());
|
} else if (mGuiScreen.findPreference(preference.getKey()) != null) {
|
||||||
}
|
mSyncthingService.getApi().setValue(
|
||||||
else if (mGuiScreen.findPreference(preference.getKey()) != null) {
|
RestApi.TYPE_GUI, preference.getKey(), o, false, getActivity());
|
||||||
mSyncthingService.getApi().setValue(
|
}
|
||||||
RestApi.TYPE_GUI, preference.getKey(), o, false, getActivity());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ import android.content.Intent;
|
||||||
*/
|
*/
|
||||||
public class BatteryReceiver extends BroadcastReceiver {
|
public class BatteryReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
boolean isCharging = Intent.ACTION_POWER_CONNECTED.equals(intent.getAction());
|
boolean isCharging = Intent.ACTION_POWER_CONNECTED.equals(intent.getAction());
|
||||||
Intent i = new Intent(context, SyncthingService.class);
|
Intent i = new Intent(context, SyncthingService.class);
|
||||||
i.putExtra(DeviceStateHolder.EXTRA_IS_CHARGING, isCharging);
|
i.putExtra(DeviceStateHolder.EXTRA_IS_CHARGING, isCharging);
|
||||||
context.startService(i);
|
context.startService(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import android.os.BatteryManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds information about the current wifi and charging state of the device.
|
* Holds information about the current wifi and charging state of the device.
|
||||||
*
|
* <p/>
|
||||||
* This information is actively read on construction, and then updated from intents that are passed
|
* This information is actively read on construction, and then updated from intents that are passed
|
||||||
* to {@link #update(android.content.Intent)}.
|
* 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.
|
* 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
|
* Intent extra containging a boolean saying whether the device is
|
||||||
* charging or not (any power source).
|
* 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;
|
private SyncthingService mService;
|
||||||
|
|
||||||
public DeviceStateHolder(SyncthingService service) {
|
public DeviceStateHolder(SyncthingService service) {
|
||||||
mService = service;
|
mService = service;
|
||||||
ConnectivityManager cm = (ConnectivityManager)
|
ConnectivityManager cm = (ConnectivityManager)
|
||||||
mService.getSystemService(Context.CONNECTIVITY_SERVICE);
|
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) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
context.unregisterReceiver(this);
|
context.unregisterReceiver(this);
|
||||||
int status = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
int status = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||||
|
@ -48,16 +48,16 @@ public class DeviceStateHolder extends BroadcastReceiver {
|
||||||
mIsInitialized = true;
|
mIsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCharging() {
|
public boolean isCharging() {
|
||||||
return mIsCharging;
|
return mIsCharging;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWifiConnected() {
|
public boolean isWifiConnected() {
|
||||||
return mIsWifiConnected;
|
return mIsWifiConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(Intent intent) {
|
public void update(Intent intent) {
|
||||||
mIsWifiConnected = intent.getBooleanExtra(EXTRA_HAS_WIFI, mIsWifiConnected);
|
mIsWifiConnected = intent.getBooleanExtra(EXTRA_HAS_WIFI, mIsWifiConnected);
|
||||||
mIsCharging = intent.getBooleanExtra(EXTRA_IS_CHARGING, mIsCharging);
|
mIsCharging = intent.getBooleanExtra(EXTRA_IS_CHARGING, mIsCharging);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,60 +25,59 @@ import java.util.LinkedList;
|
||||||
*/
|
*/
|
||||||
public class GetTask extends AsyncTask<String, Void, String> {
|
public class GetTask extends AsyncTask<String, Void, String> {
|
||||||
|
|
||||||
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[0] Syncthing hostname
|
||||||
* params[1] URI to call
|
* params[1] URI to call
|
||||||
* params[2] Syncthing API key
|
* params[2] Syncthing API key
|
||||||
* params[3] optional parameter key
|
* params[3] optional parameter key
|
||||||
* params[4] optional parameter value
|
* params[4] optional parameter value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected String doInBackground(String... params) {
|
protected String doInBackground(String... params) {
|
||||||
String fullUri = params[0] + params[1];
|
String fullUri = params[0] + params[1];
|
||||||
HttpClient httpclient = new DefaultHttpClient();
|
HttpClient httpclient = new DefaultHttpClient();
|
||||||
if (params.length == 5) {
|
if (params.length == 5) {
|
||||||
LinkedList<NameValuePair> urlParams = new LinkedList<>();
|
LinkedList<NameValuePair> urlParams = new LinkedList<>();
|
||||||
urlParams.add(new BasicNameValuePair(params[3], params[4]));
|
urlParams.add(new BasicNameValuePair(params[3], params[4]));
|
||||||
fullUri += "?" + URLEncodedUtils.format(urlParams, "utf-8");
|
fullUri += "?" + URLEncodedUtils.format(urlParams, "utf-8");
|
||||||
}
|
}
|
||||||
HttpGet get = new HttpGet(fullUri);
|
HttpGet get = new HttpGet(fullUri);
|
||||||
get.addHeader(new BasicHeader("X-API-Key", params[2]));
|
get.addHeader(new BasicHeader("X-API-Key", params[2]));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpResponse response = httpclient.execute(get);
|
HttpResponse response = httpclient.execute(get);
|
||||||
HttpEntity entity = response.getEntity();
|
HttpEntity entity = response.getEntity();
|
||||||
|
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
InputStream is = entity.getContent();
|
InputStream is = entity.getContent();
|
||||||
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||||
String line;
|
String line;
|
||||||
String result = "";
|
String result = "";
|
||||||
while((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
result += line;
|
result += line;
|
||||||
}
|
}
|
||||||
br.close();
|
br.close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
Log.w(TAG, "Failed to call Rest API at " + fullUri, e);
|
||||||
Log.w(TAG, "Failed to call Rest API at " + fullUri, e);
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,17 @@ import android.net.NetworkInfo;
|
||||||
*/
|
*/
|
||||||
public class NetworkReceiver extends BroadcastReceiver {
|
public class NetworkReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
ConnectivityManager cm =
|
ConnectivityManager cm =
|
||||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||||
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
||||||
boolean isWifiConnected = (wifiInfo != null && wifiInfo.isConnected()) ||
|
boolean isWifiConnected = (wifiInfo != null && wifiInfo.isConnected()) ||
|
||||||
activeNetworkInfo == null;
|
activeNetworkInfo == null;
|
||||||
Intent i = new Intent(context, SyncthingService.class);
|
Intent i = new Intent(context, SyncthingService.class);
|
||||||
i.putExtra(DeviceStateHolder.EXTRA_HAS_WIFI, isWifiConnected);
|
i.putExtra(DeviceStateHolder.EXTRA_HAS_WIFI, isWifiConnected);
|
||||||
context.startService(i);
|
context.startService(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,37 +16,36 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
public class PostTask extends AsyncTask<String, Void, Void> {
|
public class PostTask extends AsyncTask<String, Void, Void> {
|
||||||
|
|
||||||
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[0] Syncthing hostname
|
||||||
* params[1] URI to call
|
* params[1] URI to call
|
||||||
* params[2] Syncthing API key
|
* params[2] Syncthing API key
|
||||||
* params[3] The request content (optional)
|
* params[3] The request content (optional)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(String... params) {
|
protected Void doInBackground(String... params) {
|
||||||
String fullUri = params[0] + params[1];
|
String fullUri = params[0] + params[1];
|
||||||
HttpClient httpclient = new DefaultHttpClient();
|
HttpClient httpclient = new DefaultHttpClient();
|
||||||
HttpPost post = new HttpPost(fullUri);
|
HttpPost post = new HttpPost(fullUri);
|
||||||
post.addHeader(new BasicHeader("X-API-Key", params[2]));
|
post.addHeader(new BasicHeader("X-API-Key", params[2]));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (params.length > 3) {
|
if (params.length > 3) {
|
||||||
post.setEntity(new StringEntity(params[3]));
|
post.setEntity(new StringEntity(params[3]));
|
||||||
}
|
}
|
||||||
httpclient.execute(post);
|
httpclient.execute(post);
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
Log.w(TAG, "Failed to call Rest API at " + fullUri, e);
|
||||||
Log.w(TAG, "Failed to call Rest API at " + fullUri, e);
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,7 +43,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
DataOutputStream dos = null;
|
DataOutputStream dos = null;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
Process process = null;
|
Process process = null;
|
||||||
try {
|
try {
|
||||||
process = Runtime.getRuntime().exec("sh");
|
process = Runtime.getRuntime().exec("sh");
|
||||||
dos = new DataOutputStream(process.getOutputStream());
|
dos = new DataOutputStream(process.getOutputStream());
|
||||||
// Set home directory to data folder for syncthing to use.
|
// Set home directory to data folder for syncthing to use.
|
||||||
|
@ -57,22 +57,19 @@ public class SyncthingRunnable implements Runnable {
|
||||||
log(process.getInputStream());
|
log(process.getInputStream());
|
||||||
|
|
||||||
ret = process.waitFor();
|
ret = process.waitFor();
|
||||||
}
|
} catch (IOException | InterruptedException e) {
|
||||||
catch(IOException | InterruptedException e) {
|
|
||||||
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
try {
|
try {
|
||||||
dos.close();
|
dos.close();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
|
||||||
Log.w(TAG, "Failed to close shell stream", e);
|
Log.w(TAG, "Failed to close shell stream", e);
|
||||||
}
|
}
|
||||||
process.destroy();
|
process.destroy();
|
||||||
final int retVal = ret;
|
final int retVal = ret;
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " + Integer.toString(retVal));
|
Log.w(TAG_NATIVE, "Syncthing binary crashed with error code " + Integer.toString(retVal));
|
||||||
postCrashDialog(retVal);
|
postCrashDialog(retVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +92,8 @@ public class SyncthingRunnable implements Runnable {
|
||||||
int i) {
|
int i) {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
.create();
|
.create();
|
||||||
dialog.getWindow()
|
dialog.getWindow()
|
||||||
.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||||
|
@ -120,8 +118,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
Log.i(TAG_NATIVE, line);
|
Log.i(TAG_NATIVE, line);
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
|
||||||
// NOTE: This is sometimes called on shutdown, as
|
// NOTE: This is sometimes called on shutdown, as
|
||||||
// Process.destroy() closes the stream.
|
// Process.destroy() closes the stream.
|
||||||
Log.w(TAG, "Failed to read syncthing command line output", e);
|
Log.w(TAG, "Failed to read syncthing command line output", e);
|
||||||
|
|
|
@ -40,56 +40,56 @@ import java.util.Iterator;
|
||||||
*/
|
*/
|
||||||
public class SyncthingService extends Service {
|
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.
|
* Intent action to perform a syncthing restart.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_RESTART = "restart";
|
public static final String ACTION_RESTART = "restart";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interval in ms at which the GUI is updated (eg {@link }LocalNodeInfoFragment}).
|
* Interval in ms at which the GUI is updated (eg {@link }LocalNodeInfoFragment}).
|
||||||
*/
|
*/
|
||||||
public static final int GUI_UPDATE_INTERVAL = 1000;
|
public static final int GUI_UPDATE_INTERVAL = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interval in ms, at which connections to the web gui are performed on first start
|
* Interval in ms, at which connections to the web gui are performed on first start
|
||||||
* to find out if it's online.
|
* to find out if it's online.
|
||||||
*/
|
*/
|
||||||
private static final long WEB_GUI_POLL_INTERVAL = 100;
|
private static final long WEB_GUI_POLL_INTERVAL = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the public key file in the data directory.
|
* Name of the public key file in the data directory.
|
||||||
*/
|
*/
|
||||||
private static final String PUBLIC_KEY_FILE = "cert.pem";
|
private static final String PUBLIC_KEY_FILE = "cert.pem";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the private key file in the data directory.
|
* Name of the private key file in the data directory.
|
||||||
*/
|
*/
|
||||||
private static final String PRIVATE_KEY_FILE = "key.pem";
|
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.
|
* Callback for when the Syncthing web interface becomes first available after service start.
|
||||||
*/
|
*/
|
||||||
public interface OnWebGuiAvailableListener {
|
public interface OnWebGuiAvailableListener {
|
||||||
public void onWebGuiAvailable();
|
public void onWebGuiAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final HashSet<OnWebGuiAvailableListener> mOnWebGuiAvailableListeners =
|
private final HashSet<OnWebGuiAvailableListener> mOnWebGuiAvailableListeners =
|
||||||
new HashSet<>();
|
new HashSet<>();
|
||||||
|
|
||||||
public interface OnApiChangeListener {
|
public interface OnApiChangeListener {
|
||||||
public void onApiChange(State currentState);
|
public void onApiChange(State currentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final HashSet<WeakReference<OnApiChangeListener>> mOnApiChangeListeners =
|
private final HashSet<WeakReference<OnApiChangeListener>> mOnApiChangeListeners =
|
||||||
new HashSet<>();
|
new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INIT: Service is starting up and initializing.
|
* INIT: Service is starting up and initializing.
|
||||||
|
@ -97,334 +97,328 @@ public class SyncthingService extends Service {
|
||||||
* ACTIVE: Syncthing binary is up and running.
|
* ACTIVE: Syncthing binary is up and running.
|
||||||
* DISABLED: Syncthing binary is stopped according to user preferences.
|
* DISABLED: Syncthing binary is stopped according to user preferences.
|
||||||
*/
|
*/
|
||||||
public enum State {
|
public enum State {
|
||||||
INIT,
|
INIT,
|
||||||
STARTING,
|
STARTING,
|
||||||
ACTIVE,
|
ACTIVE,
|
||||||
DISABLED
|
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
|
* True if a stop was requested while syncthing is starting, in that case, perform stop in
|
||||||
* {@link PollWebGuiAvailableTask}.
|
* {@link PollWebGuiAvailableTask}.
|
||||||
*/
|
*/
|
||||||
private boolean mStopScheduled = false;
|
private boolean mStopScheduled = false;
|
||||||
|
|
||||||
private DeviceStateHolder mDeviceStateHolder;
|
private DeviceStateHolder mDeviceStateHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles intents, either {@link #ACTION_RESTART}, or intents having
|
* Handles intents, either {@link #ACTION_RESTART}, or intents having
|
||||||
* {@link DeviceStateHolder.EXTRA_HAS_WIFI} or {@link DeviceStateHolder.EXTRA_IS_CHARGING}
|
* {@link DeviceStateHolder.EXTRA_HAS_WIFI} or {@link DeviceStateHolder.EXTRA_IS_CHARGING}
|
||||||
* (which are handled by {@link DeviceStateHolder}.
|
* (which are handled by {@link DeviceStateHolder}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
// Just catch the empty intent and return.
|
// Just catch the empty intent and return.
|
||||||
if (intent == null) {
|
if (intent == null) {
|
||||||
}
|
} else if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
|
||||||
else if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
|
new PostTask() {
|
||||||
new PostTask() {
|
@Override
|
||||||
@Override
|
protected void onPostExecute(Void aVoid) {
|
||||||
protected void onPostExecute(Void aVoid) {
|
ConfigXml config = new ConfigXml(SyncthingService.this);
|
||||||
ConfigXml config = new ConfigXml(SyncthingService.this);
|
mApi = new RestApi(SyncthingService.this,
|
||||||
mApi = new RestApi(SyncthingService.this,
|
config.getWebGuiUrl(), config.getApiKey());
|
||||||
config.getWebGuiUrl(), config.getApiKey());
|
mCurrentState = State.STARTING;
|
||||||
mCurrentState = State.STARTING;
|
registerOnWebGuiAvailableListener(mApi);
|
||||||
registerOnWebGuiAvailableListener(mApi);
|
new PollWebGuiAvailableTask().execute();
|
||||||
new PollWebGuiAvailableTask().execute();
|
}
|
||||||
}
|
}.execute(mApi.getUrl(), PostTask.URI_RESTART, mApi.getApiKey());
|
||||||
}.execute(mApi.getUrl(), PostTask.URI_RESTART, mApi.getApiKey());
|
} else if (mCurrentState != State.INIT) {
|
||||||
}
|
mDeviceStateHolder.update(intent);
|
||||||
else if (mCurrentState != State.INIT) {
|
updateState();
|
||||||
mDeviceStateHolder.update(intent);
|
}
|
||||||
updateState();
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
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.
|
* or not.
|
||||||
*
|
* <p/>
|
||||||
* Depending on the result, syncthing is started or stopped, and {@link #onApiChange()} is
|
* Depending on the result, syncthing is started or stopped, and {@link #onApiChange()} is
|
||||||
* called.
|
* called.
|
||||||
*/
|
*/
|
||||||
public void updateState() {
|
public void updateState() {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
boolean prefStopMobileData = prefs.getBoolean("stop_sync_on_mobile_data", true);
|
boolean prefStopMobileData = prefs.getBoolean("stop_sync_on_mobile_data", true);
|
||||||
boolean prefStopNotCharging = prefs.getBoolean("stop_sync_while_not_charging", true);
|
boolean prefStopNotCharging = prefs.getBoolean("stop_sync_while_not_charging", true);
|
||||||
|
|
||||||
// Start syncthing.
|
// Start syncthing.
|
||||||
if ((mDeviceStateHolder.isCharging() || !prefStopNotCharging) &&
|
if ((mDeviceStateHolder.isCharging() || !prefStopNotCharging) &&
|
||||||
(mDeviceStateHolder.isWifiConnected() || !prefStopMobileData)) {
|
(mDeviceStateHolder.isWifiConnected() || !prefStopMobileData)) {
|
||||||
if (mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) {
|
if (mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) {
|
||||||
mStopScheduled = false;
|
mStopScheduled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentState = State.STARTING;
|
mCurrentState = State.STARTING;
|
||||||
registerOnWebGuiAvailableListener(mApi);
|
registerOnWebGuiAvailableListener(mApi);
|
||||||
new PollWebGuiAvailableTask().execute();
|
new PollWebGuiAvailableTask().execute();
|
||||||
new Thread(new SyncthingRunnable(this)).start();
|
new Thread(new SyncthingRunnable(this)).start();
|
||||||
}
|
}
|
||||||
// Stop syncthing.
|
// Stop syncthing.
|
||||||
else {
|
else {
|
||||||
if (mCurrentState == State.DISABLED)
|
if (mCurrentState == State.DISABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mCurrentState = State.DISABLED;
|
mCurrentState = State.DISABLED;
|
||||||
|
|
||||||
// Syncthing is currently started, perform the stop later.
|
// Syncthing is currently started, perform the stop later.
|
||||||
if (mCurrentState == State.STARTING) {
|
if (mCurrentState == State.STARTING) {
|
||||||
mStopScheduled = true;
|
mStopScheduled = true;
|
||||||
} else if (mApi != null) {
|
} else if (mApi != null) {
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onApiChange();
|
onApiChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners
|
* Polls SYNCTHING_URL until it returns HTTP status OK, then calls all listeners
|
||||||
* in mOnWebGuiAvailableListeners and clears it.
|
* in mOnWebGuiAvailableListeners and clears it.
|
||||||
*/
|
*/
|
||||||
private class PollWebGuiAvailableTask extends AsyncTask<Void, Void, Void> {
|
private class PollWebGuiAvailableTask extends AsyncTask<Void, Void, Void> {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
int status = 0;
|
int status = 0;
|
||||||
HttpClient httpclient = new DefaultHttpClient();
|
HttpClient httpclient = new DefaultHttpClient();
|
||||||
HttpHead head = new HttpHead(mApi.getUrl());
|
HttpHead head = new HttpHead(mApi.getUrl());
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(WEB_GUI_POLL_INTERVAL);
|
Thread.sleep(WEB_GUI_POLL_INTERVAL);
|
||||||
HttpResponse response = httpclient.execute(head);
|
HttpResponse response = httpclient.execute(head);
|
||||||
// NOTE: status is not really needed, as HttpHostConnectException is thrown
|
// NOTE: status is not really needed, as HttpHostConnectException is thrown
|
||||||
// earlier.
|
// earlier.
|
||||||
status = response.getStatusLine().getStatusCode();
|
status = response.getStatusLine().getStatusCode();
|
||||||
}
|
} catch (HttpHostConnectException e) {
|
||||||
catch (HttpHostConnectException e) {
|
// We catch this in every call, as long as the service is not online,
|
||||||
// We catch this in every call, as long as the service is not online,
|
// so we ignore and continue.
|
||||||
// so we ignore and continue.
|
} catch (IOException e) {
|
||||||
}
|
Log.w(TAG, "Failed to poll for web interface", e);
|
||||||
catch (IOException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.w(TAG, "Failed to poll for web interface", e);
|
Log.w(TAG, "Failed to poll for web interface", e);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
} while (status != HttpStatus.SC_OK);
|
||||||
Log.w(TAG, "Failed to poll for web interface", e);
|
return null;
|
||||||
}
|
}
|
||||||
} while(status != HttpStatus.SC_OK);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void aVoid) {
|
protected void onPostExecute(Void aVoid) {
|
||||||
if (mStopScheduled) {
|
if (mStopScheduled) {
|
||||||
mCurrentState = State.DISABLED;
|
mCurrentState = State.DISABLED;
|
||||||
onApiChange();
|
onApiChange();
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
mStopScheduled = false;
|
mStopScheduled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Web GUI has come online at " + mApi.getUrl());
|
Log.i(TAG, "Web GUI has come online at " + mApi.getUrl());
|
||||||
mCurrentState = State.ACTIVE;
|
mCurrentState = State.ACTIVE;
|
||||||
for (OnWebGuiAvailableListener listener : mOnWebGuiAvailableListeners) {
|
for (OnWebGuiAvailableListener listener : mOnWebGuiAvailableListeners) {
|
||||||
listener.onWebGuiAvailable();
|
listener.onWebGuiAvailable();
|
||||||
}
|
}
|
||||||
mOnWebGuiAvailableListeners.clear();
|
mOnWebGuiAvailableListeners.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move config file, keys, and index files to "official" folder
|
* Move config file, keys, and index files to "official" folder
|
||||||
*
|
* <p/>
|
||||||
* Intended to bring the file locations in older installs in line with
|
* Intended to bring the file locations in older installs in line with
|
||||||
* newer versions.
|
* newer versions.
|
||||||
*/
|
*/
|
||||||
private void moveConfigFiles() {
|
private void moveConfigFiles() {
|
||||||
FilenameFilter idxFilter = new FilenameFilter() {
|
FilenameFilter idxFilter = new FilenameFilter() {
|
||||||
public boolean accept(File dir, String name) {
|
public boolean accept(File dir, String name) {
|
||||||
return name.endsWith(".idx.gz");
|
return name.endsWith(".idx.gz");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE).exists()) {
|
if (new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE).exists()) {
|
||||||
File publicKey = new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE);
|
File publicKey = new File(getApplicationInfo().dataDir, PUBLIC_KEY_FILE);
|
||||||
publicKey.renameTo(new File(getFilesDir(), PUBLIC_KEY_FILE));
|
publicKey.renameTo(new File(getFilesDir(), PUBLIC_KEY_FILE));
|
||||||
File privateKey = new File(getApplicationInfo().dataDir, PRIVATE_KEY_FILE);
|
File privateKey = new File(getApplicationInfo().dataDir, PRIVATE_KEY_FILE);
|
||||||
privateKey.renameTo(new File(getFilesDir(), PRIVATE_KEY_FILE));
|
privateKey.renameTo(new File(getFilesDir(), PRIVATE_KEY_FILE));
|
||||||
File config = new File(getApplicationInfo().dataDir, ConfigXml.CONFIG_FILE);
|
File config = new File(getApplicationInfo().dataDir, ConfigXml.CONFIG_FILE);
|
||||||
config.renameTo(new File(getFilesDir(), ConfigXml.CONFIG_FILE));
|
config.renameTo(new File(getFilesDir(), ConfigXml.CONFIG_FILE));
|
||||||
|
|
||||||
File oldStorageDir = new File(getApplicationInfo().dataDir);
|
File oldStorageDir = new File(getApplicationInfo().dataDir);
|
||||||
File[] files = oldStorageDir.listFiles(idxFilter);
|
File[] files = oldStorageDir.listFiles(idxFilter);
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
file.renameTo(new File(getFilesDir(), file.getName()));
|
file.renameTo(new File(getFilesDir(), file.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates notification, starts native binary.
|
* Creates notification, starts native binary.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
PendingIntent pi = PendingIntent.getActivity(
|
PendingIntent pi = PendingIntent.getActivity(
|
||||||
this, 0, new Intent(this, MainActivity.class),
|
this, 0, new Intent(this, MainActivity.class),
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
Notification n = new NotificationCompat.Builder(this)
|
Notification n = new NotificationCompat.Builder(this)
|
||||||
.setContentTitle(getString(R.string.app_name))
|
.setContentTitle(getString(R.string.app_name))
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_launcher)
|
||||||
.setContentIntent(pi)
|
.setContentIntent(pi)
|
||||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||||
.build();
|
.build();
|
||||||
n.flags |= Notification.FLAG_ONGOING_EVENT;
|
n.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||||
startForeground(NOTIFICATION_RUNNING, n);
|
startForeground(NOTIFICATION_RUNNING, n);
|
||||||
|
|
||||||
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this);
|
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this);
|
||||||
registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
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
|
* 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
|
* version, and reads syncthing URL and API key (these are passed internally as
|
||||||
* {@code Pair<String, String>}.
|
* {@code Pair<String, String>}.
|
||||||
*/
|
*/
|
||||||
private class StartupTask extends AsyncTask<Void, Void, Pair<String, String>> {
|
private class StartupTask extends AsyncTask<Void, Void, Pair<String, String>> {
|
||||||
@Override
|
@Override
|
||||||
protected Pair<String, String> doInBackground(Void... voids) {
|
protected Pair<String, String> doInBackground(Void... voids) {
|
||||||
moveConfigFiles();
|
moveConfigFiles();
|
||||||
ConfigXml config = new ConfigXml(SyncthingService.this);
|
ConfigXml config = new ConfigXml(SyncthingService.this);
|
||||||
config.updateIfNeeded();
|
config.updateIfNeeded();
|
||||||
|
|
||||||
if (isFirstStart()) {
|
if (isFirstStart()) {
|
||||||
Log.i(TAG, "App started for the first time. " +
|
Log.i(TAG, "App started for the first time. " +
|
||||||
"Copying default config, keys will be generated automatically");
|
"Copying default config, keys will be generated automatically");
|
||||||
config.createCameraRepo();
|
config.createCameraRepo();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pair<>(config.getWebGuiUrl(), config.getApiKey());
|
return new Pair<>(config.getWebGuiUrl(), config.getApiKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Pair<String, String> urlAndKey) {
|
protected void onPostExecute(Pair<String, String> urlAndKey) {
|
||||||
mApi = new RestApi(SyncthingService.this, urlAndKey.first, urlAndKey.second);
|
mApi = new RestApi(SyncthingService.this, urlAndKey.first, urlAndKey.second);
|
||||||
Log.i(TAG, "Web GUI will be available at " + mApi.getUrl());
|
Log.i(TAG, "Web GUI will be available at " + mApi.getUrl());
|
||||||
|
|
||||||
// HACK: Make sure there is no syncthing binary left running from an improper
|
// HACK: Make sure there is no syncthing binary left running from an improper
|
||||||
// shutdown (eg Play Store updateIfNeeded).
|
// shutdown (eg Play Store updateIfNeeded).
|
||||||
// NOTE: This will log an exception if syncthing is not actually running.
|
// NOTE: This will log an exception if syncthing is not actually running.
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the native binary.
|
* Stops the native binary.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
Log.i(TAG, "Shutting down service");
|
Log.i(TAG, "Shutting down service");
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a listener for the web gui becoming available..
|
* Register a listener for the web gui becoming available..
|
||||||
*
|
* <p/>
|
||||||
* If the web gui is already available, listener will be called immediately.
|
* If the web gui is already available, listener will be called immediately.
|
||||||
* Listeners are unregistered automatically after being called.
|
* Listeners are unregistered automatically after being called.
|
||||||
*/
|
*/
|
||||||
public void registerOnWebGuiAvailableListener(OnWebGuiAvailableListener listener) {
|
public void registerOnWebGuiAvailableListener(OnWebGuiAvailableListener listener) {
|
||||||
if (mCurrentState == State.ACTIVE) {
|
if (mCurrentState == State.ACTIVE) {
|
||||||
listener.onWebGuiAvailable();
|
listener.onWebGuiAvailable();
|
||||||
}
|
} else {
|
||||||
else {
|
mOnWebGuiAvailableListeners.add(listener);
|
||||||
mOnWebGuiAvailableListeners.add(listener);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this service has not been started before (ie config.xml does not exist).
|
* Returns true if this service has not been started before (ie config.xml does not exist).
|
||||||
*
|
* <p/>
|
||||||
* This will return true until the public key file has been generated.
|
* This will return true until the public key file has been generated.
|
||||||
*/
|
*/
|
||||||
public boolean isFirstStart() {
|
public boolean isFirstStart() {
|
||||||
return !new File(getFilesDir(), PUBLIC_KEY_FILE).exists();
|
return !new File(getFilesDir(), PUBLIC_KEY_FILE).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestApi getApi() {
|
public RestApi getApi() {
|
||||||
return mApi;
|
return mApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a listener for the syncthing API state changing.
|
* Register a listener for the syncthing API state changing.
|
||||||
*
|
* <p/>
|
||||||
* The listener is called immediately with the current state, and again whenever the state
|
* The listener is called immediately with the current state, and again whenever the state
|
||||||
* changes.
|
* changes.
|
||||||
*/
|
*/
|
||||||
public void registerOnApiChangeListener(OnApiChangeListener listener) {
|
public void registerOnApiChangeListener(OnApiChangeListener listener) {
|
||||||
// Make sure we don't send an invalid state or syncthing might shwow a "disabled" message
|
// Make sure we don't send an invalid state or syncthing might shwow a "disabled" message
|
||||||
// when it's just starting up.
|
// when it's just starting up.
|
||||||
listener.onApiChange(mCurrentState);
|
listener.onApiChange(mCurrentState);
|
||||||
mOnApiChangeListeners.add(new WeakReference<OnApiChangeListener>(listener));
|
mOnApiChangeListeners.add(new WeakReference<OnApiChangeListener>(listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to notifiy listeners of an API change.
|
* Called to notifiy listeners of an API change.
|
||||||
*
|
* <p/>
|
||||||
* Must only be called from SyncthingService or {@link RestApi}.
|
* Must only be called from SyncthingService or {@link RestApi}.
|
||||||
*/
|
*/
|
||||||
public void onApiChange() {
|
public void onApiChange() {
|
||||||
for (Iterator<WeakReference<OnApiChangeListener>> i = mOnApiChangeListeners.iterator();
|
for (Iterator<WeakReference<OnApiChangeListener>> i = mOnApiChangeListeners.iterator();
|
||||||
i.hasNext(); ) {
|
i.hasNext(); ) {
|
||||||
WeakReference<OnApiChangeListener> listener = i.next();
|
WeakReference<OnApiChangeListener> listener = i.next();
|
||||||
if (listener.get() != null) {
|
if (listener.get() != null) {
|
||||||
listener.get().onApiChange(mCurrentState);
|
listener.get().onApiChange(mCurrentState);
|
||||||
}
|
} else {
|
||||||
else {
|
i.remove();
|
||||||
i.remove();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to be shown when attempting to start syncthing while it is disabled according
|
* 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).
|
* to settings (because the device is not charging or wifi is disconnected).
|
||||||
*/
|
*/
|
||||||
public static void showDisabledDialog(final Activity activity) {
|
public static void showDisabledDialog(final Activity activity) {
|
||||||
new AlertDialog.Builder(activity)
|
new AlertDialog.Builder(activity)
|
||||||
.setTitle(R.string.syncthing_disabled_title)
|
.setTitle(R.string.syncthing_disabled_title)
|
||||||
.setMessage(R.string.syncthing_disabled_message)
|
.setMessage(R.string.syncthing_disabled_message)
|
||||||
.setPositiveButton(R.string.syncthing_disabled_change_settings,
|
.setPositiveButton(R.string.syncthing_disabled_change_settings,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
activity.finish();
|
activity.finish();
|
||||||
Intent intent = new Intent(activity, SettingsActivity.class)
|
Intent intent = new Intent(activity, SettingsActivity.class)
|
||||||
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT);
|
.setAction(SettingsActivity.ACTION_APP_SETTINGS_FRAGMENT);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.setNegativeButton(R.string.exit,
|
)
|
||||||
new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.exit,
|
||||||
@Override
|
new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
@Override
|
||||||
activity.finish();
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
}
|
activity.finish();
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
.show()
|
)
|
||||||
.setCancelable(false);
|
.show()
|
||||||
}
|
.setCancelable(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@ import android.os.Binder;
|
||||||
|
|
||||||
public class SyncthingServiceBinder extends Binder {
|
public class SyncthingServiceBinder extends Binder {
|
||||||
|
|
||||||
private final SyncthingService mService;
|
private final SyncthingService mService;
|
||||||
|
|
||||||
public SyncthingServiceBinder(SyncthingService service) {
|
public SyncthingServiceBinder(SyncthingService service) {
|
||||||
mService = service;
|
mService = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyncthingService getService() {
|
public SyncthingService getService() {
|
||||||
return mService;
|
return mService;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,184 +28,180 @@ import javax.xml.transform.stream.StreamResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides direct access to the config.xml file in the file system.
|
* Provides direct access to the config.xml file in the file system.
|
||||||
*
|
* <p/>
|
||||||
* This class should only be used if the syncthing API is not available (usually during startup).
|
* This class should only be used if the syncthing API is not available (usually during startup).
|
||||||
*/
|
*/
|
||||||
public class ConfigXml {
|
public class ConfigXml {
|
||||||
|
|
||||||
private static final String TAG = "ConfigXml";
|
private static final String TAG = "ConfigXml";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File in the config folder that contains configuration.
|
* File in the config folder that contains configuration.
|
||||||
*/
|
*/
|
||||||
public static final String CONFIG_FILE = "config.xml";
|
public static final String CONFIG_FILE = "config.xml";
|
||||||
|
|
||||||
private File mConfigFile;
|
private File mConfigFile;
|
||||||
|
|
||||||
private Document mConfig;
|
private Document mConfig;
|
||||||
|
|
||||||
public ConfigXml(Context context) {
|
public ConfigXml(Context context) {
|
||||||
mConfigFile = new File(context.getFilesDir(), CONFIG_FILE);
|
mConfigFile = new File(context.getFilesDir(), CONFIG_FILE);
|
||||||
if (!mConfigFile.exists()) {
|
if (!mConfigFile.exists()) {
|
||||||
copyDefaultConfig(context);
|
copyDefaultConfig(context);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
mConfig = db.parse(mConfigFile);
|
mConfig = db.parse(mConfigFile);
|
||||||
} catch (SAXException | ParserConfigurationException | IOException e) {
|
} catch (SAXException | ParserConfigurationException | IOException e) {
|
||||||
throw new RuntimeException("Failed to open config file", e);
|
throw new RuntimeException("Failed to open config file", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWebGuiUrl() {
|
public String getWebGuiUrl() {
|
||||||
return "http://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent();
|
return "http://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getApiKey() {
|
public String getApiKey() {
|
||||||
return getGuiElement().getElementsByTagName("apikey").item(0).getTextContent();
|
return getGuiElement().getElementsByTagName("apikey").item(0).getTextContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the config file.
|
* Updates the config file.
|
||||||
*
|
* <p/>
|
||||||
* Coming from 0.2.0 and earlier, globalAnnounceServer value "announce.syncthing.net:22025" is
|
* 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).
|
* replaced with "194.126.249.5:22025" (as domain resolve is broken).
|
||||||
*
|
* <p/>
|
||||||
* Coming from 0.3.0 and earlier, the ignorePerms flag is set to true on every repository.
|
* Coming from 0.3.0 and earlier, the ignorePerms flag is set to true on every repository.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("SdCardPath")
|
@SuppressWarnings("SdCardPath")
|
||||||
public void updateIfNeeded() {
|
public void updateIfNeeded() {
|
||||||
Log.i(TAG, "Checking for needed config updates");
|
Log.i(TAG, "Checking for needed config updates");
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
Element options = (Element) mConfig.getDocumentElement()
|
Element options = (Element) mConfig.getDocumentElement()
|
||||||
.getElementsByTagName("options").item(0);
|
.getElementsByTagName("options").item(0);
|
||||||
Element gui = (Element) mConfig.getDocumentElement()
|
Element gui = (Element) mConfig.getDocumentElement()
|
||||||
.getElementsByTagName("gui").item(0);
|
.getElementsByTagName("gui").item(0);
|
||||||
|
|
||||||
// Create an API key if it does not exist.
|
// Create an API key if it does not exist.
|
||||||
if (gui.getElementsByTagName("apikey").getLength() == 0) {
|
if (gui.getElementsByTagName("apikey").getLength() == 0) {
|
||||||
Log.i(TAG, "Initializing API key with random string");
|
Log.i(TAG, "Initializing API key with random string");
|
||||||
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
|
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
sb.append(chars[random.nextInt(chars.length)]);
|
sb.append(chars[random.nextInt(chars.length)]);
|
||||||
}
|
}
|
||||||
Element apiKey = mConfig.createElement("apikey");
|
Element apiKey = mConfig.createElement("apikey");
|
||||||
apiKey.setTextContent(sb.toString());
|
apiKey.setTextContent(sb.toString());
|
||||||
gui.appendChild(apiKey);
|
gui.appendChild(apiKey);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardcode default globalAnnounceServer ip.
|
// Hardcode default globalAnnounceServer ip.
|
||||||
Element globalAnnounceServer = (Element)
|
Element globalAnnounceServer = (Element)
|
||||||
options.getElementsByTagName("globalAnnounceServer").item(0);
|
options.getElementsByTagName("globalAnnounceServer").item(0);
|
||||||
if (globalAnnounceServer.getTextContent().equals("announce.syncthing.net:22025")) {
|
if (globalAnnounceServer.getTextContent().equals("announce.syncthing.net:22025")) {
|
||||||
Log.i(TAG, "Replacing globalAnnounceServer host with ip");
|
Log.i(TAG, "Replacing globalAnnounceServer host with ip");
|
||||||
globalAnnounceServer.setTextContent("194.126.249.5:22025");
|
globalAnnounceServer.setTextContent("194.126.249.5:22025");
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeList repos = mConfig.getDocumentElement().getElementsByTagName("repository");
|
NodeList repos = mConfig.getDocumentElement().getElementsByTagName("repository");
|
||||||
for (int i = 0; i < repos.getLength(); i++) {
|
for (int i = 0; i < repos.getLength(); i++) {
|
||||||
Element r = (Element) repos.item(i);
|
Element r = (Element) repos.item(i);
|
||||||
// Set ignorePerms attribute.
|
// Set ignorePerms attribute.
|
||||||
if (!r.hasAttribute("ignorePerms") ||
|
if (!r.hasAttribute("ignorePerms") ||
|
||||||
!Boolean.parseBoolean(r.getAttribute("ignorePerms"))) {
|
!Boolean.parseBoolean(r.getAttribute("ignorePerms"))) {
|
||||||
Log.i(TAG, "Set 'ignorePerms' on repository " + r.getAttribute("id"));
|
Log.i(TAG, "Set 'ignorePerms' on repository " + r.getAttribute("id"));
|
||||||
r.setAttribute("ignorePerms", Boolean.toString(true));
|
r.setAttribute("ignorePerms", Boolean.toString(true));
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace /sdcard/ in repository path with proper path.
|
// Replace /sdcard/ in repository path with proper path.
|
||||||
String dir = r.getAttribute("directory");
|
String dir = r.getAttribute("directory");
|
||||||
if (dir.startsWith("/sdcard")) {
|
if (dir.startsWith("/sdcard")) {
|
||||||
String newDir = dir.replace("/sdcard",
|
String newDir = dir.replace("/sdcard",
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath());
|
Environment.getExternalStorageDirectory().getAbsolutePath());
|
||||||
r.setAttribute("directory", newDir);
|
r.setAttribute("directory", newDir);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change global announce server port to 22026 for syncthing v0.9.0.
|
// Change global announce server port to 22026 for syncthing v0.9.0.
|
||||||
if (globalAnnounceServer.getTextContent().equals("194.126.249.5:22025")) {
|
if (globalAnnounceServer.getTextContent().equals("194.126.249.5:22025")) {
|
||||||
Log.i(TAG, "Changing announce server port for v0.9.0");
|
Log.i(TAG, "Changing announce server port for v0.9.0");
|
||||||
globalAnnounceServer.setTextContent("194.126.249.5:22026");
|
globalAnnounceServer.setTextContent("194.126.249.5:22026");
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
saveChanges();
|
saveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element getGuiElement() {
|
private Element getGuiElement() {
|
||||||
return (Element) mConfig.getDocumentElement()
|
return (Element) mConfig.getDocumentElement()
|
||||||
.getElementsByTagName("gui").item(0);
|
.getElementsByTagName("gui").item(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a repository for the default camera folder.
|
* Creates a repository for the default camera folder.
|
||||||
*/
|
*/
|
||||||
public void createCameraRepo() {
|
public void createCameraRepo() {
|
||||||
File cameraFolder =
|
File cameraFolder =
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
|
||||||
|
|
||||||
Element cameraRepo = mConfig.createElement("repository");
|
Element cameraRepo = mConfig.createElement("repository");
|
||||||
cameraRepo.setAttribute("id", "camera");
|
cameraRepo.setAttribute("id", "camera");
|
||||||
cameraRepo.setAttribute("directory", cameraFolder.getAbsolutePath());
|
cameraRepo.setAttribute("directory", cameraFolder.getAbsolutePath());
|
||||||
cameraRepo.setAttribute("ro", "true");
|
cameraRepo.setAttribute("ro", "true");
|
||||||
cameraRepo.setAttribute("ignorePerms", "true");
|
cameraRepo.setAttribute("ignorePerms", "true");
|
||||||
mConfig.getDocumentElement().appendChild(cameraRepo);
|
mConfig.getDocumentElement().appendChild(cameraRepo);
|
||||||
|
|
||||||
saveChanges();
|
saveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes updated mConfig back to file.
|
* Writes updated mConfig back to file.
|
||||||
*/
|
*/
|
||||||
private void saveChanges() {
|
private void saveChanges() {
|
||||||
try {
|
try {
|
||||||
Log.i(TAG, "Writing updated config back to file");
|
Log.i(TAG, "Writing updated config back to file");
|
||||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
Transformer transformer = transformerFactory.newTransformer();
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
DOMSource domSource = new DOMSource(mConfig);
|
DOMSource domSource = new DOMSource(mConfig);
|
||||||
StreamResult streamResult = new StreamResult(mConfigFile);
|
StreamResult streamResult = new StreamResult(mConfigFile);
|
||||||
transformer.transform(domSource, streamResult);
|
transformer.transform(domSource, streamResult);
|
||||||
}
|
} catch (TransformerException e) {
|
||||||
catch (TransformerException e) {
|
Log.w(TAG, "Failed to save updated config", 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.
|
* Copies the default config file from res/raw/config_default.xml to (data folder)/config.xml.
|
||||||
*/
|
*/
|
||||||
private void copyDefaultConfig(Context context) {
|
private void copyDefaultConfig(Context context) {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
in = context.getResources().openRawResource(R.raw.config_default);
|
in = context.getResources().openRawResource(R.raw.config_default);
|
||||||
out = new FileOutputStream(mConfigFile);
|
out = new FileOutputStream(mConfigFile);
|
||||||
byte[] buff = new byte[1024];
|
byte[] buff = new byte[1024];
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
while ((read = in.read(buff)) > 0) {
|
while ((read = in.read(buff)) > 0) {
|
||||||
out.write(buff, 0, read);
|
out.write(buff, 0, read);
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
throw new RuntimeException("Failed to write config file", e);
|
||||||
throw new RuntimeException("Failed to write config file", e);
|
} finally {
|
||||||
}
|
try {
|
||||||
finally {
|
in.close();
|
||||||
try {
|
out.close();
|
||||||
in.close();
|
} catch (IOException e) {
|
||||||
out.close();
|
Log.w(TAG, "Failed to close stream while copying config", e);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
}
|
||||||
Log.w(TAG, "Failed to close stream while copying config", e);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,15 @@ import android.preference.CheckBoxPreference;
|
||||||
*/
|
*/
|
||||||
public class ExtendedCheckBoxPreference extends CheckBoxPreference {
|
public class ExtendedCheckBoxPreference extends CheckBoxPreference {
|
||||||
|
|
||||||
private final Object mObject;
|
private final Object mObject;
|
||||||
|
|
||||||
public ExtendedCheckBoxPreference(Context context, Object object) {
|
public ExtendedCheckBoxPreference(Context context, Object object) {
|
||||||
super(context);
|
super(context);
|
||||||
mObject = object;
|
mObject = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getObject() {
|
public Object getObject() {
|
||||||
return mObject;
|
return mObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,79 +20,77 @@ import java.util.Map;
|
||||||
* Generates item views for node items.
|
* Generates item views for node items.
|
||||||
*/
|
*/
|
||||||
public class NodesAdapter extends ArrayAdapter<RestApi.Node>
|
public class NodesAdapter extends ArrayAdapter<RestApi.Node>
|
||||||
implements RestApi.OnReceiveConnectionsListener {
|
implements RestApi.OnReceiveConnectionsListener {
|
||||||
|
|
||||||
private Map<String, RestApi.Connection> mConnections =
|
private Map<String, RestApi.Connection> mConnections =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
|
|
||||||
public NodesAdapter(Context context) {
|
public NodesAdapter(Context context) {
|
||||||
super(context, R.layout.node_list_item);
|
super(context, R.layout.node_list_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
LayoutInflater inflater = (LayoutInflater) getContext()
|
LayoutInflater inflater = (LayoutInflater) getContext()
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
convertView = inflater.inflate(R.layout.node_list_item, parent, false);
|
convertView = inflater.inflate(R.layout.node_list_item, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView name = (TextView) convertView.findViewById(R.id.name);
|
TextView name = (TextView) convertView.findViewById(R.id.name);
|
||||||
TextView status = (TextView) convertView.findViewById(R.id.status);
|
TextView status = (TextView) convertView.findViewById(R.id.status);
|
||||||
TextView download = (TextView) convertView.findViewById(R.id.download);
|
TextView download = (TextView) convertView.findViewById(R.id.download);
|
||||||
TextView upload = (TextView) convertView.findViewById(R.id.upload);
|
TextView upload = (TextView) convertView.findViewById(R.id.upload);
|
||||||
|
|
||||||
name.setText(getItem(position).Name);
|
name.setText(getItem(position).Name);
|
||||||
final String nodeId = getItem(position).NodeID;
|
final String nodeId = getItem(position).NodeID;
|
||||||
|
|
||||||
RestApi.Connection conn = mConnections.get(nodeId);
|
RestApi.Connection conn = mConnections.get(nodeId);
|
||||||
Resources res = getContext().getResources();
|
Resources res = getContext().getResources();
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
if (conn.Completion == 100) {
|
if (conn.Completion == 100) {
|
||||||
status.setText(res.getString(R.string.node_up_to_date));
|
status.setText(res.getString(R.string.node_up_to_date));
|
||||||
status.setTextColor(res.getColor(R.color.text_green));
|
status.setTextColor(res.getColor(R.color.text_green));
|
||||||
}
|
} else {
|
||||||
else {
|
status.setText(res.getString(R.string.node_syncing, conn.Completion));
|
||||||
status.setText(res.getString(R.string.node_syncing, conn.Completion));
|
status.setTextColor(res.getColor(R.color.text_blue));
|
||||||
status.setTextColor(res.getColor(R.color.text_blue));
|
}
|
||||||
}
|
download.setText(RestApi.readableTransferRate(getContext(), conn.InBits));
|
||||||
download.setText(RestApi.readableTransferRate(getContext(), conn.InBits));
|
upload.setText(RestApi.readableTransferRate(getContext(), conn.OutBits));
|
||||||
upload.setText(RestApi.readableTransferRate(getContext(), conn.OutBits));
|
} else {
|
||||||
}
|
download.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
||||||
else {
|
upload.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
||||||
download.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
status.setText(res.getString(R.string.node_disconnected));
|
||||||
upload.setText("0 " + res.getStringArray(R.array.transfer_rate_units)[0]);
|
status.setTextColor(res.getColor(R.color.text_red));
|
||||||
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.
|
* Replacement for addAll, which is not implemented on lower API levels.
|
||||||
*/
|
*/
|
||||||
public void add(List<RestApi.Node> nodes) {
|
public void add(List<RestApi.Node> nodes) {
|
||||||
for (RestApi.Node n : nodes) {
|
for (RestApi.Node n : nodes) {
|
||||||
add(n);
|
add(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests new connection info for all nodes visible in listView.
|
* Requests new connection info for all nodes visible in listView.
|
||||||
*/
|
*/
|
||||||
public void updateConnections(RestApi api, ListView listView) {
|
public void updateConnections(RestApi api, ListView listView) {
|
||||||
for (int i = 0; i < getCount(); i++) {
|
for (int i = 0; i < getCount(); i++) {
|
||||||
if ( i >= listView.getFirstVisiblePosition() &&
|
if (i >= listView.getFirstVisiblePosition() &&
|
||||||
i <= listView.getLastVisiblePosition()) {
|
i <= listView.getLastVisiblePosition()) {
|
||||||
api.getConnections(this);
|
api.getConnections(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
public void onReceiveConnections(Map<String, RestApi.Connection> connections) {
|
||||||
mConnections = connections;
|
mConnections = connections;
|
||||||
notifyDataSetInvalidated();
|
notifyDataSetInvalidated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,77 +18,77 @@ import java.util.List;
|
||||||
* Generates item views for repository items.
|
* Generates item views for repository items.
|
||||||
*/
|
*/
|
||||||
public class ReposAdapter extends ArrayAdapter<RestApi.Repo>
|
public class ReposAdapter extends ArrayAdapter<RestApi.Repo>
|
||||||
implements RestApi.OnReceiveModelListener {
|
implements RestApi.OnReceiveModelListener {
|
||||||
|
|
||||||
private HashMap<String, RestApi.Model> mModels = new HashMap<>();
|
private HashMap<String, RestApi.Model> mModels = new HashMap<>();
|
||||||
|
|
||||||
public ReposAdapter(Context context) {
|
public ReposAdapter(Context context) {
|
||||||
super(context, R.layout.repo_list_item);
|
super(context, R.layout.repo_list_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
LayoutInflater inflater = (LayoutInflater) getContext()
|
LayoutInflater inflater = (LayoutInflater) getContext()
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
convertView = inflater.inflate(R.layout.repo_list_item, parent, false);
|
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 state = (TextView) convertView.findViewById(R.id.state);
|
||||||
TextView folder = (TextView) convertView.findViewById(R.id.folder);
|
TextView folder = (TextView) convertView.findViewById(R.id.folder);
|
||||||
TextView items = (TextView) convertView.findViewById(R.id.items);
|
TextView items = (TextView) convertView.findViewById(R.id.items);
|
||||||
TextView size = (TextView) convertView.findViewById(R.id.size);
|
TextView size = (TextView) convertView.findViewById(R.id.size);
|
||||||
TextView invalid = (TextView) convertView.findViewById(R.id.invalid);
|
TextView invalid = (TextView) convertView.findViewById(R.id.invalid);
|
||||||
|
|
||||||
id.setText(getItem(position).ID);
|
id.setText(getItem(position).ID);
|
||||||
state.setTextColor(getContext().getResources().getColor(R.color.text_green));
|
state.setTextColor(getContext().getResources().getColor(R.color.text_green));
|
||||||
folder.setText((getItem(position).Directory));
|
folder.setText((getItem(position).Directory));
|
||||||
RestApi.Model model = mModels.get(getItem(position).ID);
|
RestApi.Model model = mModels.get(getItem(position).ID);
|
||||||
if (model != null) {
|
if (model != null) {
|
||||||
state.setText(getContext().getString(R.string.repo_progress_format, model.state,
|
state.setText(getContext().getString(R.string.repo_progress_format, model.state,
|
||||||
(model.globalBytes <= 0)
|
(model.globalBytes <= 0)
|
||||||
? 100
|
? 100
|
||||||
: (int) ((model.localBytes / (float) model.globalBytes) * 100)));
|
: (int) ((model.localBytes / (float) model.globalBytes) * 100)
|
||||||
items.setText(getContext()
|
));
|
||||||
.getString(R.string.files, model.localFiles, model.globalFiles));
|
items.setText(getContext()
|
||||||
size.setText(RestApi.readableFileSize(getContext(), model.localBytes) + " / " +
|
.getString(R.string.files, model.localFiles, model.globalFiles));
|
||||||
RestApi.readableFileSize(getContext(), model.globalBytes));
|
size.setText(RestApi.readableFileSize(getContext(), model.localBytes) + " / " +
|
||||||
invalid.setText(model.invalid);
|
RestApi.readableFileSize(getContext(), model.globalBytes));
|
||||||
invalid.setVisibility((model.invalid.equals("")) ? View.GONE : View.VISIBLE);
|
invalid.setText(model.invalid);
|
||||||
}
|
invalid.setVisibility((model.invalid.equals("")) ? View.GONE : View.VISIBLE);
|
||||||
else {
|
} else {
|
||||||
invalid.setVisibility(View.GONE);
|
invalid.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replacement for addAll, which is not implemented on lower API levels.
|
* Replacement for addAll, which is not implemented on lower API levels.
|
||||||
*/
|
*/
|
||||||
public void add(List<RestApi.Repo> nodes) {
|
public void add(List<RestApi.Repo> nodes) {
|
||||||
for (RestApi.Repo r : nodes) {
|
for (RestApi.Repo r : nodes) {
|
||||||
add(r);
|
add(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests updated model info from the api for all visible items.
|
* Requests updated model info from the api for all visible items.
|
||||||
*/
|
*/
|
||||||
public void updateModel(RestApi api, ListView listView) {
|
public void updateModel(RestApi api, ListView listView) {
|
||||||
for (int i = 0; i < getCount(); i++) {
|
for (int i = 0; i < getCount(); i++) {
|
||||||
if ( i >= listView.getFirstVisiblePosition() &&
|
if (i >= listView.getFirstVisiblePosition() &&
|
||||||
i <= listView.getLastVisiblePosition()) {
|
i <= listView.getLastVisiblePosition()) {
|
||||||
api.getModel(getItem(i).ID, this);
|
api.getModel(getItem(i).ID, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceiveModel(String repoId, RestApi.Model model) {
|
public void onReceiveModel(String repoId, RestApi.Model model) {
|
||||||
mModels.put(repoId, model);
|
mModels.put(repoId, model);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" >
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@android:id/list"
|
android:id="@android:id/list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/empty"
|
android:id="@android:id/empty"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/directory_empty"
|
android:text="@string/directory_empty"
|
||||||
android:layout_centerInParent="true"/>
|
android:layout_centerInParent="true" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:padding="10dip"
|
android:padding="10dip"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
style="?android:attr/progressBarStyleLarge"
|
style="?android:attr/progressBarStyleLarge"
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/loading_text"
|
android:id="@+id/loading_text"
|
||||||
android:layout_toRightOf="@id/progress"
|
android:layout_toRightOf="@id/progress"
|
||||||
android:layout_alignBottom="@id/progress"
|
android:layout_alignBottom="@id/progress"
|
||||||
android:layout_alignTop="@id/progress"
|
android:layout_alignTop="@id/progress"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -1,117 +1,123 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dip"
|
android:padding="10dip"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" >
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
|
||||||
android:id="@+id/node_id_title"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/node_id"
|
android:id="@+id/node_id_title"
|
||||||
android:lines="1"
|
android:textStyle="bold"
|
||||||
android:ellipsize="end"
|
android:layout_width="wrap_content"
|
||||||
android:layout_below="@id/node_id_title"
|
android:layout_height="wrap_content" />
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/node_id"
|
||||||
android:layout_height="wrap_content" >
|
android:lines="1"
|
||||||
<TextView
|
android:ellipsize="end"
|
||||||
android:id="@+id/cpu_usage_title"
|
android:layout_below="@id/node_id_title"
|
||||||
android:text="@string/cpu_usage"
|
android:layout_width="wrap_content"
|
||||||
android:textStyle="bold"
|
android:layout_height="wrap_content" />
|
||||||
android:layout_width="wrap_content"
|
</RelativeLayout>
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/cpu_usage"
|
android:layout_width="match_parent"
|
||||||
android:layout_alignBottom="@id/cpu_usage_title"
|
android:layout_height="wrap_content">
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/cpu_usage_title"
|
||||||
android:layout_height="wrap_content" >
|
android:text="@string/cpu_usage"
|
||||||
<TextView
|
android:textStyle="bold"
|
||||||
android:id="@+id/ram_usage_title"
|
android:layout_width="wrap_content"
|
||||||
android:text="@string/ram_usage"
|
android:layout_height="wrap_content" />
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/ram_usage"
|
android:id="@+id/cpu_usage"
|
||||||
android:layout_alignBottom="@id/ram_usage_title"
|
android:layout_alignBottom="@id/cpu_usage_title"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
|
||||||
android:id="@+id/download_title"
|
|
||||||
android:text="@string/download_title"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download"
|
android:id="@+id/ram_usage_title"
|
||||||
android:layout_alignBottom="@id/download_title"
|
android:text="@string/ram_usage"
|
||||||
android:layout_alignParentRight="true"
|
android:textStyle="bold"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/ram_usage"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_alignBottom="@id/ram_usage_title"
|
||||||
<TextView
|
android:layout_alignParentRight="true"
|
||||||
android:id="@+id/upload_title"
|
android:layout_width="wrap_content"
|
||||||
android:text="@string/upload_title"
|
android:layout_height="wrap_content" />
|
||||||
android:textStyle="bold"
|
</RelativeLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/upload"
|
android:layout_width="match_parent"
|
||||||
android:layout_alignBottom="@id/upload_title"
|
android:layout_height="wrap_content">
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/download_title"
|
||||||
android:layout_height="wrap_content" >
|
android:text="@string/download_title"
|
||||||
<TextView
|
android:textStyle="bold"
|
||||||
android:id="@+id/announce_server_title"
|
android:layout_width="wrap_content"
|
||||||
android:text="@string/announce_server"
|
android:layout_height="wrap_content" />
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/announce_server"
|
android:id="@+id/download"
|
||||||
android:layout_alignBottom="@id/announce_server_title"
|
android:layout_alignBottom="@id/download_title"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/upload_title"
|
||||||
|
android:text="@string/upload_title"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/upload"
|
||||||
|
android:layout_alignBottom="@id/upload_title"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/announce_server_title"
|
||||||
|
android:text="@string/announce_server"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/announce_server"
|
||||||
|
android:layout_alignBottom="@id/announce_server_title"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -1,23 +1,22 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<android.support.v4.widget.DrawerLayout
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:id="@+id/drawer_layout"
|
||||||
android:id="@+id/drawer_layout"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<android.support.v4.view.ViewPager
|
<android.support.v4.view.ViewPager
|
||||||
android:id="@+id/pager"
|
android:id="@+id/pager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/drawer"
|
android:id="@+id/drawer"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:layout_width="260dip"
|
android:layout_width="260dip"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:background="@android:color/background_light" />
|
android:background="@android:color/background_light" />
|
||||||
|
|
||||||
</android.support.v4.widget.DrawerLayout>
|
</android.support.v4.widget.DrawerLayout>
|
|
@ -1,59 +1,59 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="4dip" >
|
android:padding="4dip">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_toLeftOf="@+id/status"
|
android:layout_toLeftOf="@+id/status"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end" />
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/status"
|
android:id="@+id/status"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignBottom="@+id/name"
|
android:layout_alignBottom="@+id/name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_title"
|
android:id="@+id/download_title"
|
||||||
android:text="@string/download_title_colon"
|
android:text="@string/download_title_colon"
|
||||||
android:layout_below="@id/name"
|
android:layout_below="@id/name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download"
|
android:id="@+id/download"
|
||||||
android:layout_alignBaseline="@id/download_title"
|
android:layout_alignBaseline="@id/download_title"
|
||||||
android:layout_toRightOf="@id/download_title"
|
android:layout_toRightOf="@id/download_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/upload_title"
|
android:id="@+id/upload_title"
|
||||||
android:text="@string/upload_title_colon"
|
android:text="@string/upload_title_colon"
|
||||||
android:layout_below="@id/download_title"
|
android:layout_below="@id/download_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/upload"
|
android:id="@+id/upload"
|
||||||
android:layout_alignBaseline="@id/upload_title"
|
android:layout_alignBaseline="@id/upload_title"
|
||||||
android:layout_toRightOf="@id/upload_title"
|
android:layout_toRightOf="@id/upload_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
>>>>>>> Changed code style to use spaces instead of tabs.
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,55 +1,55 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="4dip" >
|
android:padding="4dip">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/id"
|
android:id="@+id/id"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_toLeftOf="@+id/state"
|
android:layout_toLeftOf="@+id/state"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end" />
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/state"
|
android:id="@+id/state"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignBottom="@+id/id"
|
android:layout_alignBottom="@+id/id"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/folder"
|
android:id="@+id/folder"
|
||||||
android:layout_below="@id/state"
|
android:layout_below="@id/state"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end" />
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/items"
|
android:id="@+id/items"
|
||||||
android:layout_below="@id/folder"
|
android:layout_below="@id/folder"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/size"
|
android:id="@+id/size"
|
||||||
android:layout_below="@id/items"
|
android:layout_below="@id/items"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/invalid"
|
android:id="@+id/invalid"
|
||||||
android:textColor="@color/text_red"
|
android:textColor="@color/text_red"
|
||||||
android:layout_below="@id/size"
|
android:layout_below="@id/size"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="48dip"
|
android:layout_width="48dip"
|
||||||
android:layout_height="48dip"
|
android:layout_height="48dip"
|
||||||
android:src="@drawable/ic_qrcode"
|
android:src="@drawable/ic_qrcode"
|
||||||
android:onClick="onClick"
|
android:onClick="onClick"
|
||||||
android:contentDescription="@string/scan_qr_code_description" />
|
android:contentDescription="@string/scan_qr_code_description" />
|
||||||
|
|
|
@ -1,37 +1,36 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:layout_height="match_parent" >
|
|
||||||
|
|
||||||
<WebView
|
<WebView
|
||||||
android:id="@+id/webview"
|
android:id="@+id/webview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/loading"
|
android:id="@+id/loading"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
style="?android:attr/progressBarStyleLarge"
|
style="?android:attr/progressBarStyleLarge"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="10dip" />
|
android:layout_marginBottom="10dip" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/loading_text"
|
android:id="@+id/loading_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/progress"
|
android:layout_below="@id/progress"
|
||||||
android:text="@string/web_gui_loading" />
|
android:text="@string/web_gui_loading" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<menu
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/select"
|
android:id="@+id/select"
|
||||||
android:title="@string/select_folder"
|
android:title="@string/select_folder"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/create_folder"
|
android:id="@+id/create_folder"
|
||||||
android:title="@string/create_folder"
|
android:title="@string/create_folder"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<menu
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/share_node_id"
|
android:id="@+id/share_node_id"
|
||||||
android:icon="@android:drawable/ic_menu_share"
|
android:icon="@android:drawable/ic_menu_share"
|
||||||
android:title="@string/share_node_id"
|
android:title="@string/share_node_id"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/add_repo"
|
android:id="@+id/add_repo"
|
||||||
android:title="@string/add_repo"
|
android:title="@string/add_repo"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/add_node"
|
android:id="@+id/add_node"
|
||||||
android:title="@string/add_node"
|
android:title="@string/add_node"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/web_gui"
|
android:id="@+id/web_gui"
|
||||||
android:title="@string/web_gui_title" />
|
android:title="@string/web_gui_title" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/settings"
|
android:id="@+id/settings"
|
||||||
android:title="@string/settings_title" />
|
android:title="@string/settings_title" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/create"
|
android:id="@+id/create"
|
||||||
android:title="@string/add"
|
android:title="@string/add"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/share_node_id"
|
android:id="@+id/share_node_id"
|
||||||
android:icon="@android:drawable/ic_menu_share"
|
android:icon="@android:drawable/ic_menu_share"
|
||||||
android:title="@string/share_node_id"
|
android:title="@string/share_node_id"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:icon="@drawable/ic_delete"
|
android:icon="@drawable/ic_delete"
|
||||||
android:title="@string/delete_node"
|
android:title="@string/delete_node"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/create"
|
android:id="@+id/create"
|
||||||
android:title="@string/create"
|
android:title="@string/create"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:icon="@drawable/ic_delete"
|
android:icon="@drawable/ic_delete"
|
||||||
android:title="@string/delete_repo"
|
android:title="@string/delete_repo"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<configuration version="2">
|
<configuration version="2">
|
||||||
<gui enabled="true">
|
<gui enabled="true">
|
||||||
<address>127.0.0.1:8080</address>
|
<address>127.0.0.1:8080</address>
|
||||||
</gui>
|
</gui>
|
||||||
<options>
|
<options>
|
||||||
<listenAddress>0.0.0.0:22000</listenAddress>
|
<listenAddress>0.0.0.0:22000</listenAddress>
|
||||||
<globalAnnounceServer>194.126.249.5:22026</globalAnnounceServer>
|
<globalAnnounceServer>194.126.249.5:22026</globalAnnounceServer>
|
||||||
<globalAnnounceEnabled>true</globalAnnounceEnabled>
|
<globalAnnounceEnabled>true</globalAnnounceEnabled>
|
||||||
<localAnnounceEnabled>true</localAnnounceEnabled>
|
<localAnnounceEnabled>true</localAnnounceEnabled>
|
||||||
<parallelRequests>16</parallelRequests>
|
<parallelRequests>16</parallelRequests>
|
||||||
<maxSendKbps>0</maxSendKbps>
|
<maxSendKbps>0</maxSendKbps>
|
||||||
<rescanIntervalS>60</rescanIntervalS>
|
<rescanIntervalS>60</rescanIntervalS>
|
||||||
<reconnectionIntervalS>60</reconnectionIntervalS>
|
<reconnectionIntervalS>60</reconnectionIntervalS>
|
||||||
<maxChangeKbps>1000</maxChangeKbps>
|
<maxChangeKbps>1000</maxChangeKbps>
|
||||||
<startBrowser>false</startBrowser>
|
<startBrowser>false</startBrowser>
|
||||||
<upnpEnabled>true</upnpEnabled>
|
<upnpEnabled>true</upnpEnabled>
|
||||||
</options>
|
</options>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar" />
|
|
||||||
|
<style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="text_red">#ffff4444</color>
|
<color name="text_red">#ffff4444</color>
|
||||||
<color name="text_blue">#ff33b5e5</color>
|
<color name="text_blue">#ff33b5e5</color>
|
||||||
<color name="text_green">#ff99cc00</color>
|
<color name="text_green">#ff99cc00</color>
|
||||||
</resources>
|
</resources>
|
|
@ -1,234 +1,234 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string name="app_name">Syncthing</string>
|
<string name="app_name">Syncthing</string>
|
||||||
|
|
||||||
<!-- MainActivity -->
|
<!-- MainActivity -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Title of the "add repo" menu action -->
|
<!-- Title of the "add repo" menu action -->
|
||||||
<string name="add_repo">Add Repository</string>
|
<string name="add_repo">Add Repository</string>
|
||||||
|
|
||||||
<!-- Title of the "share node id" menu action -->
|
<!-- Title of the "share node id" menu action -->
|
||||||
<string name="share_node_id">Share Node ID</string>
|
<string name="share_node_id">Share Node ID</string>
|
||||||
|
|
||||||
<!-- Shown in the chooser dialog when sharing a Node ID -->
|
<!-- Shown in the chooser dialog when sharing a Node ID -->
|
||||||
<string name="send_node_id_to">Send Node ID to</string>
|
<string name="send_node_id_to">Send Node ID to</string>
|
||||||
|
|
||||||
<!-- Text for RepositoriesFragment and NodesFragment loading view -->
|
<!-- Text for RepositoriesFragment and NodesFragment loading view -->
|
||||||
<string name="api_loading">Waiting for API</string>
|
<string name="api_loading">Waiting for API</string>
|
||||||
|
|
||||||
<!-- RepositoriesFragment -->
|
<!-- RepositoriesFragment -->
|
||||||
|
|
||||||
|
|
||||||
<string name="repositories_fragment_title">Repositories</string>
|
<string name="repositories_fragment_title">Repositories</string>
|
||||||
|
|
||||||
<!-- Format string for repository progress. First parameter is status string, second is sync percentage -->
|
<!-- Format string for repository progress. First parameter is status string, second is sync percentage -->
|
||||||
<string name="repo_progress_format">%1$s (%2$d%%)</string>
|
<string name="repo_progress_format">%1$s (%2$d%%)</string>
|
||||||
|
|
||||||
<!-- Shown if no repos exist -->
|
<!-- Shown if no repos exist -->
|
||||||
<string name="repositories_list_empty">No repositories found</string>
|
<string name="repositories_list_empty">No repositories found</string>
|
||||||
|
|
||||||
<!-- Format string for repository file count -->
|
<!-- Format string for repository file count -->
|
||||||
<string name="files">%1$d / %2$d Files</string>
|
<string name="files">%1$d / %2$d Files</string>
|
||||||
|
|
||||||
<!-- NodesFragment -->
|
<!-- NodesFragment -->
|
||||||
|
|
||||||
|
|
||||||
<string name="nodes_fragment_title">Nodes</string>
|
<string name="nodes_fragment_title">Nodes</string>
|
||||||
|
|
||||||
<!-- Shown if no nodes exist -->
|
<!-- Shown if no nodes exist -->
|
||||||
<string name="nodes_list_empty">No nodes found</string>
|
<string name="nodes_list_empty">No nodes found</string>
|
||||||
|
|
||||||
<!-- Indicates that a repo is fully synced to the local node -->
|
<!-- Indicates that a repo is fully synced to the local node -->
|
||||||
<string name="node_up_to_date">Up to Date</string>
|
<string name="node_up_to_date">Up to Date</string>
|
||||||
|
|
||||||
<!-- Indicates that the node is currently syncing. Parameter is sync percentage -->
|
<!-- Indicates that the node is currently syncing. Parameter is sync percentage -->
|
||||||
<string name="node_syncing">Syncing (%1$d%%)</string>
|
<string name="node_syncing">Syncing (%1$d%%)</string>
|
||||||
|
|
||||||
<!-- Indicates that there is no connection to the node -->
|
<!-- Indicates that there is no connection to the node -->
|
||||||
<string name="node_disconnected">Disconnected</string>
|
<string name="node_disconnected">Disconnected</string>
|
||||||
|
|
||||||
<!-- Title for current download rate -->
|
<!-- Title for current download rate -->
|
||||||
<string name="download_title">Download</string>
|
<string name="download_title">Download</string>
|
||||||
|
|
||||||
<!-- Title for current upload rate -->
|
<!-- Title for current upload rate -->
|
||||||
<string name="upload_title">Upload</string>
|
<string name="upload_title">Upload</string>
|
||||||
|
|
||||||
<!-- LocalNodeInfoFragment -->
|
<!-- LocalNodeInfoFragment -->
|
||||||
|
|
||||||
|
|
||||||
<!-- ActionBar title shown when the drawer is open -->
|
<!-- ActionBar title shown when the drawer is open -->
|
||||||
<string name="system_info">System Info</string>
|
<string name="system_info">System Info</string>
|
||||||
|
|
||||||
<!-- Same as download_title with a colon and space appended -->
|
<!-- Same as download_title with a colon and space appended -->
|
||||||
<string name="download_title_colon">Download:\u0020</string>
|
<string name="download_title_colon">Download:\u0020</string>
|
||||||
|
|
||||||
<!-- Same as upload_title with a colon and space appended -->
|
<!-- Same as upload_title with a colon and space appended -->
|
||||||
<string name="upload_title_colon">Upload:\u0020</string>
|
<string name="upload_title_colon">Upload:\u0020</string>
|
||||||
|
|
||||||
<!-- Title for current CPU usage -->
|
<!-- Title for current CPU usage -->
|
||||||
<string name="cpu_usage">CPU Usage</string>
|
<string name="cpu_usage">CPU Usage</string>
|
||||||
|
|
||||||
<!-- Title for current RAM usage -->
|
<!-- Title for current RAM usage -->
|
||||||
<string name="ram_usage">RAM Usage</string>
|
<string name="ram_usage">RAM Usage</string>
|
||||||
|
|
||||||
<!-- Title for announce server status -->
|
<!-- Title for announce server status -->
|
||||||
<string name="announce_server">Announce Server</string>
|
<string name="announce_server">Announce Server</string>
|
||||||
|
|
||||||
<!-- RepoSettingsFragment -->
|
<!-- RepoSettingsFragment -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="repo_id">Repository ID</string>
|
<string name="repo_id">Repository ID</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="directory">Directory</string>
|
<string name="directory">Directory</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="repo_master">Repository Master</string>
|
<string name="repo_master">Repository Master</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="nodes">Nodes</string>
|
<string name="nodes">Nodes</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="file_versioning">File Versioning</string>
|
<string name="file_versioning">File Versioning</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="keep_versions">Keep Versions</string>
|
<string name="keep_versions">Keep Versions</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="delete_repo">Delete Repository</string>
|
<string name="delete_repo">Delete Repository</string>
|
||||||
|
|
||||||
<!-- Title for RepoSettingsFragment in create mode -->
|
<!-- Title for RepoSettingsFragment in create mode -->
|
||||||
<string name="create_repo">Create Repository</string>
|
<string name="create_repo">Create Repository</string>
|
||||||
|
|
||||||
<!-- Title for RepoSettingsFragment in edit mode -->
|
<!-- Title for RepoSettingsFragment in edit mode -->
|
||||||
<string name="edit_repo">Edit Repository</string>
|
<string name="edit_repo">Edit Repository</string>
|
||||||
|
|
||||||
<!-- Menu item to confirm repo creation -->
|
<!-- Menu item to confirm repo creation -->
|
||||||
<string name="create">Create</string>
|
<string name="create">Create</string>
|
||||||
|
|
||||||
<!-- Dialog shown when attempting to delete a repository -->
|
<!-- Dialog shown when attempting to delete a repository -->
|
||||||
<string name="delete_repo_confirm">Do you really want to delete this repository?</string>
|
<string name="delete_repo_confirm">Do you really want to delete this repository?</string>
|
||||||
|
|
||||||
<!-- Toast shown when trying to create a repository with an empty ID -->
|
<!-- Toast shown when trying to create a repository with an empty ID -->
|
||||||
<string name="repo_id_required">The repository ID must not be empty</string>
|
<string name="repo_id_required">The repository ID must not be empty</string>
|
||||||
|
|
||||||
<!-- Toast shown when trying to create a repository with an empty path -->
|
<!-- Toast shown when trying to create a repository with an empty path -->
|
||||||
<string name="repo_path_required">The repository path must not be empty</string>
|
<string name="repo_path_required">The repository path must not be empty</string>
|
||||||
|
|
||||||
<!-- Toast shown when selecting 'nodes' if no nodes have been added -->
|
<!-- Toast shown when selecting 'nodes' if no nodes have been added -->
|
||||||
<string name="no_nodes">Please connect a node first.</string>
|
<string name="no_nodes">Please connect a node first.</string>
|
||||||
|
|
||||||
<!-- NodeSettingsFragment -->
|
<!-- NodeSettingsFragment -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="node_id">Node ID</string>
|
<string name="node_id">Node ID</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="addresses">Addresses</string>
|
<string name="addresses">Addresses</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="current_address">Current Address</string>
|
<string name="current_address">Current Address</string>
|
||||||
|
|
||||||
<!-- Setting title -->
|
<!-- Setting title -->
|
||||||
<string name="delete_node">Delete Node</string>
|
<string name="delete_node">Delete Node</string>
|
||||||
|
|
||||||
<!-- Title for NodeSettingsFragment in create mode -->
|
<!-- Title for NodeSettingsFragment in create mode -->
|
||||||
<string name="add_node">Add Node</string>
|
<string name="add_node">Add Node</string>
|
||||||
|
|
||||||
<!-- Menu item to confirm adding a node -->
|
<!-- Menu item to confirm adding a node -->
|
||||||
<string name="add">Add</string>
|
<string name="add">Add</string>
|
||||||
|
|
||||||
<!-- Title for NodeSettingsFragment in edit mode -->
|
<!-- Title for NodeSettingsFragment in edit mode -->
|
||||||
<string name="edit_node">Edit Node</string>
|
<string name="edit_node">Edit Node</string>
|
||||||
|
|
||||||
<!-- Dialog shown when attempting to delete a node -->
|
<!-- Dialog shown when attempting to delete a node -->
|
||||||
<string name="delete_node_confirm">Do you really want to delete this node?</string>
|
<string name="delete_node_confirm">Do you really want to delete this node?</string>
|
||||||
|
|
||||||
<!-- Toast shown when trying to create a node with an empty ID -->
|
<!-- Toast shown when trying to create a node with an empty ID -->
|
||||||
<string name="node_id_required">The node ID must not be empty</string>
|
<string name="node_id_required">The node ID must not be empty</string>
|
||||||
|
|
||||||
<!-- Toast shown when trying to create a node with an empty name -->
|
<!-- Toast shown when trying to create a node with an empty name -->
|
||||||
<string name="node_name_required">The node name must not be empty</string>
|
<string name="node_name_required">The node name must not be empty</string>
|
||||||
|
|
||||||
<!-- Content description for node ID qr code icon -->
|
<!-- Content description for node ID qr code icon -->
|
||||||
<string name="scan_qr_code_description">Scan QR Code</string>
|
<string name="scan_qr_code_description">Scan QR Code</string>
|
||||||
|
|
||||||
<!-- Text for toast shown if the "scan QR code" intent fails with an ActivityNotFoundException -->
|
<!-- Text for toast shown if the "scan QR code" intent fails with an ActivityNotFoundException -->
|
||||||
<string name="no_qr_scanner_installed">You have no QR scanner installed or your scanner is not supported. \
|
<string name="no_qr_scanner_installed">You have no QR scanner installed or your scanner is not supported. \
|
||||||
Please install a scanner or enter the node ID manually.</string>
|
Please install a scanner or enter the node ID manually.</string>
|
||||||
|
|
||||||
<!-- WebGuiActivity -->
|
<!-- WebGuiActivity -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Title of the web gui activity -->
|
<!-- Title of the web gui activity -->
|
||||||
<string name="web_gui_title">Web GUI</string>
|
<string name="web_gui_title">Web GUI</string>
|
||||||
|
|
||||||
<!-- Text for WebGuiActivity loading view -->
|
<!-- Text for WebGuiActivity loading view -->
|
||||||
<string name="web_gui_loading">Waiting for GUI</string>
|
<string name="web_gui_loading">Waiting for GUI</string>
|
||||||
|
|
||||||
<!-- Shown instead of web_gui_loading if the key does not exist and has to be created -->
|
<!-- Shown instead of web_gui_loading if the key does not exist and has to be created -->
|
||||||
<string name="web_gui_creating_key">Generating keys. This may take a while.</string>
|
<string name="web_gui_creating_key">Generating keys. This may take a while.</string>
|
||||||
|
|
||||||
<!-- Title for dialog displayed on first start -->
|
<!-- Title for dialog displayed on first start -->
|
||||||
<string name="welcome_title">First Start</string>
|
<string name="welcome_title">First Start</string>
|
||||||
|
|
||||||
<!-- Text for dialog displayed on first start -->
|
<!-- Text for dialog displayed on first start -->
|
||||||
<string name="welcome_text">Welcome to Syncthing for Android!\n\n\
|
<string name="welcome_text">Welcome to Syncthing for Android!\n\n\
|
||||||
This app is currently in Alpha state, and you may experience bugs, performance problems or data loss.\n\n\
|
This app is currently in Alpha state, and you may experience bugs, performance problems or data loss.\n\n\
|
||||||
There is currently no special handling for mobile data, so it may use up your data volume if active.\n\n\
|
There is currently no special handling for mobile data, so it may use up your data volume if active.\n\n\
|
||||||
Please report any problems you encounter.</string>
|
Please report any problems you encounter.</string>
|
||||||
|
|
||||||
<!-- SettingsFragment -->
|
<!-- SettingsFragment -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Activity title -->
|
<!-- Activity title -->
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
|
|
||||||
<string name="stop_sync_while_not_charging">Stop sync when not charging</string>
|
<string name="stop_sync_while_not_charging">Stop sync when not charging</string>
|
||||||
|
|
||||||
<string name="stop_sync_on_mobile_data">Stop sync on mobile data</string>
|
<string name="stop_sync_on_mobile_data">Stop sync on mobile data</string>
|
||||||
|
|
||||||
<!-- Settings item that opens issue tracker -->
|
<!-- Settings item that opens issue tracker -->
|
||||||
<string name="report_issue_title">Report Issue</string>
|
<string name="report_issue_title">Report Issue</string>
|
||||||
|
|
||||||
<!-- Summary for the issue tracker settings item -->
|
<!-- Summary for the issue tracker settings item -->
|
||||||
<string name="report_issue_summary">Open the Syncthing-Android issue tracker</string>
|
<string name="report_issue_summary">Open the Syncthing-Android issue tracker</string>
|
||||||
|
|
||||||
<!-- URL of the issue tracker -->
|
<!-- URL of the issue tracker -->
|
||||||
<string name="issue_tracker_url" translatable="false">https://github.com/Nutomic/syncthing-android/issues</string>
|
<string name="issue_tracker_url" translatable="false">https://github.com/Nutomic/syncthing-android/issues</string>
|
||||||
|
|
||||||
<!-- Title of the preference showing upstream version name -->
|
<!-- Title of the preference showing upstream version name -->
|
||||||
<string name="syncthing_version_title">Syncthing Version</string>
|
<string name="syncthing_version_title">Syncthing Version</string>
|
||||||
|
|
||||||
<!-- FolderPickerAcitivity -->
|
<!-- FolderPickerAcitivity -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Activity title -->
|
<!-- Activity title -->
|
||||||
<string name="folder_picker_title">Folder Picker</string>
|
<string name="folder_picker_title">Folder Picker</string>
|
||||||
|
|
||||||
<!-- ListView empty text -->
|
<!-- ListView empty text -->
|
||||||
<string name="directory_empty">Directory is Empty</string>
|
<string name="directory_empty">Directory is Empty</string>
|
||||||
|
|
||||||
<!-- Menu item to create folder -->
|
<!-- Menu item to create folder -->
|
||||||
<string name="create_folder">Create new Folder</string>
|
<string name="create_folder">Create new Folder</string>
|
||||||
|
|
||||||
<!-- Menu item to select the current folder -->
|
<!-- Menu item to select the current folder -->
|
||||||
<string name="select_folder">Select Folder</string>
|
<string name="select_folder">Select Folder</string>
|
||||||
|
|
||||||
<!-- SyncthingService -->
|
<!-- SyncthingService -->
|
||||||
|
|
||||||
<!-- Title of the dialog shown when the syncthing binary returns an error -->
|
<!-- Title of the dialog shown when the syncthing binary returns an error -->
|
||||||
<string name="binary_crashed_title">Syncthing Binary Crashed</string>
|
<string name="binary_crashed_title">Syncthing Binary Crashed</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Message of the dialog shown when the syncthing binary returns an error -->
|
<!-- Message of the dialog shown when the syncthing binary returns an error -->
|
||||||
<string name="binary_crashed_message">The syncthing binary has exited with error code %1$d.\n\n
|
<string name="binary_crashed_message">The syncthing binary has exited with error code %1$d.\n\n
|
||||||
If this error persists, try reinstalling the app and restarting your device.\n\n</string>
|
If this error persists, try reinstalling the app and restarting your device.\n\n</string>
|
||||||
|
|
||||||
|
@ -238,43 +238,43 @@ If this error persists, try reinstalling the app and restarting your device.\n\n
|
||||||
<!-- Message of the "syncthing disabled" dialog -->
|
<!-- Message of the "syncthing disabled" dialog -->
|
||||||
<string name="syncthing_disabled_message">Do you want to change your preferences?</string>
|
<string name="syncthing_disabled_message">Do you want to change your preferences?</string>
|
||||||
|
|
||||||
<!-- Button text on the "syncthing disabled" dialog -->
|
<!-- Button text on the "syncthing disabled" dialog -->
|
||||||
<string name="syncthing_disabled_change_settings">Change Settings</string>
|
<string name="syncthing_disabled_change_settings">Change Settings</string>
|
||||||
|
|
||||||
<!-- Button text on the "syncthing disabled" dialog -->
|
<!-- Button text on the "syncthing disabled" dialog -->
|
||||||
<string name="exit">Exit</string>
|
<string name="exit">Exit</string>
|
||||||
|
|
||||||
<!-- RestApi -->
|
<!-- RestApi -->
|
||||||
|
|
||||||
|
|
||||||
<!-- Title of the notification shown when a restart is needed -->
|
<!-- Title of the notification shown when a restart is needed -->
|
||||||
<string name="restart_title">Restart Needed</string>
|
<string name="restart_title">Restart Needed</string>
|
||||||
|
|
||||||
<!-- Text of the notification shown when a restart is needed -->
|
<!-- Text of the notification shown when a restart is needed -->
|
||||||
<string name="restart_notification_text">Click here to restart syncthing now</string>
|
<string name="restart_notification_text">Click here to restart syncthing now</string>
|
||||||
|
|
||||||
<!-- Text for the dismiss button of the restart Activity -->
|
<!-- Text for the dismiss button of the restart Activity -->
|
||||||
<string name="restart_later">Restart Later</string>
|
<string name="restart_later">Restart Later</string>
|
||||||
|
|
||||||
<!-- Shown when a node ID is copied to the clipboard -->
|
<!-- Shown when a node ID is copied to the clipboard -->
|
||||||
<string name="node_id_copied_to_clipboard">Node ID copied to clipboard</string>
|
<string name="node_id_copied_to_clipboard">Node ID copied to clipboard</string>
|
||||||
|
|
||||||
<!-- Strings representing units for file sizes, from smallest to largest -->
|
<!-- Strings representing units for file sizes, from smallest to largest -->
|
||||||
<string-array name="file_size_units">
|
<string-array name="file_size_units">
|
||||||
<item>B</item>
|
<item>B</item>
|
||||||
<item>KB</item>
|
<item>KB</item>
|
||||||
<item>MB</item>
|
<item>MB</item>
|
||||||
<item>GB</item>
|
<item>GB</item>
|
||||||
<item>TB</item>
|
<item>TB</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Strings representing units for transfer rates, from smallest to largest -->
|
<!-- Strings representing units for transfer rates, from smallest to largest -->
|
||||||
<string-array name="transfer_rate_units">
|
<string-array name="transfer_rate_units">
|
||||||
<item>b/s</item>
|
<item>b/s</item>
|
||||||
<item>Kb/s</item>
|
<item>Kb/s</item>
|
||||||
<item>Mb/s</item>
|
<item>Mb/s</item>
|
||||||
<item>Gb/s</item>
|
<item>Gb/s</item>
|
||||||
<item>Tb/s</item>
|
<item>Tb/s</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="AppTheme" parent="@style/Theme.AppCompat" />
|
|
||||||
|
<style name="AppTheme" parent="@style/Theme.AppCompat" />
|
||||||
</resources>
|
</resources>
|
|
@ -1,106 +1,106 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="stop_sync_while_not_charging"
|
android:key="stop_sync_while_not_charging"
|
||||||
android:title="@string/stop_sync_while_not_charging"
|
android:title="@string/stop_sync_while_not_charging"
|
||||||
android:defaultValue="true" />
|
android:defaultValue="true" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="stop_sync_on_mobile_data"
|
android:key="stop_sync_on_mobile_data"
|
||||||
android:title="@string/stop_sync_on_mobile_data"
|
android:title="@string/stop_sync_on_mobile_data"
|
||||||
android:defaultValue="true" />
|
android:defaultValue="true" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:key="syncthing_options"
|
android:key="syncthing_options"
|
||||||
android:title="Syncthing Options"
|
android:title="Syncthing Options"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="ListenAddress"
|
android:key="ListenAddress"
|
||||||
android:title="Sync Protocol Listen Addresses"
|
android:title="Sync Protocol Listen Addresses"
|
||||||
android:defaultValue="0.0.0.0:22000" />
|
android:defaultValue="0.0.0.0:22000" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="MaxSendKbps"
|
android:key="MaxSendKbps"
|
||||||
android:title="Outgoing Rate Limit (KiB/s)"
|
android:title="Outgoing Rate Limit (KiB/s)"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="RescanIntervalS"
|
android:key="RescanIntervalS"
|
||||||
android:title="Rescan Interval (s)"
|
android:title="Rescan Interval (s)"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="ReconnectIntervalS"
|
android:key="ReconnectIntervalS"
|
||||||
android:title="Reconnect Interval (s)"
|
android:title="Reconnect Interval (s)"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="ParallelRequests"
|
android:key="ParallelRequests"
|
||||||
android:title="Max Outstanding Requests"
|
android:title="Max Outstanding Requests"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="MaxChangeKbps"
|
android:key="MaxChangeKbps"
|
||||||
android:title="Max File Change Rate (KiB/s)"
|
android:title="Max File Change Rate (KiB/s)"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="GlobalAnnEnabled"
|
android:key="GlobalAnnEnabled"
|
||||||
android:title="Global Discovery" />
|
android:title="Global Discovery" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="LocalAnnEnabled"
|
android:key="LocalAnnEnabled"
|
||||||
android:title="Local Discovery" />
|
android:title="Local Discovery" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="LocalAnnPort"
|
android:key="LocalAnnPort"
|
||||||
android:title="Local Discovery Port"
|
android:title="Local Discovery Port"
|
||||||
android:numeric="integer" />
|
android:numeric="integer" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="UPnPEnabled"
|
android:key="UPnPEnabled"
|
||||||
android:title="Enable UPnP" />
|
android:title="Enable UPnP" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:key="syncthing_gui"
|
android:key="syncthing_gui"
|
||||||
android:title="Syncthing GUI"
|
android:title="Syncthing GUI"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="Address"
|
android:key="Address"
|
||||||
android:title="GUI Listen Addresses" />
|
android:title="GUI Listen Addresses" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="User"
|
android:key="User"
|
||||||
android:title="GUI Authentication User" />
|
android:title="GUI Authentication User" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="Password"
|
android:key="Password"
|
||||||
android:title="GUI Authentication Password"
|
android:title="GUI Authentication Password"
|
||||||
android:inputType="textPassword" />
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="UseTLS"
|
android:key="UseTLS"
|
||||||
android:title="Use HTTPS for GUI"
|
android:title="Use HTTPS for GUI"
|
||||||
android:enabled="false" />
|
android:enabled="false" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:title="@string/report_issue_title"
|
android:title="@string/report_issue_title"
|
||||||
android:summary="@string/report_issue_summary" >
|
android:summary="@string/report_issue_summary">
|
||||||
<intent
|
<intent
|
||||||
android:action="android.intent.action.VIEW"
|
android:action="android.intent.action.VIEW"
|
||||||
android:data="@string/issue_tracker_url" />
|
android:data="@string/issue_tracker_url" />
|
||||||
</Preference>
|
</Preference>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="syncthing_version"
|
android:key="syncthing_version"
|
||||||
android:title="@string/syncthing_version_title"
|
android:title="@string/syncthing_version_title"
|
||||||
style="?android:preferenceInformationStyle" />
|
style="?android:preferenceInformationStyle" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="node_id"
|
android:key="node_id"
|
||||||
android:title="@string/node_id"
|
android:title="@string/node_id"
|
||||||
android:widgetLayout="@layout/scan_qr_code_widget" />
|
android:widgetLayout="@layout/scan_qr_code_widget" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="name"
|
android:key="name"
|
||||||
android:title="@string/name" />
|
android:title="@string/name" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="addresses"
|
android:key="addresses"
|
||||||
android:title="@string/addresses" />
|
android:title="@string/addresses" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
|
@ -1,27 +1,27 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="node_id"
|
android:key="node_id"
|
||||||
android:title="@string/node_id"/>
|
android:title="@string/node_id" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="name"
|
android:key="name"
|
||||||
android:title="@string/name" />
|
android:title="@string/name" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="addresses"
|
android:key="addresses"
|
||||||
android:title="@string/addresses" />
|
android:title="@string/addresses" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="version"
|
android:key="version"
|
||||||
android:title="@string/syncthing_version_title"
|
android:title="@string/syncthing_version_title"
|
||||||
style="?android:preferenceInformationStyle" />
|
style="?android:preferenceInformationStyle" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="current_address"
|
android:key="current_address"
|
||||||
android:title="@string/current_address"
|
android:title="@string/current_address"
|
||||||
style="?android:preferenceInformationStyle" />
|
style="?android:preferenceInformationStyle" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="repo_id"
|
android:key="repo_id"
|
||||||
android:title="@string/repo_id" />
|
android:title="@string/repo_id" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="directory"
|
android:key="directory"
|
||||||
android:title="@string/directory" />
|
android:title="@string/directory" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="repo_master"
|
android:key="repo_master"
|
||||||
android:title="@string/repo_master" />
|
android:title="@string/repo_master" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:key="nodes"
|
android:key="nodes"
|
||||||
android:title="@string/nodes" />
|
android:title="@string/nodes" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="versioning"
|
android:key="versioning"
|
||||||
android:title="@string/file_versioning" />
|
android:title="@string/file_versioning" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="versioning_keep"
|
android:key="versioning_keep"
|
||||||
android:title="@string/keep_versions"
|
android:title="@string/keep_versions"
|
||||||
android:inputType="numberDecimal" />
|
android:inputType="numberDecimal" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
|
@ -1,34 +1,34 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:persistent="false" >
|
android:persistent="false">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="repo_id"
|
android:key="repo_id"
|
||||||
android:title="@string/repo_id"
|
android:title="@string/repo_id"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
style="?android:preferenceInformationStyle" />
|
style="?android:preferenceInformationStyle" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="directory"
|
android:key="directory"
|
||||||
android:title="@string/directory"
|
android:title="@string/directory"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
style="?android:preferenceInformationStyle" />
|
style="?android:preferenceInformationStyle" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="repo_master"
|
android:key="repo_master"
|
||||||
android:title="@string/repo_master" />
|
android:title="@string/repo_master" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:key="nodes"
|
android:key="nodes"
|
||||||
android:title="@string/nodes" />
|
android:title="@string/nodes" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="versioning"
|
android:key="versioning"
|
||||||
android:title="File Versioning" />
|
android:title="File Versioning" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="versioning_keep"
|
android:key="versioning_keep"
|
||||||
android:title="@string/keep_versions"
|
android:title="@string/keep_versions"
|
||||||
android:inputType="numberDecimal" />
|
android:inputType="numberDecimal" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
Loading…
Reference in a new issue