mirror of
https://github.com/syncthing/syncthing-android.git
synced 2025-01-09 03:31:46 +00:00
* Add pref: Suggested new folder root (fixes #309) * Fix NPE in offline config reader (fixes #316) after folder has been created while Syncthing was not running * Fix language pref and root pref * Fix action bar not showing on sub-prefs screen (fixes #317) on Android < 7 * Add DATA, MEDIA to FileUtils#getExternalFilesDirUri (fixes #309) * SettingsActivity: Remove pref "SuggestNewFolderRoot" on API < 21 * Update Constants PREF_SUGGEST_NEW_FOLDER_ROOT_DATA, PREF_SUGGEST_NEW_FOLDER_ROOT_MEDIA * Update FolderActivity#onPathViewClick (fixes #309) to respect PREF_SUGGEST_NEW_FOLDER_ROOT_DATA * Imported de translation
This commit is contained in:
parent
ca17291561
commit
30efd903b5
8 changed files with 128 additions and 35 deletions
|
@ -41,6 +41,7 @@ import com.nutomic.syncthingandroid.service.SyncthingServiceBinder;
|
||||||
import com.nutomic.syncthingandroid.SyncthingApp;
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
import com.nutomic.syncthingandroid.util.ConfigRouter;
|
import com.nutomic.syncthingandroid.util.ConfigRouter;
|
||||||
import com.nutomic.syncthingandroid.util.FileUtils;
|
import com.nutomic.syncthingandroid.util.FileUtils;
|
||||||
|
import com.nutomic.syncthingandroid.util.FileUtils.ExternalStorageDirType;
|
||||||
import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
|
import com.nutomic.syncthingandroid.util.TextWatcherAdapter;
|
||||||
import com.nutomic.syncthingandroid.util.Util;
|
import com.nutomic.syncthingandroid.util.Util;
|
||||||
|
|
||||||
|
@ -293,13 +294,20 @@ public class FolderActivity extends SyncthingActivity {
|
||||||
@SuppressLint("InlinedAPI")
|
@SuppressLint("InlinedAPI")
|
||||||
private void onPathViewClick() {
|
private void onPathViewClick() {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
// API < 21
|
||||||
startActivityForResult(FolderPickerActivity.createIntent(this, mFolder.path, null),
|
startActivityForResult(FolderPickerActivity.createIntent(this, mFolder.path, null),
|
||||||
FolderPickerActivity.DIRECTORY_REQUEST_CODE);
|
FolderPickerActivity.DIRECTORY_REQUEST_CODE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String prefSuggestNewFolderRoot = mPreferences.getString(Constants.PREF_SUGGEST_NEW_FOLDER_ROOT, Constants.PREF_SUGGEST_NEW_FOLDER_ROOT_DATA);
|
||||||
|
|
||||||
// This has to be android.net.Uri as it implements a Parcelable.
|
// This has to be android.net.Uri as it implements a Parcelable.
|
||||||
android.net.Uri externalFilesDirUri = FileUtils.getExternalFilesDirUri(FolderActivity.this);
|
android.net.Uri externalFilesDirUri = FileUtils.getExternalFilesDirUri(
|
||||||
|
FolderActivity.this,
|
||||||
|
prefSuggestNewFolderRoot.equals(Constants.PREF_SUGGEST_NEW_FOLDER_ROOT_DATA) ?
|
||||||
|
ExternalStorageDirType.DATA :
|
||||||
|
ExternalStorageDirType.MEDIA
|
||||||
|
);
|
||||||
|
|
||||||
// Display storage access framework directory picker UI.
|
// Display storage access framework directory picker UI.
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||||
|
|
|
@ -154,7 +154,6 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
private Dialog mCurrentPrefScreenDialog = null;
|
private Dialog mCurrentPrefScreenDialog = null;
|
||||||
|
|
||||||
private Preference mCategoryRunConditions;
|
private Preference mCategoryRunConditions;
|
||||||
private CheckBoxPreference mStartServiceOnBoot;
|
|
||||||
private ListPreference mPowerSource;
|
private ListPreference mPowerSource;
|
||||||
private CheckBoxPreference mRunOnMobileData;
|
private CheckBoxPreference mRunOnMobileData;
|
||||||
private CheckBoxPreference mRunOnWifi;
|
private CheckBoxPreference mRunOnWifi;
|
||||||
|
@ -163,6 +162,13 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
private WifiSsidPreference mWifiSsidWhitelist;
|
private WifiSsidPreference mWifiSsidWhitelist;
|
||||||
private CheckBoxPreference mRunInFlightMode;
|
private CheckBoxPreference mRunInFlightMode;
|
||||||
|
|
||||||
|
/* Behaviour */
|
||||||
|
private CheckBoxPreference mStartServiceOnBoot;
|
||||||
|
private CheckBoxPreference mUseRoot;
|
||||||
|
private ListPreference mSuggestNewFolderRoot;
|
||||||
|
private Languages mLanguages;
|
||||||
|
|
||||||
|
/* Syncthing Options */
|
||||||
private Preference mCategorySyncthingOptions;
|
private Preference mCategorySyncthingOptions;
|
||||||
private EditTextPreference mDeviceName;
|
private EditTextPreference mDeviceName;
|
||||||
private EditTextPreference mListenAddresses;
|
private EditTextPreference mListenAddresses;
|
||||||
|
@ -179,7 +185,6 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
private CheckBoxPreference mUrAccepted;
|
private CheckBoxPreference mUrAccepted;
|
||||||
|
|
||||||
/* Experimental options */
|
/* Experimental options */
|
||||||
private CheckBoxPreference mUseRoot;
|
|
||||||
private CheckBoxPreference mUseWakelock;
|
private CheckBoxPreference mUseWakelock;
|
||||||
private CheckBoxPreference mUseTor;
|
private CheckBoxPreference mUseTor;
|
||||||
private EditTextPreference mSocksProxyAddress;
|
private EditTextPreference mSocksProxyAddress;
|
||||||
|
@ -248,14 +253,10 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
if (Build.VERSION.SDK_INT >= 24) {
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
categoryBehaviour.removePreference(languagePref);
|
categoryBehaviour.removePreference(languagePref);
|
||||||
} else {
|
} else {
|
||||||
Languages languages = new Languages(getActivity());
|
mLanguages = new Languages(getActivity());
|
||||||
languagePref.setDefaultValue(Languages.USE_SYSTEM_DEFAULT);
|
languagePref.setDefaultValue(mLanguages.USE_SYSTEM_DEFAULT);
|
||||||
languagePref.setEntries(languages.getAllNames());
|
languagePref.setEntries(mLanguages.getAllNames());
|
||||||
languagePref.setEntryValues(languages.getSupportedLocales());
|
languagePref.setEntryValues(mLanguages.getSupportedLocales());
|
||||||
languagePref.setOnPreferenceChangeListener((p, o) -> {
|
|
||||||
languages.forceChangeLanguage(getActivity(), (String) o);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
|
|
||||||
|
@ -294,6 +295,14 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
(CheckBoxPreference) findPreference(Constants.PREF_START_SERVICE_ON_BOOT);
|
(CheckBoxPreference) findPreference(Constants.PREF_START_SERVICE_ON_BOOT);
|
||||||
mUseRoot =
|
mUseRoot =
|
||||||
(CheckBoxPreference) findPreference(Constants.PREF_USE_ROOT);
|
(CheckBoxPreference) findPreference(Constants.PREF_USE_ROOT);
|
||||||
|
mSuggestNewFolderRoot =
|
||||||
|
(ListPreference) findPreference(Constants.PREF_SUGGEST_NEW_FOLDER_ROOT);
|
||||||
|
screen.findPreference(Constants.PREF_SUGGEST_NEW_FOLDER_ROOT).setSummary(mSuggestNewFolderRoot.getEntry());
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
// Remove preference as FileUtils#getExternalFilesDirUri is only supported on API 21+ (LOLLIPOP+).
|
||||||
|
categoryBehaviour.removePreference(mSuggestNewFolderRoot);
|
||||||
|
}
|
||||||
|
setPreferenceCategoryChangeListener(categoryBehaviour, this::onBehaviourPreferenceChange);
|
||||||
|
|
||||||
/* Syncthing options */
|
/* Syncthing options */
|
||||||
mDeviceName = (EditTextPreference) findPreference("deviceName");
|
mDeviceName = (EditTextPreference) findPreference("deviceName");
|
||||||
|
@ -350,7 +359,6 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
mUseWakelock.setChecked(false);
|
mUseWakelock.setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUseRoot.setOnPreferenceClickListener(this);
|
|
||||||
mUseWakelock.setOnPreferenceChangeListener(this);
|
mUseWakelock.setOnPreferenceChangeListener(this);
|
||||||
mUseTor.setOnPreferenceChangeListener(this);
|
mUseTor.setOnPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
@ -557,6 +565,27 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean onBehaviourPreferenceChange(Preference preference, Object o) {
|
||||||
|
switch (preference.getKey()) {
|
||||||
|
case Constants.PREF_USE_ROOT:
|
||||||
|
if ((Boolean) o) {
|
||||||
|
new TestRootTask(this).execute();
|
||||||
|
} else {
|
||||||
|
new Thread(() -> Util.fixAppDataPermissions(getActivity())).start();
|
||||||
|
mPendingConfig = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Constants.PREF_SUGGEST_NEW_FOLDER_ROOT:
|
||||||
|
mSuggestNewFolderRoot.setValue(o.toString());
|
||||||
|
preference.setSummary(mSuggestNewFolderRoot.getEntry());
|
||||||
|
break;
|
||||||
|
case Languages.PREFERENCE_LANGUAGE:
|
||||||
|
mLanguages.forceChangeLanguage(getActivity(), (String) o);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean onSyncthingPreferenceChange(Preference preference, Object o) {
|
public boolean onSyncthingPreferenceChange(Preference preference, Object o) {
|
||||||
Splitter splitter = Splitter.on(",").trimResults().omitEmptyStrings();
|
Splitter splitter = Splitter.on(",").trimResults().omitEmptyStrings();
|
||||||
switch (preference.getKey()) {
|
switch (preference.getKey()) {
|
||||||
|
@ -710,16 +739,6 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
final Intent intent;
|
final Intent intent;
|
||||||
switch (preference.getKey()) {
|
switch (preference.getKey()) {
|
||||||
case Constants.PREF_USE_ROOT:
|
|
||||||
if (mUseRoot.isChecked()) {
|
|
||||||
// Only check preference after root was granted.
|
|
||||||
mUseRoot.setChecked(false);
|
|
||||||
new TestRootTask(this).execute();
|
|
||||||
} else {
|
|
||||||
new Thread(() -> Util.fixAppDataPermissions(getActivity())).start();
|
|
||||||
mPendingConfig = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case KEY_OPEN_ISSUE_TRACKER:
|
case KEY_OPEN_ISSUE_TRACKER:
|
||||||
intent = new Intent(getActivity(), WebViewActivity.class);
|
intent = new Intent(getActivity(), WebViewActivity.class);
|
||||||
intent.putExtra(WebViewActivity.EXTRA_WEB_URL, getString(R.string.issue_tracker_url));
|
intent.putExtra(WebViewActivity.EXTRA_WEB_URL, getString(R.string.issue_tracker_url));
|
||||||
|
@ -829,13 +848,15 @@ public class SettingsActivity extends SyncthingActivity {
|
||||||
if (settingsFragment == null) {
|
if (settingsFragment == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
settingsFragment.mUseRoot.setOnPreferenceChangeListener(null);
|
||||||
|
settingsFragment.mUseRoot.setChecked(haveRoot);
|
||||||
if (haveRoot) {
|
if (haveRoot) {
|
||||||
settingsFragment.mPendingConfig = true;
|
settingsFragment.mPendingConfig = true;
|
||||||
settingsFragment.mUseRoot.setChecked(true);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(settingsFragment.getActivity(), R.string.toast_root_denied, Toast.LENGTH_SHORT)
|
Toast.makeText(settingsFragment.getActivity(), R.string.toast_root_denied, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
settingsFragment.mUseRoot.setOnPreferenceChangeListener(settingsFragment::onBehaviourPreferenceChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,22 @@ public class Constants {
|
||||||
|
|
||||||
// Preferences - Behaviour
|
// Preferences - Behaviour
|
||||||
public static final String PREF_USE_ROOT = "use_root";
|
public static final String PREF_USE_ROOT = "use_root";
|
||||||
|
|
||||||
|
public static final String PREF_SUGGEST_NEW_FOLDER_ROOT = "suggest_new_folder_root";
|
||||||
|
public static final String PREF_SUGGEST_NEW_FOLDER_ROOT_DATA = "external_android_data";
|
||||||
|
public static final String PREF_SUGGEST_NEW_FOLDER_ROOT_MEDIA = "external_android_media";
|
||||||
|
|
||||||
|
|
||||||
|
// Preferences - Troubleshooting
|
||||||
public static final String PREF_ENVIRONMENT_VARIABLES = "environment_variables";
|
public static final String PREF_ENVIRONMENT_VARIABLES = "environment_variables";
|
||||||
public static final String PREF_DEBUG_FACILITIES_ENABLED = "debug_facilities_enabled";
|
public static final String PREF_DEBUG_FACILITIES_ENABLED = "debug_facilities_enabled";
|
||||||
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
|
|
||||||
|
// Preferences - Experimental
|
||||||
public static final String PREF_USE_TOR = "use_tor";
|
public static final String PREF_USE_TOR = "use_tor";
|
||||||
public static final String PREF_SOCKS_PROXY_ADDRESS = "socks_proxy_address";
|
public static final String PREF_SOCKS_PROXY_ADDRESS = "socks_proxy_address";
|
||||||
public static final String PREF_HTTP_PROXY_ADDRESS = "http_proxy_address";
|
public static final String PREF_HTTP_PROXY_ADDRESS = "http_proxy_address";
|
||||||
public static final String PREF_BROADCAST_SERVICE_CONTROL = "broadcast_service_control";
|
public static final String PREF_BROADCAST_SERVICE_CONTROL = "broadcast_service_control";
|
||||||
|
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
|
||||||
|
|
||||||
// Preferences - per Folder and Device Sync Conditions
|
// Preferences - per Folder and Device Sync Conditions
|
||||||
public static final String PREF_OBJECT_PREFIX_FOLDER = "sc_folder_";
|
public static final String PREF_OBJECT_PREFIX_FOLDER = "sc_folder_";
|
||||||
|
|
|
@ -47,6 +47,11 @@ public class FileUtils {
|
||||||
private static final String PRIMARY_VOLUME_NAME = "primary";
|
private static final String PRIMARY_VOLUME_NAME = "primary";
|
||||||
private static final String HOME_VOLUME_NAME = "home";
|
private static final String HOME_VOLUME_NAME = "home";
|
||||||
|
|
||||||
|
public enum ExternalStorageDirType {
|
||||||
|
DATA,
|
||||||
|
MEDIA
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@TargetApi(21)
|
@TargetApi(21)
|
||||||
public static String getAbsolutePathFromSAFUri(Context context, @Nullable final Uri safResultUri) {
|
public static String getAbsolutePathFromSAFUri(Context context, @Nullable final Uri safResultUri) {
|
||||||
|
@ -155,24 +160,37 @@ public class FileUtils {
|
||||||
* has been blocked since Android 7+, we need to build the Uri
|
* has been blocked since Android 7+, we need to build the Uri
|
||||||
* manually after discovering the first external storage.
|
* manually after discovering the first external storage.
|
||||||
* This is crucial to assist the user finding a writeable folder
|
* This is crucial to assist the user finding a writeable folder
|
||||||
* to use syncthing's two way sync feature.
|
* to use Syncthing's two way sync feature.
|
||||||
|
* API for getExternalFilesDirs(): 19+ (KITKAT+)
|
||||||
|
* API for getExternalMediaDirs(): 21+ (LOLLIPOP+)
|
||||||
*/
|
*/
|
||||||
@TargetApi(19)
|
@TargetApi(21)
|
||||||
public static android.net.Uri getExternalFilesDirUri(Context context) {
|
public static android.net.Uri getExternalFilesDirUri(Context context, ExternalStorageDirType extDirType) {
|
||||||
try {
|
try {
|
||||||
/**
|
/**
|
||||||
* Determine the app's private data folder on external storage if present.
|
* Determine the app's private data folder on external storage if present.
|
||||||
* e.g. "/storage/abcd-efgh/Android/[PACKAGE_NAME]/files"
|
* e.g. "/storage/abcd-efgh/Android/[PACKAGE_NAME]/files"
|
||||||
*/
|
*/
|
||||||
ArrayList<File> externalFilesDir = new ArrayList<>();
|
ArrayList<File> externalFilesDir = new ArrayList<>();
|
||||||
|
switch(extDirType ){
|
||||||
|
case DATA:
|
||||||
externalFilesDir.addAll(Arrays.asList(context.getExternalFilesDirs(null)));
|
externalFilesDir.addAll(Arrays.asList(context.getExternalFilesDirs(null)));
|
||||||
externalFilesDir.remove(context.getExternalFilesDir(null));
|
externalFilesDir.remove(context.getExternalFilesDir(null));
|
||||||
|
break;
|
||||||
|
case MEDIA:
|
||||||
|
externalFilesDir.addAll(Arrays.asList(context.getExternalMediaDirs()));
|
||||||
|
if (externalFilesDir.size() > 0) {
|
||||||
|
externalFilesDir.remove(externalFilesDir.get(0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
externalFilesDir.remove(null); // getExternalFilesDirs may return null for an ejected SDcard.
|
externalFilesDir.remove(null); // getExternalFilesDirs may return null for an ejected SDcard.
|
||||||
if (externalFilesDir.size() == 0) {
|
if (externalFilesDir.size() == 0) {
|
||||||
Log.w(TAG, "Could not determine app's private files directory on external storage.");
|
Log.w(TAG, "Could not determine app's private files directory on external storage.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String absPath = externalFilesDir.get(0).getAbsolutePath();
|
String absPath = externalFilesDir.get(0).getAbsolutePath();
|
||||||
|
// Log.v(TAG, "getExternalFilesDirUri: absPath=" + absPath);
|
||||||
String[] segments = absPath.split("/");
|
String[] segments = absPath.split("/");
|
||||||
if (segments.length < 2) {
|
if (segments.length < 2) {
|
||||||
Log.w(TAG, "Could not extract volumeId from app's private files path '" + absPath + "'");
|
Log.w(TAG, "Could not extract volumeId from app's private files path '" + absPath + "'");
|
||||||
|
@ -180,11 +198,20 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
// Extract the volumeId, e.g. "abcd-efgh"
|
// Extract the volumeId, e.g. "abcd-efgh"
|
||||||
String volumeId = segments[2];
|
String volumeId = segments[2];
|
||||||
// Build the content Uri for our private "files" folder.
|
switch(extDirType ){
|
||||||
|
case DATA:
|
||||||
|
// Build the content Uri for our private ".../data/[PKG_NAME]/files" folder.
|
||||||
return android.net.Uri.parse(
|
return android.net.Uri.parse(
|
||||||
"content://com.android.externalstorage.documents/document/" +
|
"content://com.android.externalstorage.documents/document/" +
|
||||||
volumeId + "%3AAndroid%2Fdata%2F" +
|
volumeId + "%3AAndroid%2Fdata%2F" +
|
||||||
context.getPackageName() + "%2Ffiles");
|
context.getPackageName() + "%2Ffiles");
|
||||||
|
case MEDIA:
|
||||||
|
// Build the content Uri for our private ".../media/[PKG_NAME]" folder.
|
||||||
|
return android.net.Uri.parse(
|
||||||
|
"content://com.android.externalstorage.documents/document/" +
|
||||||
|
volumeId + "%3AAndroid%2Fmedia%2F" +
|
||||||
|
context.getPackageName());
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "getExternalFilesDirUri exception", e);
|
Log.w(TAG, "getExternalFilesDirUri exception", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,6 +439,13 @@ Bitte melden Sie auftretende Probleme via GitHub.</string>
|
||||||
|
|
||||||
<string name="use_root_summary">Wenn Syncthing unter dem Root-Benutzer ausgeführt wird, hat es Schreibzugriff auf Ordner, die Android normalerweise auf schreibgeschützten Zugriff beschränkt. Verwende diese Funktion mit Bedacht.</string>
|
<string name="use_root_summary">Wenn Syncthing unter dem Root-Benutzer ausgeführt wird, hat es Schreibzugriff auf Ordner, die Android normalerweise auf schreibgeschützten Zugriff beschränkt. Verwende diese Funktion mit Bedacht.</string>
|
||||||
|
|
||||||
|
<string name="suggest_new_folder_root_title">Wähle Stamm für neue Ordner</string>
|
||||||
|
|
||||||
|
<string-array name="suggest_new_folder_root_entries">
|
||||||
|
<item>[Ext_Speicher]/Android/data</item>
|
||||||
|
<item>[Ext_Speicher]/Android/media</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string name="preference_language_title">Sprache</string>
|
<string name="preference_language_title">Sprache</string>
|
||||||
|
|
||||||
<string name="preference_language_summary">Anwendungssprache ändern</string>
|
<string name="preference_language_summary">Anwendungssprache ändern</string>
|
||||||
|
|
|
@ -15,4 +15,10 @@
|
||||||
<item>battery_power</item>
|
<item>battery_power</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Preference screen -->
|
||||||
|
<string-array name="suggest_new_folder_root_values">
|
||||||
|
<item>external_android_data</item>
|
||||||
|
<item>external_android_media</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -442,6 +442,13 @@ Please report any problems you encounter via Github.</string>
|
||||||
|
|
||||||
<string name="use_root_summary">Running Syncthing as root allows it to write to folders Android normally restricts to be readonly accessed. Use this feature cautious.</string>
|
<string name="use_root_summary">Running Syncthing as root allows it to write to folders Android normally restricts to be readonly accessed. Use this feature cautious.</string>
|
||||||
|
|
||||||
|
<string name="suggest_new_folder_root_title">Select new folder root</string>
|
||||||
|
|
||||||
|
<string-array name="suggest_new_folder_root_entries">
|
||||||
|
<item>[external_storage]/Android/data</item>
|
||||||
|
<item>[external_storage]/Android/media</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string name="preference_language_title">Language</string>
|
<string name="preference_language_title">Language</string>
|
||||||
|
|
||||||
<string name="preference_language_summary">Change the app language</string>
|
<string name="preference_language_summary">Change the app language</string>
|
||||||
|
|
|
@ -90,6 +90,14 @@
|
||||||
android:summary="@string/use_root_summary"
|
android:summary="@string/use_root_summary"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:key="suggest_new_folder_root"
|
||||||
|
android:title="@string/suggest_new_folder_root_title"
|
||||||
|
android:entryValues="@array/suggest_new_folder_root_values"
|
||||||
|
android:entries="@array/suggest_new_folder_root_entries"
|
||||||
|
android:summary="@null"
|
||||||
|
android:defaultValue="external_android_data" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:key="pref_current_language"
|
android:key="pref_current_language"
|
||||||
android:title="@string/preference_language_title"
|
android:title="@string/preference_language_title"
|
||||||
|
|
Loading…
Reference in a new issue