From f6f90c9c2bca04fa71ac7a197a9fd40057fcac66 Mon Sep 17 00:00:00 2001 From: Catfriend1 Date: Mon, 15 Oct 2018 00:29:52 +0200 Subject: [PATCH] Allow specifying different sync conditions per folder (fixes #57) (#66) * WIP - https://github.com/Catfriend1/syncthing-android/issues/57 * Add sync conditions activity * Update folder edit layout Implement SyncConditionsActivity stub * Add dialog open logic * Fix UI glitches * Update APK version to 0.14.51.4 / 4167 * Revert "Update APK version to 0.14.51.4 / 4167" This reverts commit 47bc4aa9ba219c134047765cc2fb49a9fa651fbe. * Implement WiFi Ssid Whitelist UI * Read per-folder sync conditions from prefs * Implement onCheckedChange listeners * Implement saving object sync conditions * Remove early draft stuff * Implement per folder master switch for custom sync conditions * FolderActivity - More log * Improve generation of object-specific constants * Added onSyncPreconditionChanged to RunConditionMonitor * Fix UI glitch * Fix non-harming typos * Refactor "on mobile data" sync condition * Refactor "on wifi" sync condition * Refactor "on whitelisted wifi" sync condition * Refactor "on metered wifi" sync condition * Refactor RunConditionMonitor#decideShouldRun * RunConditionMonitor - Rename variables * Pause/Unpause folders using RunConditionMonitor events * Implement RunConditionMonitor#SyncConditionResult * Fix lint - use editor.apply instead of editor.commit * Updated translations * Add null check in RestApi * Fix missing explanation text * Fix german translation * Update APK version to 0.14.51.6 / 4169 * Update whatsnew --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 7 + .../syncthingandroid/DaggerComponent.java | 4 + .../activities/FolderActivity.java | 109 +++++-- .../activities/SettingsActivity.java | 34 +- .../activities/SyncConditionsActivity.java | 295 ++++++++++++++++++ .../syncthingandroid/service/Constants.java | 28 ++ .../service/EventProcessor.java | 22 +- .../syncthingandroid/service/RestApi.java | 35 +++ .../service/RunConditionMonitor.java | 255 +++++++++++---- .../service/SyncthingService.java | 63 ++-- .../views/WifiSsidPreference.java | 5 +- app/src/main/play/en-GB/whatsnew | 15 +- .../ic_pause_circle_outline_black_24dp.png | Bin 0 -> 454 bytes ...connected_no_internet_4_bar_black_24dp.png | Bin 0 -> 160 bytes .../ic_signal_wifi_0_bar_black_24dp.png | Bin 0 -> 263 bytes .../res/drawable-hdpi/ic_wifi_black_24dp.png | Bin 0 -> 387 bytes .../ic_wifi_tethering_black_24dp.png | Bin 0 -> 667 bytes .../ic_pause_circle_outline_black_24dp.png | Bin 0 -> 312 bytes ...connected_no_internet_4_bar_black_24dp.png | Bin 0 -> 137 bytes .../ic_signal_wifi_0_bar_black_24dp.png | Bin 0 -> 209 bytes .../res/drawable-mdpi/ic_wifi_black_24dp.png | Bin 0 -> 269 bytes .../ic_wifi_tethering_black_24dp.png | Bin 0 -> 419 bytes .../ic_pause_circle_outline_black_24dp.png | Bin 0 -> 594 bytes ...connected_no_internet_4_bar_black_24dp.png | Bin 0 -> 175 bytes .../ic_signal_wifi_0_bar_black_24dp.png | Bin 0 -> 338 bytes .../res/drawable-xhdpi/ic_wifi_black_24dp.png | Bin 0 -> 483 bytes .../ic_wifi_tethering_black_24dp.png | Bin 0 -> 873 bytes .../ic_pause_circle_outline_black_24dp.png | Bin 0 -> 848 bytes ...connected_no_internet_4_bar_black_24dp.png | Bin 0 -> 210 bytes .../ic_signal_wifi_0_bar_black_24dp.png | Bin 0 -> 487 bytes .../drawable-xxhdpi/ic_wifi_black_24dp.png | Bin 0 -> 695 bytes .../ic_wifi_tethering_black_24dp.png | Bin 0 -> 1276 bytes .../ic_pause_circle_outline_black_24dp.png | Bin 0 -> 1168 bytes ...connected_no_internet_4_bar_black_24dp.png | Bin 0 -> 239 bytes .../ic_signal_wifi_0_bar_black_24dp.png | Bin 0 -> 602 bytes .../drawable-xxxhdpi/ic_wifi_black_24dp.png | Bin 0 -> 883 bytes .../ic_wifi_tethering_black_24dp.png | Bin 0 -> 1747 bytes .../res/layout/activity_sync_conditions.xml | 189 +++++++++++ app/src/main/res/layout/fragment_device.xml | 4 +- app/src/main/res/layout/fragment_folder.xml | 86 ++++- .../main/res/layout/item_wifi_ssid_form.xml | 11 + .../res/menu/sync_conditions_settings.xml | 12 + app/src/main/res/values-ar/strings.xml | 4 - app/src/main/res/values-bg/strings.xml | 26 +- app/src/main/res/values-ca-rES/strings.xml | 32 +- app/src/main/res/values-cs/strings.xml | 32 +- app/src/main/res/values-da/strings.xml | 28 +- app/src/main/res/values-de-rAT/strings.xml | 4 + app/src/main/res/values-de-rDE/strings.xml | 4 + app/src/main/res/values-de/strings.xml | 45 +-- app/src/main/res/values-el/strings.xml | 32 +- app/src/main/res/values-es-rMX/strings.xml | 27 +- app/src/main/res/values-es/strings.xml | 28 +- app/src/main/res/values-fi/strings.xml | 22 +- app/src/main/res/values-fr/strings.xml | 32 +- app/src/main/res/values-hu/strings.xml | 32 +- app/src/main/res/values-in/strings.xml | 28 +- app/src/main/res/values-it/strings.xml | 32 +- app/src/main/res/values-ja/strings.xml | 32 +- app/src/main/res/values-ko/strings.xml | 32 +- app/src/main/res/values-nb/strings.xml | 27 +- app/src/main/res/values-nl/strings.xml | 32 +- app/src/main/res/values-nn/strings.xml | 27 +- app/src/main/res/values-no/strings.xml | 118 +------ app/src/main/res/values-pl/strings.xml | 26 +- app/src/main/res/values-pt-rBR/strings.xml | 32 +- app/src/main/res/values-pt/strings.xml | 28 +- app/src/main/res/values-ro/strings.xml | 32 +- app/src/main/res/values-ru/strings.xml | 32 +- app/src/main/res/values-sk/strings.xml | 25 +- app/src/main/res/values-sv-rSE/strings.xml | 4 + app/src/main/res/values-sv/strings.xml | 32 +- app/src/main/res/values-tr/strings.xml | 28 +- app/src/main/res/values-uk/strings.xml | 20 +- app/src/main/res/values-vi/strings.xml | 27 +- app/src/main/res/values-zh-rCN/strings.xml | 32 +- app/src/main/res/values-zh-rTW/strings.xml | 32 +- app/src/main/res/values/strings.xml | 28 +- app/src/main/res/values/styles.xml | 5 + 80 files changed, 1142 insertions(+), 1095 deletions(-) create mode 100644 app/src/main/java/com/nutomic/syncthingandroid/activities/SyncConditionsActivity.java create mode 100644 app/src/main/res/drawable-hdpi/ic_pause_circle_outline_black_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_signal_wifi_0_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_wifi_black_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_wifi_tethering_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_pause_circle_outline_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_signal_wifi_0_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_wifi_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_wifi_tethering_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_pause_circle_outline_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_signal_wifi_0_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_wifi_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_wifi_tethering_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_pause_circle_outline_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_signal_wifi_0_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_wifi_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_wifi_tethering_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_pause_circle_outline_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_0_bar_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_wifi_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_wifi_tethering_black_24dp.png create mode 100644 app/src/main/res/layout/activity_sync_conditions.xml create mode 100644 app/src/main/res/layout/item_wifi_ssid_form.xml create mode 100644 app/src/main/res/menu/sync_conditions_settings.xml create mode 100644 app/src/main/res/values-de-rAT/strings.xml create mode 100644 app/src/main/res/values-de-rDE/strings.xml create mode 100644 app/src/main/res/values-sv-rSE/strings.xml diff --git a/app/build.gradle b/app/build.gradle index 9ef59962..80832e3b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,8 +35,8 @@ android { applicationId "com.github.catfriend1.syncthingandroid" minSdkVersion 16 targetSdkVersion 26 - versionCode 4168 - versionName "0.14.51.5" + versionCode 4169 + versionName "0.14.51.6" testApplicationId 'com.github.catfriend1.syncthingandroid.test' testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' playAccountConfig = playAccountConfigs.defaultAccountConfig diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f32d7b1b..7a9019bc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,6 +90,13 @@ android:name="android.support.UI_OPTIONS" android:value="splitActionBarWhenNarrow" /> + + + diff --git a/app/src/main/java/com/nutomic/syncthingandroid/DaggerComponent.java b/app/src/main/java/com/nutomic/syncthingandroid/DaggerComponent.java index 58661667..a0fad95d 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/DaggerComponent.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/DaggerComponent.java @@ -1,9 +1,11 @@ package com.nutomic.syncthingandroid; import com.nutomic.syncthingandroid.activities.FirstStartActivity; +import com.nutomic.syncthingandroid.activities.FolderActivity; import com.nutomic.syncthingandroid.activities.FolderPickerActivity; import com.nutomic.syncthingandroid.activities.MainActivity; import com.nutomic.syncthingandroid.activities.SettingsActivity; +import com.nutomic.syncthingandroid.activities.SyncConditionsActivity; import com.nutomic.syncthingandroid.receiver.AppConfigReceiver; import com.nutomic.syncthingandroid.service.RunConditionMonitor; import com.nutomic.syncthingandroid.service.EventProcessor; @@ -24,7 +26,9 @@ public interface DaggerComponent { void inject(SyncthingApp app); void inject(MainActivity activity); void inject(FirstStartActivity activity); + void inject(FolderActivity activity); void inject(FolderPickerActivity activity); + void inject(SyncConditionsActivity activity); void inject(Languages languages); void inject(SyncthingService service); void inject(RunConditionMonitor runConditionMonitor); diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/FolderActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/FolderActivity.java index 5d230b6e..e0738b9b 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/FolderActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/FolderActivity.java @@ -1,11 +1,11 @@ package com.nutomic.syncthingandroid.activities; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -19,6 +19,7 @@ import android.util.TypedValue; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.EditText; @@ -26,7 +27,6 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; -import com.google.common.base.Objects; import com.google.gson.Gson; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.model.Device; @@ -35,17 +35,19 @@ import com.nutomic.syncthingandroid.model.FolderIgnoreList; import com.nutomic.syncthingandroid.service.Constants; import com.nutomic.syncthingandroid.service.RestApi; import com.nutomic.syncthingandroid.service.SyncthingService; +import com.nutomic.syncthingandroid.SyncthingApp; import com.nutomic.syncthingandroid.util.FileUtils; import com.nutomic.syncthingandroid.util.TextWatcherAdapter; import com.nutomic.syncthingandroid.util.Util; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.Random; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + import static android.support.v4.view.MarginLayoutParamsCompat.setMarginEnd; import static android.support.v4.view.MarginLayoutParamsCompat.setMarginStart; import static android.util.TypedValue.COMPLEX_UNIT_DIP; @@ -95,9 +97,12 @@ public class FolderActivity extends SyncthingActivity private TextView mAccessExplanationView; private TextView mFolderTypeView; private TextView mFolderTypeDescriptionView; + private ViewGroup mDevicesContainer; private SwitchCompat mFolderFileWatcher; private SwitchCompat mFolderPaused; - private ViewGroup mDevicesContainer; + private SwitchCompat mCustomSyncConditionsSwitch; + private TextView mCustomSyncConditionsDescription; + private TextView mCustomSyncConditionsDialog; private TextView mPullOrderTypeView; private TextView mPullOrderDescriptionView; private TextView mVersioningDescriptionView; @@ -105,6 +110,9 @@ public class FolderActivity extends SyncthingActivity private TextView mEditIgnoreListTitle; private EditText mEditIgnoreListContent; + @Inject + SharedPreferences mPreferences; + private boolean mIsCreateMode; private boolean mFolderNeedsToUpdate = false; @@ -137,6 +145,12 @@ public class FolderActivity extends SyncthingActivity mFolder.paused = isChecked; mFolderNeedsToUpdate = true; break; + case R.id.customSyncConditionsSwitch: + mCustomSyncConditionsDescription.setEnabled(isChecked); + mCustomSyncConditionsDialog.setEnabled(isChecked); + // This is needed to display the "discard changes dialog". + mFolderNeedsToUpdate = true; + break; case R.id.device_toggle: Device device = (Device) view.getTag(); if (isChecked) { @@ -153,6 +167,7 @@ public class FolderActivity extends SyncthingActivity @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + ((SyncthingApp) getApplication()).component().inject(this); setContentView(R.layout.fragment_folder); mIsCreateMode = getIntent().getBooleanExtra(EXTRA_IS_CREATE, false); @@ -167,6 +182,9 @@ public class FolderActivity extends SyncthingActivity mFolderTypeDescriptionView = findViewById(R.id.folderTypeDescription); mFolderFileWatcher = findViewById(R.id.fileWatcher); mFolderPaused = findViewById(R.id.folderPause); + mCustomSyncConditionsSwitch = findViewById(R.id.customSyncConditionsSwitch); + mCustomSyncConditionsDescription = findViewById(R.id.customSyncConditionsDescription); + mCustomSyncConditionsDialog = findViewById(R.id.customSyncConditionsDialog); mPullOrderTypeView = findViewById(R.id.pullOrderType); mPullOrderDescriptionView = findViewById(R.id.pullOrderDescription); mVersioningDescriptionView = findViewById(R.id.versioningDescription); @@ -176,6 +194,7 @@ public class FolderActivity extends SyncthingActivity mEditIgnoreListContent = findViewById(R.id.edit_ignore_list_content); mPathView.setOnClickListener(view -> onPathViewClick()); + mCustomSyncConditionsDialog.setOnClickListener(view -> onCustomSyncConditionsDialogClick()); findViewById(R.id.folderTypeContainer).setOnClickListener(v -> showFolderTypeDialog()); findViewById(R.id.pullOrderContainer).setOnClickListener(v -> showPullOrderDialog()); @@ -241,6 +260,20 @@ public class FolderActivity extends SyncthingActivity startActivityForResult(intent, CHOOSE_FOLDER_REQUEST); } + /** + * Invoked after user clicked on the {@link mCustomSyncConditionsDialog} label. + */ + @SuppressLint("InlinedAPI") + private void onCustomSyncConditionsDialogClick() { + startActivityForResult( + SyncConditionsActivity.createIntent( + this, Constants.PREF_OBJECT_PREFIX_FOLDER + mFolder.id, mFolder.label + ), + 0 + ); + return; + } + private void showFolderTypeDialog() { if (TextUtils.isEmpty(mFolder.path)) { Toast.makeText(this, R.string.folder_path_required, Toast.LENGTH_LONG) @@ -407,6 +440,7 @@ public class FolderActivity extends SyncthingActivity mIdView.removeTextChangedListener(mTextWatcher); mFolderFileWatcher.setOnCheckedChangeListener(null); mFolderPaused.setOnCheckedChangeListener(null); + mCustomSyncConditionsSwitch.setOnCheckedChangeListener(null); // Update views mLabelView.setText(mFolder.label); @@ -416,8 +450,23 @@ public class FolderActivity extends SyncthingActivity updateVersioningDescription(); mFolderFileWatcher.setChecked(mFolder.fsWatcherEnabled); mFolderPaused.setChecked(mFolder.paused); - List devicesList = getApi().getDevices(false); + findViewById(R.id.editIgnoresContainer).setVisibility(mIsCreateMode ? View.GONE : View.VISIBLE); + // Update views - custom sync conditions. + mCustomSyncConditionsSwitch.setChecked(false); + if (mIsCreateMode) { + findViewById(R.id.customSyncConditionsContainer).setVisibility(View.GONE); + } else { + mCustomSyncConditionsSwitch.setChecked(mPreferences.getBoolean( + Constants.DYN_PREF_OBJECT_CUSTOM_SYNC_CONDITIONS(Constants.PREF_OBJECT_PREFIX_FOLDER + mFolder.id), false + )); + } + mCustomSyncConditionsSwitch.setEnabled(!mIsCreateMode); + mCustomSyncConditionsDescription.setEnabled(mCustomSyncConditionsSwitch.isChecked()); + mCustomSyncConditionsDialog.setEnabled(mCustomSyncConditionsSwitch.isChecked()); + + // Populate devicesList. + List devicesList = getApi().getDevices(false); mDevicesContainer.removeAllViews(); if (devicesList.isEmpty()) { addEmptyDeviceListView(); @@ -432,6 +481,7 @@ public class FolderActivity extends SyncthingActivity mIdView.addTextChangedListener(mTextWatcher); mFolderFileWatcher.setOnCheckedChangeListener(mCheckedListener); mFolderPaused.setOnCheckedChangeListener(mCheckedListener); + mCustomSyncConditionsSwitch.setOnCheckedChangeListener(mCheckedListener); } @Override @@ -652,25 +702,38 @@ public class FolderActivity extends SyncthingActivity } private void updateFolder() { - if (!mIsCreateMode) { - RestApi restApi = getApi(); - /** - * RestApi is guaranteed not to be null as {@link onServiceStateChange} - * immediately finishes this activity if SyncthingService shuts down. - */ - /* - if (restApi == null) { - Log.e(TAG, "updateFolder: restApi == null"); - return; - } - */ - // Update ignore list. - String[] ignore = mEditIgnoreListContent.getText().toString().split("\n"); - restApi.postFolderIgnoreList(mFolder.id, ignore); - - // Update model and send the config to REST endpoint. - restApi.updateFolder(mFolder); + if (mIsCreateMode) { + // If we are about to create this folder, we cannot update via restApi. + return; } + + // Save folder specific preferences. + Log.v(TAG, "updateFolder: mFolder.id = \'" + mFolder.id + "\'"); + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean( + Constants.DYN_PREF_OBJECT_CUSTOM_SYNC_CONDITIONS(Constants.PREF_OBJECT_PREFIX_FOLDER + mFolder.id), + mCustomSyncConditionsSwitch.isChecked() + ); + editor.apply(); + + // Update folder via restApi. + RestApi restApi = getApi(); + /** + * RestApi is guaranteed not to be null as {@link onServiceStateChange} + * immediately finishes this activity if SyncthingService shuts down. + */ + /* + if (restApi == null) { + Log.e(TAG, "updateFolder: restApi == null"); + return; + } + */ + // Update ignore list. + String[] ignore = mEditIgnoreListContent.getText().toString().split("\n"); + restApi.postFolderIgnoreList(mFolder.id, ignore); + + // Update model and send the config to REST endpoint. + restApi.updateFolder(mFolder); } @Override diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java index cddf2259..e9ca27bd 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/SettingsActivity.java @@ -132,7 +132,7 @@ public class SettingsActivity extends SyncthingActivity { private Preference mSyncthingVersion; private SyncthingService mSyncthingService; - private RestApi mApi; + private RestApi mRestApi; private Options mOptions; private Config.Gui mGui; @@ -312,21 +312,21 @@ public class SettingsActivity extends SyncthingActivity { @Override public void onServiceStateChange(SyncthingService.State currentState) { - mApi = mSyncthingService.getApi(); - boolean isSyncthingRunning = (mApi != null) && - mApi.isConfigLoaded() && + mRestApi = mSyncthingService.getApi(); + boolean isSyncthingRunning = (mRestApi != null) && + mRestApi.isConfigLoaded() && (currentState == SyncthingService.State.ACTIVE); mCategorySyncthingOptions.setEnabled(isSyncthingRunning); if (!isSyncthingRunning) return; - mSyncthingVersion.setSummary(mApi.getVersion()); - mOptions = mApi.getOptions(); - mGui = mApi.getGui(); + mSyncthingVersion.setSummary(mRestApi.getVersion()); + mOptions = mRestApi.getOptions(); + mGui = mRestApi.getGui(); Joiner joiner = Joiner.on(", "); - mDeviceName.setText(mApi.getLocalDevice().name); + mDeviceName.setText(mRestApi.getLocalDevice().name); mListenAddresses.setText(joiner.join(mOptions.listenAddresses)); mMaxRecvKbps.setText(Integer.toString(mOptions.maxRecvKbps)); mMaxSendKbps.setText(Integer.toString(mOptions.maxSendKbps)); @@ -337,7 +337,7 @@ public class SettingsActivity extends SyncthingActivity { mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers)); mAddress.setText(mGui.address); mRestartOnWakeup.setChecked(mOptions.restartOnWakeup); - mApi.getSystemStatus(systemStatus -> + mRestApi.getSystemStatus(systemStatus -> mUrAccepted.setChecked(mOptions.isUsageReportingAccepted(systemStatus.urVersionMax))); } @@ -384,9 +384,9 @@ public class SettingsActivity extends SyncthingActivity { Splitter splitter = Splitter.on(",").trimResults().omitEmptyStrings(); switch (preference.getKey()) { case "deviceName": - Device localDevice = mApi.getLocalDevice(); + Device localDevice = mRestApi.getLocalDevice(); localDevice.name = (String) o; - mApi.editDevice(localDevice); + mRestApi.editDevice(localDevice); break; case "listenAddresses": mOptions.listenAddresses = Iterables.toArray(splitter.split((String) o), String.class); @@ -435,7 +435,7 @@ public class SettingsActivity extends SyncthingActivity { mOptions.restartOnWakeup = (boolean) o; break; case "urAccepted": - mApi.getSystemStatus(systemStatus -> { + mRestApi.getSystemStatus(systemStatus -> { mOptions.urAccepted = ((boolean) o) ? systemStatus.urVersionMax : Options.USAGE_REPORTING_DENIED; @@ -444,7 +444,7 @@ public class SettingsActivity extends SyncthingActivity { default: throw new InvalidParameterException(); } - mApi.editSettings(mGui, mOptions); + mRestApi.editSettings(mGui, mOptions); mPendingConfig = true; return true; } @@ -454,9 +454,9 @@ public class SettingsActivity extends SyncthingActivity { if (mSyncthingService != null) { mNotificationHandler.updatePersistentNotification(mSyncthingService); if (mPendingConfig) { - if (mApi != null && + if (mRestApi != null && mSyncthingService.getCurrentState() != SyncthingService.State.DISABLED) { - mApi.saveConfigAndRestart(); + mRestApi.saveConfigAndRestart(); mPendingConfig = false; } } @@ -556,13 +556,13 @@ public class SettingsActivity extends SyncthingActivity { new AlertDialog.Builder(getActivity()) .setMessage(R.string.undo_ignored_devices_folders_question) .setPositiveButton(android.R.string.yes, (dialog, which) -> { - if (mApi == null) { + if (mRestApi == null) { Toast.makeText(getActivity(), getString(R.string.generic_error) + getString(R.string.syncthing_disabled_title), Toast.LENGTH_SHORT).show(); return; } - mApi.undoIgnoredDevicesAndFolders(); + mRestApi.undoIgnoredDevicesAndFolders(); mPendingConfig = true; Toast.makeText(getActivity(), getString(R.string.undo_ignored_devices_folders_done), diff --git a/app/src/main/java/com/nutomic/syncthingandroid/activities/SyncConditionsActivity.java b/app/src/main/java/com/nutomic/syncthingandroid/activities/SyncConditionsActivity.java new file mode 100644 index 00000000..8a77f1a4 --- /dev/null +++ b/app/src/main/java/com/nutomic/syncthingandroid/activities/SyncConditionsActivity.java @@ -0,0 +1,295 @@ +package com.nutomic.syncthingandroid.activities; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.IBinder; +import android.support.v7.widget.SwitchCompat; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.google.common.collect.Sets; +import com.nutomic.syncthingandroid.R; +import com.nutomic.syncthingandroid.SyncthingApp; +import com.nutomic.syncthingandroid.service.Constants; +import com.nutomic.syncthingandroid.service.SyncthingService; +import com.nutomic.syncthingandroid.service.SyncthingServiceBinder; +import com.nutomic.syncthingandroid.util.Util; + +import java.util.HashSet; +import java.util.Set; + +import javax.inject.Inject; + +import static android.support.v4.view.MarginLayoutParamsCompat.setMarginEnd; +import static android.support.v4.view.MarginLayoutParamsCompat.setMarginStart; +import static android.util.TypedValue.COMPLEX_UNIT_DIP; +import static android.view.Gravity.CENTER_VERTICAL; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +/** + * Activity that allows selecting a directory in the local file system. + */ +public class SyncConditionsActivity extends SyncthingActivity + implements SyncthingService.OnServiceStateChangeListener { + + private static final String TAG = "SyncConditionsActivity"; + + private static final String EXTRA_OBJECT_PREFIX_AND_ID = + "com.nutomic.syncthingandroid.activities.SyncConditionsActivity.OBJECT_PREFIX_AND_ID"; + + private static final String EXTRA_OBJECT_READABLE_NAME = + "com.nutomic.syncthingandroid.activities.SyncConditionsActivity.OBJECT_READABLE_NAME"; + + // UI elements + private SwitchCompat mSyncOnWifi; + private SwitchCompat mSyncOnWhitelistedWifi; + private ViewGroup mWifiSsidContainer; + private SwitchCompat mSyncOnMeteredWifi; + private SwitchCompat mSyncOnMobileData; + + /** + * Shared preferences names for custom per-folder settings. + */ + private String mObjectPrefixAndId; + private String mPrefSyncOnWifi; + private String mPrefSyncOnWhitelistedWifi; + private String mPrefSelectedWhitelistSsid; + private String mPrefSyncOnMeteredWifi; + private String mPrefSyncOnMobileData; + + // UI information and state. + private String mObjectReadableName; + private boolean mUnsavedChanges = false; + + @Inject + SharedPreferences mPreferences; + + public static Intent createIntent(Context context, String objectPrefixAndId, String objectReadableName) { + Intent intent = new Intent(context, SyncConditionsActivity.class); + intent.putExtra(EXTRA_OBJECT_PREFIX_AND_ID, objectPrefixAndId); + intent.putExtra(EXTRA_OBJECT_READABLE_NAME, objectReadableName); + return intent; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ((SyncthingApp) getApplication()).component().inject(this); + + Intent intent = getIntent(); + if (!intent.hasExtra(EXTRA_OBJECT_PREFIX_AND_ID) || + !intent.hasExtra(EXTRA_OBJECT_READABLE_NAME)) { + Log.e(TAG, "onCreate extra missing"); + return; + } + mObjectReadableName = intent.getStringExtra(EXTRA_OBJECT_READABLE_NAME); + + // Display content and get views. + setContentView(R.layout.activity_sync_conditions); + mSyncOnWifi = findViewById(R.id.sync_on_wifi_title); + mSyncOnWhitelistedWifi = findViewById(R.id.sync_on_whitelisted_wifi_title); + mWifiSsidContainer = findViewById(R.id.wifiSsidContainer); + mSyncOnMeteredWifi = findViewById(R.id.sync_on_metered_wifi_title); + mSyncOnMobileData = findViewById(R.id.sync_on_mobile_data_title); + + // Generate shared preferences names. + mObjectPrefixAndId = intent.getStringExtra(EXTRA_OBJECT_PREFIX_AND_ID); + Log.v(TAG, "Prefix is \'" + mObjectPrefixAndId + "\' (" + mObjectReadableName + ")"); + mPrefSyncOnWifi = Constants.DYN_PREF_OBJECT_SYNC_ON_WIFI(mObjectPrefixAndId); + mPrefSyncOnWhitelistedWifi = Constants.DYN_PREF_OBJECT_SYNC_ON_WHITELISTED_WIFI(mObjectPrefixAndId); + mPrefSelectedWhitelistSsid = Constants.DYN_PREF_OBJECT_SELECTED_WHITELIST_SSID(mObjectPrefixAndId); + mPrefSyncOnMeteredWifi = Constants.DYN_PREF_OBJECT_SYNC_ON_METERED_WIFI(mObjectPrefixAndId); + mPrefSyncOnMobileData = Constants.DYN_PREF_OBJECT_SYNC_ON_MOBILE_DATA(mObjectPrefixAndId); + + /** + * Load global run conditions. + */ + Boolean globalRunOnWifiEnabled = mPreferences.getBoolean(Constants.PREF_RUN_ON_WIFI, false); + Boolean globalWhitelistEnabled = !mPreferences.getStringSet(Constants.PREF_WIFI_SSID_WHITELIST, new HashSet<>()) + .isEmpty(); + Set globalWhitelistedSsid = mPreferences.getStringSet(Constants.PREF_WIFI_SSID_WHITELIST, new HashSet<>()); + Boolean globalRunOnMeteredWifiEnabled = mPreferences.getBoolean(Constants.PREF_RUN_ON_METERED_WIFI, false); + Boolean globalRunOnMobileDataEnabled = mPreferences.getBoolean(Constants.PREF_RUN_ON_MOBILE_DATA, false); + + /** + * Load custom folder preferences. If unset, use global setting as default. + */ + mSyncOnWifi.setChecked(globalRunOnWifiEnabled && mPreferences.getBoolean(mPrefSyncOnWifi, globalRunOnWifiEnabled)); + mSyncOnWifi.setEnabled(globalRunOnWifiEnabled); + mSyncOnWifi.setOnCheckedChangeListener(mCheckedListener); + + mSyncOnWhitelistedWifi.setChecked(globalWhitelistEnabled && mPreferences.getBoolean(mPrefSyncOnWhitelistedWifi, globalWhitelistEnabled)); + mSyncOnWhitelistedWifi.setEnabled(globalWhitelistEnabled && mSyncOnWifi.isChecked()); + mSyncOnWhitelistedWifi.setOnCheckedChangeListener(mCheckedListener); + + mSyncOnMeteredWifi.setChecked(globalRunOnMeteredWifiEnabled && mPreferences.getBoolean(mPrefSyncOnMeteredWifi, globalRunOnMeteredWifiEnabled)); + mSyncOnMeteredWifi.setEnabled(globalRunOnMeteredWifiEnabled); + mSyncOnMeteredWifi.setOnCheckedChangeListener(mCheckedListener); + + mSyncOnMobileData.setChecked(globalRunOnMobileDataEnabled && mPreferences.getBoolean(mPrefSyncOnMobileData, globalRunOnMobileDataEnabled)); + mSyncOnMobileData.setEnabled(globalRunOnMobileDataEnabled); + mSyncOnMobileData.setOnCheckedChangeListener(mCheckedListener); + + // Read selected WiFi Ssid whitelist items. + Set selectedWhitelistedSsid = mPreferences.getStringSet(mPrefSelectedWhitelistSsid, new HashSet<>()); + // Removes any network that is no longer part of the global WiFi Ssid whitelist. + selectedWhitelistedSsid.retainAll(globalWhitelistedSsid); + + // Populate WiFi Ssid whitelist. + mWifiSsidContainer.removeAllViews(); + // from JavaDoc: Note that you must not modify the set instance returned by this call. + // therefore required to make a defensive copy of the elements + globalWhitelistedSsid = new HashSet<>(globalWhitelistedSsid); + if (!globalWhitelistEnabled) { + // Add empty WiFi Ssid ListView. + int height = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, 48, getResources().getDisplayMetrics()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WRAP_CONTENT, height); + int dividerInset = getResources().getDimensionPixelOffset(R.dimen.material_divider_inset); + int contentInset = getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_content_inset_material); + setMarginStart(params, dividerInset); + setMarginEnd(params, contentInset); + TextView emptyView = new TextView(mWifiSsidContainer.getContext()); + emptyView.setGravity(CENTER_VERTICAL); + emptyView.setText(R.string.wifi_ssid_whitelist_empty); + mWifiSsidContainer.addView(emptyView, params); + mWifiSsidContainer.setEnabled(false); + } else { + for (String wifiSsid : globalWhitelistedSsid) { + // Strip quotes and add WiFi Ssid to view. + LayoutInflater layoutInflater = getLayoutInflater(); + layoutInflater.inflate(R.layout.item_wifi_ssid_form, mWifiSsidContainer); + SwitchCompat wifiSsidView = (SwitchCompat) mWifiSsidContainer.getChildAt(mWifiSsidContainer.getChildCount()-1); + wifiSsidView.setOnCheckedChangeListener(null); + wifiSsidView.setChecked(selectedWhitelistedSsid.contains(wifiSsid)); + wifiSsidView.setEnabled(mSyncOnWhitelistedWifi.isChecked()); + wifiSsidView.setText(wifiSsid.replaceFirst("^\"", "").replaceFirst("\"$", "")); + wifiSsidView.setTag(wifiSsid); + wifiSsidView.setOnCheckedChangeListener(mCheckedListener); + } + } + } + + private final CompoundButton.OnCheckedChangeListener mCheckedListener = + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton view, boolean isChecked) { + switch (view.getId()) { + case R.id.sync_on_wifi_title: + mSyncOnWhitelistedWifi.setEnabled(isChecked); + // Fall-through to dependent options. + case R.id.sync_on_whitelisted_wifi_title: + // Enable or disable WiFi Ssid switches according to parent switch. + for (int i = 0; i < mWifiSsidContainer.getChildCount(); i++) { + mWifiSsidContainer.getChildAt(i).setEnabled(isChecked); + } + break; + default: + break; + } + mUnsavedChanges = true; + } + }; + + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + super.onServiceConnected(componentName, iBinder); + SyncthingServiceBinder syncthingServiceBinder = (SyncthingServiceBinder) iBinder; + syncthingServiceBinder.getService().registerOnServiceStateChangeListener(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + SyncthingService syncthingService = getService(); + if (syncthingService != null) { + syncthingService.unregisterOnServiceStateChangeListener(this::onServiceStateChange); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mUnsavedChanges) { + Log.v(TAG, "onPause: mUnsavedChanges == true. Saving prefs ..."); + /** + * Save custom folder preferences. + */ + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(mPrefSyncOnWifi, mSyncOnWifi.isChecked()); + editor.putBoolean(mPrefSyncOnWhitelistedWifi, mSyncOnWhitelistedWifi.isChecked()); + editor.putBoolean(mPrefSyncOnMeteredWifi, mSyncOnMeteredWifi.isChecked()); + editor.putBoolean(mPrefSyncOnMobileData, mSyncOnMobileData.isChecked()); + + // Save Selected WiFi Ssid's to mPrefSelectedWhitelistSsid. + Set selectedWhitelistedSsid = new HashSet<>(); + if (mSyncOnWhitelistedWifi.isChecked()) { + for (int i = 0; i < mWifiSsidContainer.getChildCount(); i++) { + View view = mWifiSsidContainer.getChildAt(i); + if (view instanceof SwitchCompat) { + SwitchCompat wifiSsidSwitch = (SwitchCompat) view; + if (wifiSsidSwitch.isChecked()) { + selectedWhitelistedSsid.add((String) wifiSsidSwitch.getTag()); + // Log.v(TAG, "onPause: +Ssid [" + (String) wifiSsidSwitch.getTag() + "]"); + } + } + } + } + editor.putStringSet(mPrefSelectedWhitelistSsid, selectedWhitelistedSsid); + editor.apply(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.sync_conditions_settings, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.findItem(R.id.done).setVisible(true); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + case R.id.done: + onBackPressed(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + /** + * Cancel without saving changes. + */ + @Override + public void onBackPressed() { + setResult(Activity.RESULT_OK); + finish(); + } + + @Override + public void onServiceStateChange(SyncthingService.State currentState) { + if (!isFinishing() && currentState != SyncthingService.State.ACTIVE) { + setResult(Activity.RESULT_CANCELED); + finish(); + } + } + +} diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java index 7bc9847f..10d2a86e 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java @@ -31,6 +31,34 @@ public class Constants { public static final String PREF_SOCKS_PROXY_ADDRESS = "socks_proxy_address"; public static final String PREF_HTTP_PROXY_ADDRESS = "http_proxy_address"; + // Preferences - per Folder and Device Sync Conditions + public static final String PREF_OBJECT_PREFIX_FOLDER = "sc_folder_"; + public static final String PREF_OBJECT_PREFIX_DEVICE = "sc_device_"; + + public static String DYN_PREF_OBJECT_CUSTOM_SYNC_CONDITIONS(String objectPrefixAndId) { + return objectPrefixAndId + "_" + "custom_sync_conditions"; + } + + public static String DYN_PREF_OBJECT_SYNC_ON_WIFI(String objectPrefixAndId) { + return objectPrefixAndId + "_" + PREF_RUN_ON_WIFI; + } + + public static String DYN_PREF_OBJECT_SYNC_ON_WHITELISTED_WIFI(String objectPrefixAndId) { + return objectPrefixAndId + "_" + "use_wifi_whitelist"; + } + + public static String DYN_PREF_OBJECT_SELECTED_WHITELIST_SSID(String objectPrefixAndId) { + return objectPrefixAndId + "_" + PREF_WIFI_SSID_WHITELIST; + } + + public static String DYN_PREF_OBJECT_SYNC_ON_METERED_WIFI(String objectPrefixAndId) { + return objectPrefixAndId + "_" + PREF_RUN_ON_METERED_WIFI; + } + + public static String DYN_PREF_OBJECT_SYNC_ON_MOBILE_DATA(String objectPrefixAndId) { + return objectPrefixAndId + "_" + PREF_RUN_ON_MOBILE_DATA; + } + /** * Cached information which is not available on SettingsActivity. */ diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/EventProcessor.java b/app/src/main/java/com/nutomic/syncthingandroid/service/EventProcessor.java index b6cde870..aebf5d14 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/EventProcessor.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/EventProcessor.java @@ -53,14 +53,14 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener private volatile boolean mShutdown = true; private final Context mContext; - private final RestApi mApi; + private final RestApi mRestApi; @Inject SharedPreferences mPreferences; @Inject NotificationHandler mNotificationHandler; - public EventProcessor(Context context, RestApi api) { + public EventProcessor(Context context, RestApi restApi) { ((SyncthingApp) context.getApplicationContext()).component().inject(this); mContext = context; - mApi = api; + mRestApi = restApi; } @Override @@ -72,7 +72,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener // First check if the event number ran backwards. // If that's the case we've to start at zero because syncthing was restarted. - mApi.getEvents(0, 1, new RestApi.OnReceiveEventListener() { + mRestApi.getEvents(0, 1, new RestApi.OnReceiveEventListener() { @Override public void onEvent(Event event) { } @@ -83,7 +83,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener Log.d(TAG, "Reading events starting with id " + mLastEventId); - mApi.getEvents(mLastEventId, 0, EventProcessor.this); + mRestApi.getEvents(mLastEventId, 0, EventProcessor.this); } }); } @@ -95,9 +95,9 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener public void onEvent(Event event) { switch (event.type) { case "ConfigSaved": - if (mApi != null) { + if (mRestApi != null) { Log.v(TAG, "Forwarding ConfigSaved event to RestApi to get the updated config."); - mApi.reloadConfig(); + mRestApi.reloadConfig(); } break; case "DeviceRejected": @@ -109,7 +109,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener case "FolderCompletion": CompletionInfo completionInfo = new CompletionInfo(); completionInfo.completion = (Double) event.data.get("completion"); - mApi.setCompletionInfo( + mRestApi.setCompletionInfo( (String) event.data.get("device"), // deviceId (String) event.data.get("folder"), // folderId completionInfo @@ -125,7 +125,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener case "ItemFinished": String folder = (String) event.data.get("folder"); String folderPath = null; - for (Folder f : mApi.getFolders()) { + for (Folder f : mRestApi.getFolders()) { if (f.id.equals(folder)) { folderPath = f.path; } @@ -249,7 +249,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener // Find the deviceName corresponding to the deviceId String deviceName = null; - for (Device d : mApi.getDevices(false)) { + for (Device d : mRestApi.getDevices(false)) { if (d.deviceID.equals(deviceId)) { deviceName = d.getDisplayName(); break; @@ -260,7 +260,7 @@ public class EventProcessor implements Runnable, RestApi.OnReceiveEventListener int notificationId = mNotificationHandler.getNotificationIdFromText(title); // Prepare "accept" action. - boolean isNewFolder = Stream.of(mApi.getFolders()) + boolean isNewFolder = Stream.of(mRestApi.getFolders()) .noneMatch(f -> f.id.equals(folderId)); Intent intentAccept = new Intent(mContext, FolderActivity.class) .putExtra(FolderActivity.EXTRA_NOTIFICATION_ID, notificationId) diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java index 1b2979d0..afab4c44 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/RestApi.java @@ -3,6 +3,7 @@ package com.nutomic.syncthingandroid.service; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; @@ -773,4 +774,38 @@ public class RestApi { mConfig.options = options; } } + + /** + * Event triggered by {@link RunConditionMonitor} routed here through {@link SyncthingService}. + */ + public void onSyncPreconditionChanged(RunConditionMonitor runConditionMonitor) { + Log.v(TAG, "onSyncPreconditionChanged: Event fired."); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext); + synchronized (mConfigLock) { + if (mConfig == null || mConfig.folders == null) { + Log.d(TAG, "onSyncPreconditionChanged: mConfig.folders is not ready yet."); + return; + } + Boolean configChanged = false; + for (Folder folder : mConfig.folders) { + Boolean folderCustomSyncConditionsEnabled = sharedPreferences.getBoolean( + Constants.DYN_PREF_OBJECT_CUSTOM_SYNC_CONDITIONS(Constants.PREF_OBJECT_PREFIX_FOLDER + folder.id), false + ); + if (folderCustomSyncConditionsEnabled) { + Boolean syncConditionsMet = runConditionMonitor.checkObjectSyncConditions( + Constants.PREF_OBJECT_PREFIX_FOLDER + folder.id + ); + Log.v(TAG, "onSyncPreconditionChanged: syncFolder(" + folder.id + ")=" + (syncConditionsMet ? "1" : "0")); + if (folder.paused != !syncConditionsMet) { + folder.paused = !syncConditionsMet; + configChanged = true; + } + } + } + if (configChanged) { + Log.v(TAG, "onSyncPreconditionChanged: Sending changed config ..."); + sendConfig(); + } + } + } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/RunConditionMonitor.java b/app/src/main/java/com/nutomic/syncthingandroid/service/RunConditionMonitor.java index 4309508d..5677e5cf 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/RunConditionMonitor.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/RunConditionMonitor.java @@ -53,30 +53,60 @@ public class RunConditionMonitor { } }; - public interface OnRunConditionChangedListener { - void onRunConditionChanged(boolean shouldRun); + public interface OnShouldRunChangedListener { + void onShouldRunDecisionChanged(boolean shouldRun); + } + + public interface OnSyncPreconditionChangedListener { + void onSyncPreconditionChanged(); + } + + private class SyncConditionResult { + public Boolean conditionMet = false; + public String explanation = ""; + + SyncConditionResult(Boolean conditionMet) { + this.conditionMet = conditionMet; + } + + SyncConditionResult(Boolean conditionMet, String explanation) { + this.conditionMet = conditionMet; + this.explanation = explanation; + } } private final Context mContext; - @Inject SharedPreferences mPreferences; private ReceiverManager mReceiverManager; + private Resources res; private String mRunDecisionExplanation = ""; + @Inject + SharedPreferences mPreferences; + /** - * Sending callback notifications through {@link OnDeviceStateChangedListener} is enabled if not null. + * Sending callback notifications through {@link #OnShouldRunChangedListener} is enabled if not null. */ - private @Nullable OnRunConditionChangedListener mOnRunConditionChangedListener = null; + private @Nullable OnShouldRunChangedListener mOnShouldRunChangedListener = null; + + /** + * Sending callback notifications through {@link #OnSyncPreconditionChangedListener} is enabled if not null. + */ + private @Nullable OnSyncPreconditionChangedListener mOnSyncPreconditionChangedListener = null; /** * Stores the result of the last call to {@link decideShouldRun}. */ private boolean lastDeterminedShouldRun = false; - public RunConditionMonitor(Context context, OnRunConditionChangedListener listener) { + public RunConditionMonitor(Context context, + OnShouldRunChangedListener onShouldRunChangedListener, + OnSyncPreconditionChangedListener onSyncPreconditionChangedListener) { Log.v(TAG, "Created new instance"); ((SyncthingApp) context.getApplicationContext()).component().inject(this); mContext = context; - mOnRunConditionChangedListener = listener; + res = mContext.getResources(); + mOnShouldRunChangedListener = onShouldRunChangedListener; + mOnSyncPreconditionChangedListener = onSyncPreconditionChangedListener; /** * Register broadcast receivers. @@ -142,40 +172,122 @@ public class RunConditionMonitor { } } + /** + * Event handler that is fired after preconditions changed. + * We then need to decide if syncthing should run. + */ public void updateShouldRunDecision() { // Check if the current conditions changed the result of decideShouldRun() // compared to the last determined result. boolean newShouldRun = decideShouldRun(); if (newShouldRun != lastDeterminedShouldRun) { - if (mOnRunConditionChangedListener != null) { - mOnRunConditionChangedListener.onRunConditionChanged(newShouldRun); + if (mOnShouldRunChangedListener != null) { + mOnShouldRunChangedListener.onShouldRunDecisionChanged(newShouldRun); } lastDeterminedShouldRun = newShouldRun; } + + // Notify about changed preconditions. + if (mOnSyncPreconditionChangedListener != null) { + mOnSyncPreconditionChangedListener.onSyncPreconditionChanged(); + } } public String getRunDecisionExplanation() { return mRunDecisionExplanation; } + /** + * Each sync condition has its own evaluator function which + * determines if the condition is met. + */ + /** + * Constants.PREF_RUN_ON_WIFI + */ + private SyncConditionResult checkConditionSyncOnWifi(String prefNameSyncOnWifi) { + boolean prefSyncOnWifi = mPreferences.getBoolean(prefNameSyncOnWifi, true); + if (!prefSyncOnWifi) { + return new SyncConditionResult(false, "\n" + res.getString(R.string.reason_wifi_disallowed)); + } + + if (isWifiOrEthernetConnection()) { + return new SyncConditionResult(true, "\n" + res.getString(R.string.reason_on_wifi)); + } + + /** + * if (prefRunOnWifi && !isWifiOrEthernetConnection()) { return false; } + * This is intentionally not returning "false" as the flight mode workaround + * relevant for some phone models needs to be done by the code below. + * ConnectivityManager.getActiveNetworkInfo() returns "null" on those phones which + * results in assuming !isWifiOrEthernetConnection even if the phone is connected + * to wifi during flight mode, see {@link isWifiOrEthernetConnection}. + */ + return new SyncConditionResult(false, "\n" + res.getString(R.string.reason_not_on_wifi)); + } + + /** + * Constants.PREF_WIFI_SSID_WHITELIST + */ + private SyncConditionResult checkConditionSyncOnWhitelistedWifi(String prefNameSyncOnWhitelistedWifi) { + Set whitelistedWifiSsids = mPreferences.getStringSet(prefNameSyncOnWhitelistedWifi, new HashSet<>()); + boolean prefWifiWhitelistEnabled = !whitelistedWifiSsids.isEmpty(); + try { + if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) { + return new SyncConditionResult(true, "\n" + res.getString(R.string.reason_on_whitelisted_wifi)); + } + return new SyncConditionResult(false, "\n" + res.getString(R.string.reason_not_on_whitelisted_wifi)); + } catch (LocationUnavailableException e) { + return new SyncConditionResult(false, "\n" + res.getString(R.string.reason_location_unavailable)); + } + } + + /** + * Constants.PREF_RUN_ON_METERED_WIFI + */ + private SyncConditionResult checkConditionSyncOnMeteredWifi(String prefNameSyncOnMeteredWifi) { + boolean prefSyncOnMeteredWifi = mPreferences.getBoolean(prefNameSyncOnMeteredWifi, false); + if (prefSyncOnMeteredWifi) { + // Condition is always met as we allow both types of wifi - metered and non-metered. + return new SyncConditionResult(true, "\n" + res.getString(R.string.reason_on_metered_nonmetered_wifi)); + } + + // Check if we are on a non-metered wifi. + if (!isMeteredNetworkConnection()) { + return new SyncConditionResult(true, "\n" + res.getString(R.string.reason_on_nonmetered_wifi)); + } + + // We disallowed non-metered wifi and are connected to metered wifi. + return new SyncConditionResult(false, "\n" + res.getString(R.string.reason_not_nonmetered_wifi)); + } + + /** + * Constants.PREF_RUN_ON_MOBILE_DATA + */ + private SyncConditionResult checkConditionSyncOnMobileData(String prefNameSyncOnMobileData) { + boolean prefSyncOnMobileData = mPreferences.getBoolean(prefNameSyncOnMobileData, false); + if (!prefSyncOnMobileData) { + return new SyncConditionResult(false, res.getString(R.string.reason_mobile_data_disallowed)); + } + + if (isMobileDataConnection()) { + return new SyncConditionResult(true, res.getString(R.string.reason_on_mobile_data)); + } + + return new SyncConditionResult(false, res.getString(R.string.reason_not_on_mobile_data)); + } + /** * Determines if Syncthing should currently run. * Updates mRunDecisionExplanation. */ private boolean decideShouldRun() { - Resources res = mContext.getResources(); mRunDecisionExplanation = ""; - // Get run conditions preferences. - boolean prefRunOnMobileData= mPreferences.getBoolean(Constants.PREF_RUN_ON_MOBILE_DATA, false); - boolean prefRunOnWifi= mPreferences.getBoolean(Constants.PREF_RUN_ON_WIFI, true); - boolean prefRunOnMeteredWifi= mPreferences.getBoolean(Constants.PREF_RUN_ON_METERED_WIFI, false); - Set whitelistedWifiSsids = mPreferences.getStringSet(Constants.PREF_WIFI_SSID_WHITELIST, new HashSet<>()); - boolean prefWifiWhitelistEnabled = !whitelistedWifiSsids.isEmpty(); - boolean prefRunInFlightMode = mPreferences.getBoolean(Constants.PREF_RUN_IN_FLIGHT_MODE, false); + // Get sync condition preferences. String prefPowerSource = mPreferences.getString(Constants.PREF_POWER_SOURCE, POWER_SOURCE_CHARGER_BATTERY); boolean prefRespectPowerSaving = mPreferences.getBoolean(Constants.PREF_RESPECT_BATTERY_SAVING, true); boolean prefRespectMasterSync = mPreferences.getBoolean(Constants.PREF_RESPECT_MASTER_SYNC, false); + boolean prefRunInFlightMode = mPreferences.getBoolean(Constants.PREF_RUN_IN_FLIGHT_MODE, false); // PREF_POWER_SOURCE switch (prefPowerSource) { @@ -214,58 +326,35 @@ public class RunConditionMonitor { return false; } - // Run on mobile data. - if (prefRunOnMobileData) { - if (isMobileDataConnection()) { - Log.v(TAG, "decideShouldRun: prefRunOnMobileData && isMobileDataConnection"); - mRunDecisionExplanation = res.getString(R.string.reason_on_mobile_data); - return true; - } - mRunDecisionExplanation = res.getString(R.string.reason_not_on_mobile_data); + // Run on mobile data? + SyncConditionResult scr = checkConditionSyncOnMobileData(Constants.PREF_RUN_ON_MOBILE_DATA); + mRunDecisionExplanation += scr.explanation; + if (scr.conditionMet) { + // Mobile data is connected. + Log.v(TAG, "decideShouldRun: checkConditionSyncOnMobileData"); + return true; } - // Run on wifi. - if (prefRunOnWifi) { - if (isWifiOrEthernetConnection()) { - try { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_on_wifi); - if (prefRunOnMeteredWifi) { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_on_metered_nonmetered_wifi); - // We are on non-metered or metered wifi. Check if wifi whitelist run condition is met. - if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) { - Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && prefRunOnMeteredWifi && wifiWhitelistConditionMet"); - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_on_whitelisted_wifi); - return true; - } - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_not_on_whitelisted_wifi); - } else { - // Check if we are on a non-metered wifi. - if (!isMeteredNetworkConnection()) { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_on_nonmetered_wifi); - // Check if wifi whitelist run condition is met. - if (wifiWhitelistConditionMet(prefWifiWhitelistEnabled, whitelistedWifiSsids)) { - Log.v(TAG, "decideShouldRun: prefRunOnWifi && isWifiOrEthernetConnection && !prefRunOnMeteredWifi && !isMeteredNetworkConnection && wifiWhitelistConditionMet"); - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_on_whitelisted_wifi); - return true; - } - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_not_on_whitelisted_wifi); - } else { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_not_nonmetered_wifi); - } - } - } catch (LocationUnavailableException e) { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_location_unavailable); + // Run on WiFi? + scr = checkConditionSyncOnWifi(Constants.PREF_RUN_ON_WIFI); + mRunDecisionExplanation += scr.explanation; + if (scr.conditionMet) { + // Wifi is connected. + Log.v(TAG, "decideShouldRun: checkConditionSyncOnWifi"); + + scr = checkConditionSyncOnMeteredWifi(Constants.PREF_RUN_ON_METERED_WIFI); + mRunDecisionExplanation += scr.explanation; + if (scr.conditionMet) { + // Wifi type is allowed. + Log.v(TAG, "decideShouldRun: checkConditionSyncOnWifi && checkConditionSyncOnMeteredWifi"); + + scr = checkConditionSyncOnWhitelistedWifi(Constants.PREF_WIFI_SSID_WHITELIST); + mRunDecisionExplanation += scr.explanation; + if (scr.conditionMet) { + // Wifi is whitelisted. + Log.v(TAG, "decideShouldRun: checkConditionSyncOnWifi && checkConditionSyncOnMeteredWifi && checkConditionSyncOnWhitelistedWifi"); + return true; } - } else { - mRunDecisionExplanation += "\n" + res.getString(R.string.reason_not_on_wifi); - /** - * if (prefRunOnWifi && !isWifiOrEthernetConnection()) { return false; } - * This is intentionally not returning "false" as the flight mode workaround - * relevant for some phone models needs to be done by the code below. - * ConnectivityManager.getActiveNetworkInfo() returns "null" on those phones which - * results in assuming !isWifiOrEthernetConnection even if the phone is connected - * to wifi during flight mode, see {@link isWifiOrEthernetConnection}. - */ } } @@ -283,6 +372,40 @@ public class RunConditionMonitor { return false; } + /** + * Check if an object's individual sync conditions are met. + */ + public Boolean checkObjectSyncConditions(String objectPrefixAndId) { + // Sync on mobile data? + SyncConditionResult scr = checkConditionSyncOnMobileData(Constants.DYN_PREF_OBJECT_SYNC_ON_MOBILE_DATA(objectPrefixAndId)); + if (scr.conditionMet) { + // Mobile data is connected. + Log.v(TAG, "checkObjectSyncConditions: checkConditionSyncOnMobileData"); + return true; + } + + // Sync on WiFi? + scr = checkConditionSyncOnWifi(Constants.DYN_PREF_OBJECT_SYNC_ON_WIFI(objectPrefixAndId)); + if (scr.conditionMet) { + // Wifi is connected. + Log.v(TAG, "checkObjectSyncConditions: checkConditionSyncOnWifi"); + + scr = checkConditionSyncOnMeteredWifi(Constants.DYN_PREF_OBJECT_SYNC_ON_METERED_WIFI(objectPrefixAndId)); + if (scr.conditionMet) { + // Wifi type is allowed. + Log.v(TAG, "checkObjectSyncConditions: checkConditionSyncOnWifi && checkConditionSyncOnMeteredWifi"); + + scr = checkConditionSyncOnWhitelistedWifi(Constants.DYN_PREF_OBJECT_SELECTED_WHITELIST_SSID(objectPrefixAndId)); + if (scr.conditionMet) { + // Wifi is whitelisted. + Log.v(TAG, "checkObjectSyncConditions: checkConditionSyncOnWifi && checkConditionSyncOnMeteredWifi && checkConditionSyncOnWhitelistedWifi"); + return true; + } + } + } + return false; + } + /** * Return whether the wifi whitelist run condition is met. * Precondition: An active wifi connection has been detected. diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java b/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java index 778dab0f..225874c5 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/SyncthingService.java @@ -166,7 +166,7 @@ public class SyncthingService extends Service { PollWebGuiAvailableTask mPollWebGuiAvailableTask = null; private @Nullable - RestApi mApi = null; + RestApi mRestApi = null; private @Nullable EventProcessor mEventProcessor = null; @@ -189,7 +189,7 @@ public class SyncthingService extends Service { private final Object mStateLock = new Object(); /** - * Stores the result of the last should run decision received by OnDeviceStateChangedListener. + * Stores the result of the last should run decision received by OnShouldRunChangedListener. */ private boolean mLastDeterminedShouldRun = false; @@ -261,9 +261,12 @@ public class SyncthingService extends Service { * Instantiate the run condition monitor on first onStartCommand and * enable callback on run condition change affecting the final decision to * run/terminate syncthing. After initial run conditions are collected - * the first decision is sent to {@link onUpdatedShouldRunDecision}. + * the first decision is sent to {@link onShouldRunDecisionChanged}. */ - mRunConditionMonitor = new RunConditionMonitor(SyncthingService.this, this::onUpdatedShouldRunDecision); + mRunConditionMonitor = new RunConditionMonitor(SyncthingService.this, + this::onShouldRunDecisionChanged, + this::onSyncPreconditionChanged + ); } mNotificationHandler.updatePersistentNotification(this); @@ -290,15 +293,15 @@ public class SyncthingService extends Service { } else if (ACTION_REFRESH_NETWORK_INFO.equals(intent.getAction())) { mRunConditionMonitor.updateShouldRunDecision(); } else if (ACTION_IGNORE_DEVICE.equals(intent.getAction()) && mCurrentState == State.ACTIVE) { - // mApi is not null due to State.ACTIVE - mApi.ignoreDevice(intent.getStringExtra(EXTRA_DEVICE_ID)); + // mRestApi is not null due to State.ACTIVE + mRestApi.ignoreDevice(intent.getStringExtra(EXTRA_DEVICE_ID)); mNotificationHandler.cancelConsentNotification(intent.getIntExtra(EXTRA_NOTIFICATION_ID, 0)); } else if (ACTION_IGNORE_FOLDER.equals(intent.getAction()) && mCurrentState == State.ACTIVE) { - // mApi is not null due to State.ACTIVE - mApi.ignoreFolder(intent.getStringExtra(EXTRA_DEVICE_ID), intent.getStringExtra(EXTRA_FOLDER_ID)); + // mRestApi is not null due to State.ACTIVE + mRestApi.ignoreFolder(intent.getStringExtra(EXTRA_DEVICE_ID), intent.getStringExtra(EXTRA_FOLDER_ID)); mNotificationHandler.cancelConsentNotification(intent.getIntExtra(EXTRA_NOTIFICATION_ID, 0)); } else if (ACTION_OVERRIDE_CHANGES.equals(intent.getAction()) && mCurrentState == State.ACTIVE) { - mApi.overrideChanges(intent.getStringExtra(EXTRA_FOLDER_ID)); + mRestApi.overrideChanges(intent.getStringExtra(EXTRA_FOLDER_ID)); } return START_STICKY; } @@ -309,7 +312,7 @@ public class SyncthingService extends Service { * function is called to notify this class to run/terminate the syncthing binary. * {@link #onServiceStateChange} is called while applying the decision change. */ - private void onUpdatedShouldRunDecision(boolean newShouldRunDecision) { + private void onShouldRunDecisionChanged(boolean newShouldRunDecision) { if (newShouldRunDecision != mLastDeterminedShouldRun) { Log.i(TAG, "shouldRun decision changed to " + newShouldRunDecision + " according to configured run conditions."); mLastDeterminedShouldRun = newShouldRunDecision; @@ -341,6 +344,17 @@ public class SyncthingService extends Service { } } + /** + * After sync preconditions changed, we need to inform {@link RestApi} to pause or + * unpause devices and folders as defined in per-object sync preferences. + */ + private void onSyncPreconditionChanged() { + if (mRestApi != null) { + // Forward event. + mRestApi.onSyncPreconditionChanged(mRunConditionMonitor); + } + } + /** * Prepares to launch the syncthing binary. */ @@ -416,8 +430,8 @@ public class SyncthingService extends Service { * Callback on {@link StartupTask#onPostExecute}. */ private void onStartupTaskCompleteListener(SyncthingRunnable.Command srCommand) { - if (mApi == null) { - mApi = new RestApi(this, mConfig.getWebGuiUrl(), mConfig.getApiKey(), + if (mRestApi == null) { + mRestApi = new RestApi(this, mConfig.getWebGuiUrl(), mConfig.getApiKey(), this::onApiAvailable, () -> onServiceStateChange(mCurrentState)); Log.i(TAG, "Web GUI will be available at " + mConfig.getWebGuiUrl()); } @@ -450,8 +464,8 @@ public class SyncthingService extends Service { mPollWebGuiAvailableTask = new PollWebGuiAvailableTask( this, getWebGuiUrl(), mConfig.getApiKey(), result -> { Log.i(TAG, "Web GUI has come online at " + mConfig.getWebGuiUrl()); - if (mApi != null) { - mApi.readConfigFromRestApi(); + if (mRestApi != null) { + mRestApi.readConfigFromRestApi(); } } ); @@ -461,12 +475,12 @@ public class SyncthingService extends Service { /** * Called when {@link RestApi#checkReadConfigFromRestApiCompleted} detects * the RestApi class has been fully initialized. - * UI stressing results in mApi getting null on simultaneous shutdown, so + * UI stressing results in mRestApi getting null on simultaneous shutdown, so * we check it for safety. */ private void onApiAvailable() { - if (mApi == null) { - Log.e(TAG, "onApiAvailable: Did we stop the binary during startup? mApi == null"); + if (mRestApi == null) { + Log.e(TAG, "onApiAvailable: Did we stop the binary during startup? mRestApi == null"); return; } synchronized (mStateLock) { @@ -476,6 +490,9 @@ public class SyncthingService extends Service { } onServiceStateChange(State.ACTIVE); } + if (mRestApi != null && mRunConditionMonitor != null) { + mRestApi.onSyncPreconditionChanged(mRunConditionMonitor); + } /** * If the service instance got an onDestroy() event while being in @@ -489,7 +506,7 @@ public class SyncthingService extends Service { } if (mEventProcessor == null) { - mEventProcessor = new EventProcessor(SyncthingService.this, mApi); + mEventProcessor = new EventProcessor(SyncthingService.this, mRestApi); mEventProcessor.start(); } } @@ -508,7 +525,7 @@ public class SyncthingService extends Service { Log.v(TAG, "onDestroy"); if (mRunConditionMonitor != null) { /** - * Shut down the OnDeviceStateChangedListener so we won't get interrupted by run + * Shut down the OnShouldRunChangedListener so we won't get interrupted by run * condition events that occur during shutdown. */ mRunConditionMonitor.shutdown(); @@ -565,9 +582,9 @@ public class SyncthingService extends Service { mEventProcessor = null; } - if (mApi != null) { - mApi.shutdown(); - mApi = null; + if (mRestApi != null) { + mRestApi.shutdown(); + mRestApi = null; } if (mSyncthingRunnable != null) { @@ -589,7 +606,7 @@ public class SyncthingService extends Service { public @Nullable RestApi getApi() { - return mApi; + return mRestApi; } /** diff --git a/app/src/main/java/com/nutomic/syncthingandroid/views/WifiSsidPreference.java b/app/src/main/java/com/nutomic/syncthingandroid/views/WifiSsidPreference.java index 92e3c389..aa2d66a4 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/views/WifiSsidPreference.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/views/WifiSsidPreference.java @@ -115,10 +115,11 @@ public class WifiSsidPreference extends MultiSelectListPreference { // See #620: there may be null-SSIDs String ssid = configs[i].SSID != null ? configs[i].SSID : ""; // WiFi SSIDs can either be UTF-8 (encapsulated in '"') or hex-strings - if (stripQuotes) + if (stripQuotes) { result[i] = ssid.replaceFirst("^\"", "").replaceFirst("\"$", ""); - else + } else { result[i] = ssid; + } } return result; } diff --git a/app/src/main/play/en-GB/whatsnew b/app/src/main/play/en-GB/whatsnew index 4fefa414..24661d4a 100644 --- a/app/src/main/play/en-GB/whatsnew +++ b/app/src/main/play/en-GB/whatsnew @@ -1,14 +1,13 @@ -Fixes -* Fixed xml encoding when parsing, saving the config (#89) -* Fixed override changes button not showing -* Fixed the "battery eater" -* Added detection for wireless charging -* Fixed phone plugged to charger detection -* Lots of bug fixes and better Android 8+ support (#52, #54, #56, #59) Enhancements +* Specify sync conditions differently for each folder [NEW] * UI explains why syncthing is running (or not) * Support in-app editing of folder's ignore list items -* Better default prefs and crash detection +Fixes +* Fixed the "battery eater" +* Fixed xml encoding when parsing, saving the config (#89) +* Fixed override changes button not showing +* Fixed phone plugged to charger detection +* Lots of bug fixes and better Android 8+ support (#52, #54, #56, #59) Maintenance * Updated syncthing to v0.14.51 * Added support for "receive only" folders diff --git a/app/src/main/res/drawable-hdpi/ic_pause_circle_outline_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_pause_circle_outline_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..cf98cc88b0757a847005365e6efb4553ac930dc5 GIT binary patch literal 454 zcmV;%0XhDOP) zwN(T_6aWWzxgkBJ96K&i5o^&S(Fv8~>A7hFD>j zSDx5qg+XF*5PvGz=H0?$n@arAB$IRAZ9LA&M1zK(KU^_E3Xud8LIi0{aQ%~Jzz!oS zaF0@aFvXV=4phVlHfUBsbNFKof2LJbGgin`0lnCxPetZgF6mMd7xBOz9?VPZ1p$~* zFG+_4p+g{t5?_xQCz6oGF9tCNv+n{~Vooq2TJ#Q{+8KGWEiM`(T1EDNc1F-6t`#Ge zL?$|vQG&Q7j93>L?odYI;?^+YNo1%)8HI{_#E1ux!472b>GqMES5kj>5CkJ6vbf7p@ZXp%G{332#1Qe<*!^ME`h w6HWZ7WXobETU6qQgT(w?BA(SHB8LCS2Tv_S@u4h3xc~qF07*qoM6N<$g5P7jcmMzZ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..fe734894d53f9d8e428bab4ee909f810a7edb32d GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|n3?%2|6>tM7&H$efS0D`m&B-qh09i~WL4Lsu z4YRfVB!D~@PZ!6K3dW=Z%nZF}778*L2rwNy7{H=hml+~i`eMPgf>}1HRtuE;XY&2M v?!}vGwFJamc_KI}%foeEkX(C6%9q{j2~Q0E{&&#;S;^q(>gTe~DWM4fQh_ZQ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_signal_wifi_0_bar_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_signal_wifi_0_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..585e1db0d783018532af5c3920c38f92d2c9415b GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8LpIZqeIkP61P7o3w=14Udfir(H9 zwJ~>b*1yM|+It?ZeRqHP{|#5XuBBXQDs4Y^r{c?tV>_K+i}hrDYM1i46|7NzW3sKV zR892sQ2tZ)?+&igTj=J^^>qLC)wg%M-PM?^t&`m#cKcMU~z}Y^!Hs-Tq&-icW02sZ*3=+|A?ig~iC_i^!&qd9HmgGM{wJ za}m3^`GnwKy>^+`;uq&D74g-&Z91z1k_SmBRf$ii;uxx1$s8MFd@#^CAd K=d#Wzp$P!rRCUGx literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_wifi_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_wifi_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b646ff25a216aeb8f13725f6f1e4fb8871fed6e6 GIT binary patch literal 387 zcmV-}0et?6P)NklcgWVsopsi`Pg8h)(`)>9 z{P&mXWtgdEYEoyWsfH=rbjuv~LP&bygyp6wPA^^V3Prl3OE38}x+#>{O^tqQjKe~i z9WX{>mIp%2d)I8xZnnt=7-+It+O2oZ2O*~0Y>`D?#)EpSFiM_LR_OU<00n^hxZ5LZ z3{uQst2~KUX#mK+@3>*SQjK@x`&FAjyp>}HiWs584tt$*%0An47=~z|V}eX#v8b1V zi{1-K?_E?#ugcftz97H*nkcT*TcJpAbtA0@f+-+1#f3Pj;tG1p(_29W`dFY%n+5u)LaT0ZdA6xgZL-oos8gX#5X+$YTV+uF htum^Y$^7?M`UEtS0iB*SewP3M002ovPDHLkV1lXdwq*bS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_wifi_tethering_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_wifi_tethering_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..38833147eeb62823c37ee3b628598b0c88ad54a2 GIT binary patch literal 667 zcmV;M0%ZM(P)Ks>j$o;Nzj;0QSDz5Oaopu)=JN)NzRU9&FFmy{WA#|}ri?rULd7ANzm={$b^`|O`DNfT4RZ}nF z#57+SYr<><=7eqw#w(UDbP7EK)DOKz#7L_q!V5Vt_l5}jA*%WpjMir_mT5KT8&k}?-AWAqp@9K_XIbG&d~JMXI5omc{M{T$-u}slX?Z z+N39-u7cd@Zd25LtRf99i}Z2>P|gs`)62Gj5_+XWZS|xwuCpag_b|%oW@VJUsf^#! zf;ry-=wqf0>MNs_EoK_*AgE%`?C{Dv09A}6007^EVj2Qtpe_Ia002ovPDHLkV1h2J BJm`EpI2$0K>IKGK1nxKBa@4&B_Pe-n z{v7A~{JW-!l}|sueOZ}ksxY<_>1SuG#6k#1OG7uhhCUpH+@kDw=21-nbuTh;nT+Jl z2Cf-6%Z(IhISOyeyb4Dxg{iPt2ZTue)a`_+!bX@=8ZZ|&3R|IH8T5p$!b#{<1|8v~ zkO}R|peD*B%{eZNtdtY zS*93k>Rkv2OZU2NJy<#jx!={{a;qEG4CF>k7X1K(7ob^`&Hw%afjOW|v!Y>&KRlGC$@Q7ZmcR++mh%XLukGA;Z+*oKVPR!8hNT kpFVdQ&MBb@0P7tr%>V!Z literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_signal_wifi_0_bar_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_signal_wifi_0_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0c8ca6d6ead9cf5d3c421f328e94aa7efbbf5a51 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_+i8J;eVAr*{g&o{CiN)Ty#n7;6= z!>)!9tp>w@s~lci@BaVFa;D(VUk6+E2i6sTci)P8{NmZmm(Nyg4CW5mcCPKmoSaa% z*5>JowQ=9LR>bnoEDzm$CEfnZv<)ZgBAB;Ce!iBm?6=kXGd@$~PX3I|^s?HwT_9q4 zvT|XKve@z0B0^r@70faXJL}mup8PS@Cs$^6-+qlJ!83nPk3$r-xWUgN7j_(8 z-uK!I51zHO=fd%dM?nhT?J_ T@dA5}00000NkvXXu0mjf>dbXd literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_wifi_tethering_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_wifi_tethering_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..df3987483d2f55f1d484e5e83316d2cab350a409 GIT binary patch literal 419 zcmV;U0bKrxP)%8YbG}oKN04pK24; zP>wMg@YAv~~2PYqM(m1+-!KQ@*%{i87|K~~9_)EhP`roTVFX@?q?xh;g- zsa6B+ee*|uWVJjL7NNDPLJq0b8ViMoYRRSv_f=NO5#g!fnx-&3)xuGgRCZ68CfhA+ zz#QR?RsdRiEzHFRVYlqM&=JRk*%;|c3L{Caa2y?k>$1;6{lc;h9tq(gsTDq{RHN3{R| N002ovPDHLkV1nq`w}=1$ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_pause_circle_outline_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_pause_circle_outline_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..56ddd99f1138ba7307ac2b7f18365459952deab7 GIT binary patch literal 594 zcmV-Y0j5g#X2tVEut>4mR>lMV+HT|mQe3mK@JBhxXHJab(0D* zkz)(r0`->tOlKH9$&sf!Lz%@s-VyBClKwn8ay&5jka-jcqrf~K20D+^i4?TvFdE?# zt0@vkk=1-e{T!kVNdzv=Q^u2qi9AI!Y$k!ZsFf@9CM|urjOLg}3>|o>wnrJC@7_Gp znqE$y-ftB!Vt{P)ijqRB8GHT?u8S8XlM@`kN|ZTjaQ}{VTE1oX3(E zfs+9&LU)kn7{*KdOy1d`z-KArFw{t@17`!MlTwXgpQNQ;21}*v#c*2ER4;?6Qchub zENQTp!C)zmF?^NO-pio9lrI=QN-B97l%#yb@Kn-3FN1+no?TON gTbN6Cny43i2Q0ZoYfniOg#Z8m07*qoM6N<$g4HVvvj6}9 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_signal_cellular_connected_no_internet_4_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..9e295a031dca1759774b1f8931d0a0337a2aa9c8 GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDD3?#L31Vw-pXMj(LE0BhO=H!@4Q8+jWTc$gh8rF8VXxM-y6q)=kIWA~${kMDbJkr140DyYnq z<=8FAC?6lUO+qk$JF16c1*@(b%atZEWu|veY8ip@@-aDvN)HbEO({*~KgV!52V||M LtDnm{r-UW|v$ZeF literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_signal_wifi_0_bar_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_signal_wifi_0_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a54479adf5a421c7b1b6364faa809a4f6eade727 GIT binary patch literal 338 zcmV-Y0j>UtP)41)^I@+QJ{1sFRnaI}gQCf_ciQv(|KAfNy2Jy%<+!?CMC68~Z|#8+#^5h#le% z(CM?|Mn`IP+~`8vvU7hl8xS`w_KPCOjNKav5@LtAY0kBvo0W`C?oe%GQN+e);T;RTYn{dh3%TA)R$) z38VIfI7glt(<`OdnCHo%eWM~%PKBsl)4Da%Z94H=Pfe*aBSh_(&@Qib6Ly5C82~b& zu0yjroL7fgheBN$sflfUit4i+pN}VA>O|~GP0zg4k8_ zeh7)aTQDHjWutGZ zg8EKWjkpM)-H57qCZov2v8T#XE?aV(|9pC4(-mjwwOQ;uWR{gQQnD=be<&Gp&s{@G znyzfgf$+BjOUjz)X5!uY>6WI+ghZJpst8dPO;#yzzVO7KfsLn`6+n`Ppqq5#N5Lo< Z1psfp#t)8f7R~?w002ovPDHLkV1kp!-Wvb_ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_wifi_tethering_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_wifi_tethering_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..af529e9fb2ddd2dd161a7a7bd22110a6faaa7852 GIT binary patch literal 873 zcmV-v1D5=WP)Ui?;V+qP}SscqY~8`icJCv~{CZF~1Nm`u`#ytmtSqx~kDgS?!3=FGFo zDl5rGF7%esiilC(c7cuj2R8MBfr=_I(DOF6!n%3b0!58j;6dH2fD?^U)ET3kV7YYj zmO_SkK5>rSZK9j*HnN-Zd}6*rhPUcJN2|Z&Mw48mhe~?5$RxSaUs}~+ZNKG~#U9fW z)%En4MY;Z0>!>L|j%f~1kAqChJ#VVv!dyDUW|DRn`qlt*%r?L`F48L5!jRl|q3X1l z70V{uP_U`j@-t*u=rtP&HZnQJXK7W{OR;FaJp`v_wUozvrwaBmFGgQdMTdp4}@2|`qG4(xQb4A2us<|}R zY!3J#^4pd9B&Mze+z|Q5JnnkFHpLWQTQ5KBh*)(4;EKpUR;Eu(9R~P0@;d;X#wjAk zYb`nV&w#@s@2yl`@pgd0k?#R`Bl2tsVE4!e1GbBNiZaV$su{32@+Kf(YSam!De^gh z=E#>Sl@-yWByRzXRmdV(S z>u&>m93$5&vs+$QBjD{E*;6G4WTm|dXvo&SyK-6iSLD;0mVN&sr7p@ko0d0ndA^E@ z?#&A51~}Hz82d@7AF|?)%@Um$WA~}3BOCA&AbX1?wo+;%^YXmF6Zz=cRq>p z(>%|p74G94r4K?WkUx7?JyqR>O{WWJgKHN{G`ZuUM=@nl&fD+mj*xQmS@%ST&{gW-B$B}B?{9tsiny@g(a@D zoc1=<73y)Nq5hsJst~b3#Y~hsW}wPJ3`PL}l!|!;@g{pG00000NkvXXu0mjfmKdoL literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_pause_circle_outline_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_pause_circle_outline_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b3fa91cb7b063ad83db65679f46e3f0fb1e92f07 GIT binary patch literal 848 zcmV-W1F!svP){NMZ97^ctZl6k*2ZcY6n}2^=J8H7-wh|{KXV?h z9wGi%LWJl;8XGx8F4rmN3!kXq2H6~96KV7zh{Uj-LIM`;DI18uFpWv(CIJWS1}QYc z5Gj-raM4Oh!FSqmj(~@Dj&}IS7%B;PY?X|`7us=9^A{x?V-_Q6#t)h^f;k+cSW|J3 zc6g*S_Zl$%$^pUvJy9H>x`E2ObjAZcDMGdU$QF8Hhu&=AlUh$9y>Llu?x|teNEe*Y zm5qE>&l0V1K_l`NqbKyo4MTXWIOWj@$E;IKGH8uk+K{EVt-~SH6oY*Kf7)L;~W%$i<>CZSU$rJJ_n$s}S)cSWxbEFXRis_du{vXzHy7yGw-l zJ#CEyYRh|}T7n+nl928IBY|LtP+dX~EvOOFL}P&xgsO%XXqhO4FThwJcrJ7k(Xv>M zf{g}}BlN{+IUr;Uj0T!7bO+FKS;(ds4K&r>`&!Psh8PVrSkBwf@=jxnf6Gl>iI$5(HZ^FE{ROn_mqQPufffke zetTWVX`_Ko+v_^U8|+;5kI#6!!;g4lf#THRhrQlxyRksqNKbTOU5HjSKv1*?MxK)H+D7Q_(?d`PN&i^>Q7s2P*-xYXpA2;R@TuD zx?iw5f*%|~dcL6x4w&rwlHMW3aUu>`uNY*}8n?72Q*m35V;Yf%x-2{xHw@;9AIrkf znn!=q!Z|=s3JIWw+Ujv@p(h^b%-sezUk(xp=!w>EzL?yeIxe=S+7iYXQdz<=N;DOR zXooM1p^AXVR>hcqbBj}uLWQd^6{KK@#-wt~QJ9;g(ip=;vw=d(D1~ew;ve|b!Zaa5 ag!l%%eiyr@>E9Os00005}jdq4V@!q--% zttJ7wA}g0RW-av4&B|Pm&bHnPLoiAs$ea19)5IvL6=Gdi+UKw@gow<0u^ueO bRZ?xQe3W_PgukYoAeVW%`njxgN@xNA<1a%H literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_0_bar_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_0_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..98197dc42d04b4d0c6687880713fbc9204868d0f GIT binary patch literal 487 zcmV|C}XU1iNQ9xI+v_7N)*Qi*d&d?wmCzZ4f=5)!72r;qvcs8PMf-zlsiz$*5KY?UWEG0V7LM98V%$r0g=BvsWrRg!!#ta@k|q!qP0D}3QZ z<<1FT3X@ZaIgB9U){I%kZG5|97)BCS)MFM-v}2ZWXFb1@B}@wvR6UM4f#g1Jr!fo5 zo*i1IO()thBjZ+%Sx8WEdZ$8y4h>-(#yo@rOU@20;mDDbJ4ZMZau9cx5Q1LZGG;X6 zmN7fA*!H1CJaVKPvlJrT@|`pxJQQm&?g}vky|`t}=*GQ(PmZ)>M#ilhvlOHJ?VU0) zd^Ye++=c-ZEPQ!r9wi4@ISx=0BCQ=WGH&gdk#UQdmCcKo)g6eKm4&#zTZkVdrXO=4 d5V+kC1pun;Y>xx9W+ngt002ovPDHLkV1ftL$%Oy_ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_wifi_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_wifi_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..06ae9d00879a471aff594aca8872f93f815eef5e GIT binary patch literal 695 zcmV;o0!aOdP)swsx^?+sQ7rZQC|(Y}>YN+fG)&*z7yoL7{PfEb6@be!ecNR4SE9rP5h+ zvxIG(>N2-_*o$8Bh+AFmRNGlnH|=I|`?%GYCW!@2_NCkHYe{XUm#sZwnAl*$J!)IM zB(;&-jTT#Ilsj!AfiAZ4xtOTWY^_TxV|MVJn7AM9(A=oieId3{pITc(7VwbR#yx5w zb=uzqvF@fC>SrJL(9ixiRjj-54pM56Cq(6a?=t(@(7d|La^1~q1N*tM&a3YUgA`cZ z-(q2-J?>z0smELn_P8-(VSig)j?GLIbDQK^8|tA^J#66G!sq%#o5`@JX<|-O++uF6 znAgn(*Vi8oEjdff?N7Jc z&2sty7-%`Wx!qr4Zf9vx$o%-c(1MCA=)%ko;Q(nTO?8{O)MIY9nwB#s*`z-#s}alk zBWF&MNpBjWQA50!ehvh;>!umq-7e@fDoZ%tjh^<5n;dT`9jKqfGQI$QbfmsIz}7~J zIgPZPc6LO`S7XgF+SOTNNoQ$iK`bcf0HJfu$)6N-ppbS>`bj}25Yo&^KPl)$f}m2V dR4SDUrUMQu1+TV8a@GI<002ovPDHLkV1gwvV3+^^ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_wifi_tethering_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_wifi_tethering_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a6bf547ebcecf5b8d2a70abcfe1e9298f757cf99 GIT binary patch literal 1276 zcmVz>XS7#J8B z=$D84lt0?EPto!0Xt)IHU@?h=}vXju=|aJFc4i@#V+J09vUZWE2p@=#rxX|9f2{lSt>toVal zo2z6-7l!REiq7yT-FURqMbTb{b?o<|XlFCJHESnP^m`q8n<)CPVJWTnvi+RwQg^uB zWlph=uUL}Ou>Xppcj&;1>xIlZQhJje+%2-qU3Ty$DXl4FuCtknjs3^ExfNuDE$b}*@CvN=6@u4K+l zBKy8N99A5L2}cN-ziZ`hLgp|D|1Ez~H(4BY&yl>RaTyuX%8(s}%)2Ge7TMhSMUvjPx&h;e|5Cb>dnkL&0qdzi?s zsD8idRFOSXa-zuI-}Rc#u-Yt2iC3xse%^U~o{#ie64sTfbb z)82T0iG%}0cAZtUW0hihJV2tj?7mXfw0lMND#<$=qx+OrhV3t8-YI!iaSBbTv!BQ| zsD2g+2bxsJkpByrqa|!0vi(#wx9_bMCC_n>klE9!YF2FwXZL!xWYKNS8K7>lxZ9sd z_@gK~TFp_S=#LV9DzbYlYGG%QU2jS<=0G9y7Bz2ayu4$QDc6f^7cIS5RM%+U$@!Dr z+Wd5Pvia)zgcobW{>2FXJP8X97Q#Iqua3vNM+gU7knmi0H#c;rYjloj31fcY9{<$J zKi%UO#w1KTx1;q*I|-THjVL|Wl2(>HS823yGVQ2stGYqRY^--fwh=NnT2%)=E{Zlc zt{3CB6-6J`p>0Ib5f*i8QFD~rTF1uiFN!YmYTbCXOGVNC#&u!Z38K;Ob?Tp@(NU&# zX-RXb|Jd^bI>J)_Hse+1bZXIceR^}GKj+PTMmN5aGvn{{$?IG$oN7onMw~5N;+6X7 mA$IEF2H#Ts7w5phz`*^k$C1F4Ni*sI0000AyQI2!AeAkTF#TCh=?=z5@A7K zat0A_2b&OgN)f#g25sXLM$?>IIhP|zli>)?;WnBxici>P^!Fi!CDOdx;OJ>| z=UU1Q|Kl3EGY!#z-Xo0#4&>{4N3NkSXW@l2>Bky`UVKe0A#)sa^uw4-W3u=mM79(d$$a7FE2g zo$)Iin?ahX*W!Z`W+5bfL<-xa_&}LElTtkMg63K$PZZ>ts?2@?kCd=T zIrf}IRGgz6k7iSXCmu&g8cmdpQRY8}C#FjFwZ?;)JkaCcB@Se*a$(_ttCexxAkqNP zO>taB!Aw@3;Z#Q+pqll5&j&fSNY()mc>ow7IX07{AnsI#9p@y#35w@V3Sx+IQHzrR z@V&q5fS)B>8)pGpOP-%GL#;CEEN21EQe3qdxn8oY24?|amE^kK`!&#OP6NDZx+XGT z&USMepqu0xgprRV%L7gWJfK|A8~I7HT6kQ)_1dT1lQC z0le?V-#82Kt>hWJe?3+?&hKND9GfL$ei!4se()m`hsH=Q8G%I|2Uo~VWIMh=^UcsEakp%5hZw}ky^fp>?NOCE@^~k zO8EmJ=>v+eO%Wd{bN`?OA6#ameBrBHaw$HUj8N1Lo3szJY5)hYEYh;aQ`$=G0R-SC zZQbSxZ1A+UZgYd3!c!B%rV+xy@)gUf0g}jx-@q$5egkk825oYgwQ#{ZU6q z99D1ba(Lj{v6{;S_-$#CR<_50C$YOdeYn-o^Ln~kww0Ab)XYfDg0OBMlnpoXsT zUxsC(ln4175kQ~wAf-6w97eIh*HXkYi47Gzz*uLCK`kuDeRubA+^sBSDqry~LukPr ioJeRSBqSsxB>V}~Pzp2CNj+--0000(aSy=bH>Q-N;(8TnN0jRRU@&K2TMgrf4CJwF{ y%xka+|7vi5^qw22?+hc@xcU!=VFreL=&EIuXk7fKy8UM;$l0E*elF{r5}E)EY)GL1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_0_bar_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_0_bar_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..ade53936d69ce830c9b9e9118efae1c5c996f148 GIT binary patch literal 602 zcmV-g0;T5CqW}CNncLESiT|vg-cVS>`f(ple_MJb*A7uLnHO^E}V<;*2oE3Ok%|#tju3 zbP$9N4JzDl#tA#DFin9tju>Zyk5uR)&s>KJAJ|}wp-8jA1p(571)Q-;iUG;7O%dtC zuGu8h?^`b+ecm-2WazOZt6UQy16srdOT7v`%P}D`gmu_^Z5cVTAAvS2P=QglDe^YmBNr>4s^V>VxFak_K^W^55-c<7buouu9Kh-3IxXDRc4XC zFJhKH+A|lga$zi9CDF&2YdT&_F$d%skXa&Y@%BIFT?XvJTD&^unz4A5e2-%8>Ub^1 z95KTX?IN$-4vM9i&rmGITp^AF@^oJqZx%<)5E+YC*+HJUZ5(rEEM6r}%|yICh`FQV zwG?y26b{=)9v)jLmSX;Z^Ws#D#j9lLJ|kW;G3$7-74s&>oLP(ap_t3WF(^ytN4yz~ onj$h5ud>Akp67X<=l!=n1IIf~3G+j|O8@`>07*qoM6N<$g8sq>1poj5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_wifi_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_wifi_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b09716aa9080d5562384369335c65a130d7fbb8d GIT binary patch literal 883 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z-;B|;uuoF`1XeLoRn~hV-J_# z-I#lO+uYPMp*hw&U$0ED+1v%>=iZhw^E=}>_jc^}va5g2eZFtDZ+m2@kmn>7F#4l> zF-z=ovNifo@_L@f>TTZ5yCx^FIOAd-Uw70=x3bAQ&lDfy-1+++-=b0py(d{~tmh{9 zo=q}|zRdZ~B<#dhk6b04XO)V(`g=F*EUUek$9=d~$>sZ=qahnt=`Z$|Pl^3|Jw>*8 zQF={g=&~H|{GZiO=;_ z!KV4GT3@ZMscc&HzGUIfsfl*tFV+_My6xlCk8+-Q?L*R+pMt_}uLHLEEml6)KjXt% zSrPqzA05~}3ePi|zh{vYSCIP)uIX`kyi z-@GTVo;xsgiv2^r_6Qf#ZmT1*OXtZOF1&6UHtG1Ob(;VF+~8av5gotg_0p#E{WA>i zaYlU!?H2CQe)Fe;vp+JXUialgCt!#a>{Hu%;mMq$^X+Fiwwk!4-I}OkeEaUyd0!WP zJof9t=5-s|XPUN5jY)qb5*NDfoY$*cm)5QPCG^pBTF~-sUnUD&^xqcJ&Uane<=WeV zQgz`+lUF*6DsJL3dDlV+cd>NklA8^ZQHhO+s4t_W7~5uwr$(CZ9c3<$-S>r)m=U8ua2W)a+3;y$;!&g z%F4>h$~v1T_=1YGWeAg5OfH*Q!W4$kmWq7A6P(FDDb5SjVGaejkJ;4WITGwME~Oe9 zDDZi#qdFI}mlflA22zm5F_7me#$Ita-?M~*0FH%x&*AJ*A>LpG1pyw*c!Lmo$VCjH zAOpt`&SwvJf{hep=-9|ZWK<5nIZt8>{i(_4+|T8lOqd8KaTyQrIW_3d7H9ci36UXT z+9hpzDnD{NB^-6!#!pO5T2DK|WWdo3E40a#{LV%AaS?yAve5d5aRdQ7gV}mx%;J3_ zq$0}uh1NQqGYHV}%vGDor!o=J5u+0MYTa`=A-I=Ee`jZND?zxGS!(@LIFbN_8KqX= zf;d5m(?o4!6vatfWu@X=UMFa;k*l;+ku=?>+?4=nDV^HS&p`} znD!pha1_gw(eg?PQ-U{`oV1Uhz?(^4i!0eIN-X6lQr1X0g-6iE`I5yRqt7pip?g-z z-+&a|rd0L|ni${uj82#FEm1VTD7kMS1x1-DD(XlG=|VXid7N5ah!mou$T^u}`1XO) zFUOG{W@8%B=fg;Grih&H`@jDS#i)B8(%a;v6+q{yr*;APB48AY!&xO>U>|N3jeL*oJoI;e zDQ^))6Xh+IqF?ZN*uEFJZo#vLVhtxQhO8;diEQIfVvgwZPqwOoTM0~uu`bo|ASTAc zKe7F!PHS$!i<{J`%#Yaqv~p}Bh9^&o%Fn=bGMkkt$Z2?W2Gd3P&76$sERp9)JgH8{^dAE? z!*rauEAL{9(~5j65NSmm+dHBzdluZ(O8)?-3XbmW8L<)<5o5#{b+{TM`ueC?se1;~ zk5+mGoH|=YUcgkwO7DcNCI#q6O=oLmF}+}=cgAU~Rpe?%lOKxSJ1d6wgawNLOW z*H0%P(BEI{hFo>z+d6-5gy?`;8&a={2U^+^K zD=uOx5q6{>ia`X;_L7Y0Q1OzP!Xn*4o2AlXj!0VEV|) z(G}AzR(fBY+FL~)cT6){V5{L{AZzZJIz4Ztx525dV=eA!D}5^o5lW2q7)r#&^zv!P zxL*aQkF6rzM3ho#H8mUoTB0*yadx5;=Yw36=g&{UtqdKEWhO7##l!{9TS69J~!ak4Ps2s zy!IL85<0`K|1M!BwfEO33`;30WR!;mm_DB}pB!cRqj8*&ky10~Pn^JBZMKK*E z!p7h6>`KuA>4 zFDic( zBS<%~dVBiafWMAg+*X4;9wC!nS5ChnDLaG(%8-9MnQ{lY%Fc>I(yLP2SotWK z@Tj^e^ET2{UfnDAK0*6T-8)x-wB^u7je05(CMYGSqVFIjhX53(pIZGit|bW9F+;6? z0L2MNf^qsf4}X%b-}G&lj3+^Wj@HBH050G!{q#ASfF#mJD5v5T}HLFs3N?IAMic4lv%hMZ4O&L?+!yn8!)K$NoNQGp;;B$u*8 p*ki6HL68z$&A}%tD=RB2>u&;%<022^ZFv9y002ovPDHLkV1iLTQAq#* literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_sync_conditions.xml b/app/src/main/res/layout/activity_sync_conditions.xml new file mode 100644 index 00000000..382768b6 --- /dev/null +++ b/app/src/main/res/layout/activity_sync_conditions.xml @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_device.xml b/app/src/main/res/layout/fragment_device.xml index fe168280..28574c79 100644 --- a/app/src/main/res/layout/fragment_device.xml +++ b/app/src/main/res/layout/fragment_device.xml @@ -118,8 +118,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:checked="false" - android:drawableLeft="@drawable/ic_settings_black_24dp" - android:drawableStart="@drawable/ic_settings_black_24dp" + android:drawableLeft="@drawable/ic_pause_circle_outline_black_24dp" + android:drawableStart="@drawable/ic_pause_circle_outline_black_24dp" android:text="@string/pause_device" /> + + - - - + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/sync_conditions_settings.xml b/app/src/main/res/menu/sync_conditions_settings.xml new file mode 100644 index 00000000..7361257f --- /dev/null +++ b/app/src/main/res/menu/sync_conditions_settings.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 28b52c53..25299d16 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -5,10 +5,6 @@ استمرار خطأ - - - - إضافة مجلد diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 78a3601b..b4546499 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -19,10 +19,6 @@ Грешка Игнориране - - - - Добави папка @@ -216,7 +212,6 @@ Условия на работа Поведение Настройки на Syncthing - Резервно копие Дебъг Експериментални @@ -225,24 +220,10 @@ За да изберете мрежа, моля включете WiFi - Избор на папка, за напреднали - - Изберете папка, от устройството, за синхронизиране - Стартира Syncthing с права на Superuser Може да предизвика разнообразни проблеми със Syncthing и като цяло с устройството. При възникване на проблем може да се наложи преинсталиране на Syncthing. - Известия - - Изберете тип известия - - - Нормални - С нисък приоритет - Без известия - - Име на устройството Адрес за слушане на синхронизиращия протокол @@ -275,15 +256,12 @@ Наистина ли желаете внасянето на нови настройки? Съществуващите файлове ще бъдат презаписани. - + Настройките са изнесени в %1$s - Внасяне на настройки - + Настройките са внесени - - Внасянето на настройките се провали. Уверете се, че файловете са в %1$s diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 9fde2e23..bf3fc0d3 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -19,10 +19,6 @@ Ens podeu informar dels problemes que trobeu a través de Github. Finalitza Exemple Error - - - - Afegeix una carpeta @@ -243,7 +239,6 @@ Ens podeu informar dels problemes que trobeu a través de Github. Condicions d\'execució Comportament Opcions del Syncthing - Còpia de seguretat Depuració Experimental @@ -258,24 +253,10 @@ Ens podeu informar dels problemes que trobeu a través de Github. Respecta la configuració d\'estalvi de bateria de l\'Android - Utilitza el selector de carpetes avançat - - Seleccioneu qualsevol carpeta del dispositiu per sincronitzar-la - Executa el Syncthing com a Superusuari Aquesta característica és inestable i podria causar problemes amb el Syncthing i amb el vostre dispositiu. Si us trobeu amb problemes, potser haureu de reinstal·lar el Syncthing. - Notificació - - Seleccioneu el tipus de notificació - - - Normal - Baixa Prioritat - Cap - - Idioma Canvieu l\'idioma de l\'aplicació @@ -327,8 +308,6 @@ Ens podeu informar dels problemes que trobeu a través de Github. Mantingues activa la CPU mentre s\'executi el Syncthing - Activeu-ho si experimenteu desconnexions inesperades quan treballeu amb bateria. S\'incrementarà el consum de la bateria. - Utilitza Tor Força la connexió a través de Tor per millorar la privacitat. Requereix Orbot. Desactiva les opcions del proxy. @@ -359,15 +338,12 @@ Ens podeu informar dels problemes que trobeu a través de Github. Realment voleu importar una nova configuració? Es sobreescriuran els fitxers existents. - + S\'ha exportat la configuració a %1$s - Importa la configuració - + S\'ha importat la configuració - - Ha fallat la importació de la configuració, verifiqueu que els fitxers siguin a %1$s @@ -519,7 +495,6 @@ Ens podeu informar dels problemes que trobeu a través de Github. El Syncthing s\'ha aturat - No s\'ha pogut crear el fitxer de configuració Càmera @@ -619,5 +594,4 @@ Ens podeu informar dels problemes que trobeu a través de Github. Navega No s\'ha triat cap subcarpeta Comparteix la ID del dispositiu amb - - + diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 74cce45a..767d6a50 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -20,10 +20,6 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Chyba Ignorovat - - - - Přidat adresář @@ -231,7 +227,6 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Podmínky spuštění Chování Nastavení Syncthing - Záloha Ladění Experimentální @@ -241,24 +236,10 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Dodržovat nastavení úspory baterie z Androidu - Použít rozšířený výběr adresáře - - Vyberte jakýkoliv adresář v přístroji pro synchronizaci - Spustit syncthing jako superuživatel Toto je nestabilní funkce, které může způsobit problémy se Syncthing a s vaším zařízením. Pokud narazíte na problémy, může být třeba přeinstalovat Syncthing. - Upozornění - - Vybrat typ upozornění - - - Normální - Nízká priorita - Źádné - - Jazyk Změnit jazyk aplikace @@ -303,8 +284,6 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Udržovat CPU aktivní pokud běží Syncthing - Použijte toto nastavení pokud zaznamenáváte neočekávaná ukončení spojení při běhu na baterii. Toto bude mít za následek vyšší spotřebu energie. - Použít Tor Používat standardní kontrolní součet @@ -317,15 +296,12 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Opravud chcete importovat novou konfiguraci? Existující soubory budou přepsány. - + Nastavení bylo zálohováno do %1$s - Nahrát nastavení - + Nastavení bylo nahráno - - Nahrání nastavení selhalo, ujistěte se, že soubory jsou v %1$s @@ -465,7 +441,6 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Syncthing je vypnutý - Vytváření konfiguračního souboru selhalo Kamera @@ -562,5 +537,4 @@ Všechny zaznamenané chyby prosím hlašte přes Github. Procházet Není vybrána žádná podsložka Sdílet ID zařízení s - - + diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index a46249d8..b1b58158 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -18,10 +18,6 @@ Vær venlig at rapportere ethvert problem, du støder på, via Github. Fortsæt Færdiggør Fejl - - - - Tilføj mappe @@ -227,7 +223,6 @@ Vær venlig at rapportere ethvert problem, du støder på, via Github. Kør betingelser Adfærd Syncthing Muligheder - Backup Debug Eksperimentalt @@ -237,24 +232,10 @@ Vær venlig at rapportere ethvert problem, du støder på, via Github. Respekter Android battery saving indstillinger - Brug avanceret Mappe Vælger - - Vælg en valgfri mappe på enheden for synkronisering - Kør Syncthing som Superuser Dette er en ustabil feature som kan forudsage problemer med Syncthing og din enhed. Hvis du støder på problemer, kan det være du er nødt til at geninstallere Syncthing. - Notifikation - - Vælg notifikationstype - - - Normal - Lav prioritet - Ingen - - Sprog Ændr app sproget @@ -299,8 +280,6 @@ Vær venlig at rapportere ethvert problem, du støder på, via Github. Lad CPU\'en køre imens Syncthing kører - Brug denne indstilling hvis du oplever uventede forbindelsesbrud imens batteriet bruges. Dette vil resultere i forøget batteriforbrug. - Brug Tor Brug legacy hashing @@ -313,15 +292,12 @@ Vær venlig at rapportere ethvert problem, du støder på, via Github. Er du sikker på du vil importere en ny konfiguration? Eksisterende filer vil gå tabt. - + Konfigurationen blev eksporteret til %1$s - Importer Konfiguration - + Konfigurationen blev importeret - - Import af konfigurationen slog fjel, vær sikker på at filer er i %1$s diff --git a/app/src/main/res/values-de-rAT/strings.xml b/app/src/main/res/values-de-rAT/strings.xml new file mode 100644 index 00000000..e0019553 --- /dev/null +++ b/app/src/main/res/values-de-rAT/strings.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml new file mode 100644 index 00000000..e0019553 --- /dev/null +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7a246254..a67ef9a0 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -48,6 +48,10 @@ Bitte melden Sie auftretende Probleme via GitHub. + + Beenden der App bestätigen + Zu Deiner Erinnerung: Du hast Syncthing eingerichtet, automatisch beim Hochfahren zu starten. Deshalb überwacht es die Laufkonditionen und synchronisiert, wenn die Bedingungen zutreffen. Du solltest nur manuell beenden, wenn Du größere Probleme feststellst. Andernfalls schalte \"Automatisch beim Hochfahren starten\" in den Einstellungen aus. Möchtest Du jetzt beenden, bis das Gerät neu gestartet wurde? + Verzeichnis hinzufügen @@ -294,7 +298,7 @@ Bitte melden Sie auftretende Probleme via GitHub. Laufkonditionen Verhalten Syncthing-Optionen - Datensicherung + Import und Export Fehleranalyse Experimentell @@ -311,8 +315,8 @@ Bitte melden Sie auftretende Probleme via GitHub. Starte bei getakteter WLAN-Verbindung Starte, wenn das Gerät mit einem getakteten WLAN-Netzwerk wie z. B. einem Hotspot- oder Tethering-Netzwerk verbunden ist. Achtung: Dies kann einen großen Anteil des mobilen Datenvolumens verbrauchen, wenn Du viele Dateien synchronisierst. - Starte in festgelegten WLAN-Netzwerken - Starte nur in ausgewählten WLAN-Netzwerken: %1$s + Starte bei ausgewählten WLAN\'s + Starte in ausgewählten WLAN\'s: %1$s Starte in allen WLAN-Netzwerken. Bitte WLAN aktivieren, um eines zu wählen. @@ -345,24 +349,10 @@ Bitte melden Sie auftretende Probleme via GitHub. Starte den Dienst automatisch beim Hochfahren - Erweiterte Verzeichnisauswahl benutzen - - Alle Verzeichnisse auf dem Gerät für Synchronisation auswählbar - Syncthing mit Superuser Rechten ausführen 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. - Permanente Benachrichtigung - - Wähle die Art der Benachrichtigung - - - Normale Priorität - Geringe Priorität - Keine Priorität - - Sprache Anwendungssprache ändern @@ -434,7 +424,7 @@ Bitte melden Sie auftretende Probleme via GitHub. Prozessor wach halten während Syncthing läuft. - Nur für Android 5 oder niedriger. Nutze diese Einstellung, wenn du unerwartete Verbindungsabbrüche hast, während du im Batteriebetrieb arbeitest. Das wird zu einem erhöhten Energieverbrauch führen. + Nur für Android 5 oder niedriger. Benutze diese Einstellung, wenn Du unerwartete Verbindungsabbrüche hast, während Du im Batteriebetrieb arbeitest. Das wird zu einem erhöhten Energieverbrauch führen. Tor benutzen @@ -466,15 +456,14 @@ Bitte melden Sie auftretende Probleme via GitHub. Soll wirklich eine neue Konfiguration importiert werden? Die vorhandene Konfiguration wird überschrieben. - + Konfiguration exportiert nach %1$s + Konfigurations-Export fehlgeschlagen, prüfe die Logcat-Ausgabe. Konfiguration importieren - + Konfiguration importiert - - Import fehlgeschlagen, Dateien werden in %1$s erwartet @@ -614,8 +603,10 @@ Bitte melden Sie auftretende Probleme via GitHub. Telefon wird nicht batteriebetrieben Syncthing läuft nicht, weil das Telefon im Energiesparmodus ist. Syncthing läuft nicht, weil die Android-Kachel \"Automatische Datensynchronisation\" ausgeschaltet ist. + Syncthing wurde verboten, die mobile Datenverbindung zu nutzen. Syncthing läuft, weil die mobile Datenverbindung aufgebaut ist. Syncthing darf bei mobiler Datenverbindung laufen, jedoch sind mobile Daten nicht verbunden. + Syncthing wurde verboten, die WLAN-Verbindung zu nutzen. Syncthing darf bei WLAN-Verbindung laufen und WLAN ist gerade verbunden. Syncthing darf bei WLAN-Verbindung laufen, jedoch ist WLAN gerade nicht verbunden oder das Telefon befindet sich im Flugzeugmodus. Syncthing darf bei getakteter und nicht-getakteter WLAN-Verbindung laufen. @@ -623,8 +614,13 @@ Bitte melden Sie auftretende Probleme via GitHub. Syncthing läuft nicht, weil der Name des aktuellen WLAN-Netzwerks nicht auf der weißen Liste steht. Syncthing darf bei nicht-getakteter WLAN-Verbindung laufen. Die aktive WLAN-Verbindung ist nicht-getaktet. Syncthing läuft nicht, weil Du verboten hast, dass es bei getakteten WLAN-Verbindungen läuft. + Du hast \'Starte in ausgewählten WLAN-Netzwerken\' in den Einstellungen aktiviert. Die Android-tandorterfassung ist derzeit ausgeschaltet. Aufgrund von Android-Beschränkungen kann Syncthing den aktuellen WLAN-Netzwerknamen nicht ermitteln, um zu entscheiden, ob es starten soll. Lösung: Schalte den Standort ein und verbinde WLAN erneut. Syncthing läuft, weil Du erlaubt hast, dass es bei eingeschaltetem Flugzeugmodus läuft. + + + Es sind keine WLAN-Netzwerknamen auf der Erlaubt-Liste. Bitte lege welche in den Einstellungen fest. + @@ -641,6 +637,7 @@ Bitte melden Sie auftretende Probleme via GitHub. Syncthing wurde beendet + Ausführbarer Kernbestandteil der App \"%s\" fehlt. Bitte prüfe den Build und die Logcat-Ausgabe. Erstellen der Konfiguration fehlgeschlagen. Pruefe die logcat-Ausgabe! Fehler beim Lesen der Konfiguration. Sichere gegebenenfalls Daten aus deinen Sync-Ordnern zu sichern, lösche über die Android-Einstellungen die App-Daten und starte von vorn. @@ -776,5 +773,9 @@ Bitte melden Sie auftretende Probleme via GitHub. Durchsuchen Kein Verzeichnis ausgewählt Teile Geräte ID mit + Schalte die Erlaubt-Liste ein, um die Synchronisation auf die ausgewählten WLAN-Netzwerke zu beschränken. + Individuelle Sync-Bedingungen + Du kannst Ausnahmen zu den übergeordneten Laufkonditionen festlegen. + Lege Sync-Bedingungen fest diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 6d740aa4..ecc1ab2b 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -18,10 +18,6 @@ Συνέχεια Τέλος Σφάλμα - - - - Προσθήκη φακέλου @@ -227,7 +223,6 @@ Συνθήκες εκτέλεσης Συμπεριφορά Επιλογές Syncthing - Αντίγραφο ασφαλείας Αποσφαλμάτωση Πειραματικά @@ -237,24 +232,10 @@ Υπακοή στη ρύθμιση εξοικονόμησης ενέργειας του Android - Χρήση προχωρημένου επιλογέα φακέλων - - Επιλογή οποιουδήποτε φακέλου στη συσκευή για συγχρονισμό - Εκτέλεση του Syncthing ως υπερχρήστης Πρόκειται για μια πειραματική λειτουργία η οποία ενδέχεται να προκαλέσει προβλήματα στο Syncthing και τη συσκευή σας. Σε αυτή την περίπτωση, ίσως χρειαστεί να επανεγκαταστήσετε το Syncthing. - Ειδοποίηση - - Επιλέξτε τον τύπο ειδοποίησης - - - Κανονική - Χαμηλής προτεραιότητας - Καμία - - Γλώσσα Αλλαγή γλώσσας της εφαρμογής @@ -299,8 +280,6 @@ Διατήρηση της CPU σε ενεργό κατάσταση όσο εκτελείται το Syncthing - Χρησιμοποιήστε αυτή την επιλογή αν παρατηρείτε απρόσμενες αποσυνδέσεις κατά τη λειτουργία με μπαταρία. Θα έχει ως συνέπεια την υψηλότερη κατανάλωση ενέργειας. - Χρήση του Tor Χρήση κατακερματισμού παλαιού τύπου @@ -313,15 +292,12 @@ Σίγουρα επιθυμείτε να εισάγετε τις νέες ρυθμίσεις; Τυχόν υπάρχοντα αρχεία θα διαγραφούν. - + Οι ρυθμίσεις εξήχθησαν στο %1$s - Εισαγωγή ρυθμίσεων - + Οι ρυθμίσεις εισήχθησαν - - Η εισαγωγή ρυθμίσεων απέτυχε, σιγουρευτείτε ότι τα αρχεία βρίσκονται στο %1$s @@ -455,7 +431,6 @@ Το Syncthing είναι απενεργοποιημένο - Αδυναμία δημιουργίας αρχείου ρυθμίσεων Φωτογραφική μηχανή @@ -552,5 +527,4 @@ Περιήγηση Δεν έχει επιλεγεί υποφάκελος Διαμοιρασμός ID συσκευής με - - + diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 3b72b563..9101f41a 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -14,10 +14,6 @@ Error Ignorar - - - - Añadir carpeta @@ -206,22 +202,8 @@ Por favor encienda el WiFi para seleccionar redes. - Usar el avanzado Seleccionador de Carpetas - - Seleccionar cualquier carpeta en el dispositivo para sincronizar - Ejecutar Syncthing como Superusuario - Notificación - - Escoger el tipo de notificación - - - Normal - Baja Prioridad - Ninguna - - Nombre del dispositivo Direcciones de escucha del Protocolo de Sincronización @@ -242,23 +224,18 @@ Mantener el CPU encendido mientras Syncthing está en ejecución - Use estos ajustes si experimenta desconexiones inesperadas mientras opera con la batería. Esto resultará en un consumo elevado de batería. - ¿Realmente quiere exportar su configuración? Los archivos existentes se sobreescribirán.\n\n¡ADVERTENCIA! Otras aplicaciones pudieran leer la llave privada desde la ubicación del respaldo y usarla para descargar/modificar los archivos sincronizados. ¿Realmente quiere importar una nueva configuración? Los archivos existentes se sobreescribirán. - + Configuración exportada a %1$s - Importar Configuración - + Configuración importada - - Importar la configuración falló, asegúrese que los archivos están en %1$s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d7404dec..2e2dcc97 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -16,10 +16,6 @@ Continuar Finalizar Error - - - - Añadir carpeta @@ -216,7 +212,6 @@ Condiciones de ejecución Comportamiento Opciones de Syncthing - Copia de seguridad Depuración Experimental @@ -226,24 +221,10 @@ Respeta la configuración de ahorro de batería de Android - Usar selección avanzada de carpeta - - Escoja alguna carpeta del dispositivo para sincronizar - Ejecutar Syncthing como superusuario Esta es una característica inestable que podría causar problemas con Syncthing y con tu dispositivo. Si aparecieran problemas podrías tener que reinstalar Syncthing. - Notificación - - Elige el tipo de notificación - - - Normal - Baja prioridad - Ninguna - - Idioma Cambiar el idioma de la aplicación @@ -276,8 +257,6 @@ Mantener la CPU activa mientras se ejecuta Syncthing - Usa este ajuste si experimentas desconexiones inesperadas mientras funcionas con la batería. Esto resultará en un incremento del consumo de batería. - Usar Tor Utilizar método antiguo para generar los hash @@ -290,15 +269,12 @@ ¿Realmente deseas importar una nueva configuración? Se sobrescribirán los archivos existentes. - + La configuración fue exportada a %1$s - Importar configuración - + Configuración importada - - Importación de la configuración fallida, comprueba que los ficheros están en %1$s diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3147f767..80eaf8e0 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -19,10 +19,6 @@ Ilmoitathan ystävällisesti kaikista havaitsemistasi ongelmista Githubin kautta Valmis Esimerkki Virhe - - - - Lisää kansio @@ -232,7 +228,6 @@ Ilmoitathan ystävällisesti kaikista havaitsemistasi ongelmista Githubin kautta Käyntiehdot Käyttäytyminen Syncthing asetukset - Varmuuskopio Vianhaku Kokeellinen @@ -242,18 +237,10 @@ Ilmoitathan ystävällisesti kaikista havaitsemistasi ongelmista Githubin kautta Noudata Androidin virransäästöasetusta - Käytä edistynyttä Kansionvalitsinta - - Valitse mikä tahansa laitteen kansio synkronointiin. - Käynnistä Syncthing pääkäyttäjän oikeuksin. Tämä on epävakaa ominaisuus joka voi aiheuttaa ongelmia Synthingin ja laitteesi kanssa. Jos sinulle tulee vastaan ongelmia, voit joutua asentamaan Syncthingin uudelleen. - Ilmoitus - - Valitse ilmoituksen tyyppi - Kieli Muuta sovelluksen kieli @@ -286,8 +273,6 @@ Ilmoitathan ystävällisesti kaikista havaitsemistasi ongelmista Githubin kautta Pidä suoritin hereillä kun Syncthing on käynnissä - Käytä tätä asetusta, jos yhteydet katkeilevat odottamattomasti laitteen käydessä akkuvirralla. Tämä lisää virran kulutusta. - Käytä Tor-verkkoa Käytä vanhaa tarkistussumman laskentaa @@ -300,15 +285,12 @@ Ilmoitathan ystävällisesti kaikista havaitsemistasi ongelmista Githubin kautta Haluatko varmasti tuoda uudet asetukset? Vanhat tiedostot ylikirjoitetaan. - + Asetukset vietiin kansioon %1$s - Tuo asetukset - + Asetukset tuotiin - - Asetusten tuonti epäonnistui. Varmista, että tiedostot ovat kansiossa %1$s diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8060804d..f6cc4c5d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -21,10 +21,6 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Erreur Ignorer - - - - Ajouter un partage @@ -245,7 +241,6 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Conditions d\'exécution Comportement Options Syncthing - Sauvegarde Debug Expérimental @@ -260,24 +255,10 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Sauvegarde batterie selon les réglages Android - Choix étendu des répertoires - - Permettre la sélection de n\'importe quel répertoire de cet appareil pour créer les partages - Faire fonctionner syncthing en super-utilisateur Ceci est une fonction instable qui peut causer des problèmes entre Syncthing et votre appareil. Si vous rencontrez des problèmes, vous devrez réinstaller Syncthing. - Notification - - Choisissez le mode de notification - - - Permanente - Discrète - Aucune - - Langue Changer la langue de l\'application @@ -329,8 +310,6 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Garder le CPU en éveil quand Syncthing fonctionne. - Utilisez ce paramètre si vous rencontrez des déconnexions inattendues en fonctionnant sur batterie. Il en résultera une augmentation de la consommation de la batterie. - Utiliser Tor Forcer tout le trafic à travers Tor mieux préserver sa vie privée. Nécessite Orbot. Désactive les options de proxy. @@ -361,15 +340,12 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github. Voulez-vous vraiment importer la nouvelle configuration ? Les paramètres existants seront écrasés. - + La configuration a été exportée dans %1$s - Importer la configuration - + La configuration a été importée - - Echec de l\'import de la configuration, assurez-vous que les fichiers sont dans %1$s @@ -521,7 +497,6 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Syncthing va s\'arrêter - Echec de création du fichier de configuration Caméra @@ -621,5 +596,4 @@ S\'il vous plaît, soumettez les problèmes que vous rencontrez via Github.Parcourir Aucun sous-répertoire sélectionné Partager ID de l\'appareil avec - - + diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 69b10917..ca801d20 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -21,10 +21,6 @@ Kérlek, hogy az esetlegesen felmerülő hibákat jelentsd be a GitHub-on.Befejezés Példa Hiba - - - - Mappa hozzáadása @@ -249,7 +245,6 @@ Néhány eszközön extra alkalmazás-leállító alkalmazást telepített fel a Futás feltételei Viselkedés Syncthing opciók - Biztonsági mentés Hibakeresés Kísérleti @@ -264,24 +259,10 @@ Néhány eszközön extra alkalmazás-leállító alkalmazást telepített fel a Az Android akkumulátor-optimalizáció beállításainak tiszteletben tartása - Advanced mappaválasztó használata - - Bármely mappa kiválasztható szinkronizáláshoz - Syncthing futtatása Superuser-ként Ez egy kísérleti funkció, amely problémákat okozhat mind a Syncthing, mind az eszközöd számára. Ha ilyenbe ütközöl, előfordulhat, hogy újra kell telepítened az alkalmazást. - Értesítés - - Értesítés típusának kiválasztása - - - Normál - Alacsony prioritású - Semmilyen - - Nyelv Alkalmazás nyelvének megváltoztatása @@ -328,8 +309,6 @@ Néhány eszközön extra alkalmazás-leállító alkalmazást telepített fel a Kapcsolódás porxyn keresztül CPU ébren tartása a Syncthing futása során - Ezt a beállítást akkor használd, ha váratlan szakadásokat tapasztalsz akkumulátoros üzemben. Ennek hatására megnő az alkalmazás energiafelhasználása. - Tor használata A megnövelt biztonság érdekében minden forgalom a TOR-on keresztül. Orbot szükséges. Letiltja a proxy beállításokat. @@ -362,15 +341,12 @@ VIGYÁZAT! Más alkalmazások kiolvashatják a backupból a titkos kulcsot, és Biztosan importálod a konfigurációt? A meglévő fájlok felül lesznek írva. - + A konfiguráció exportálása megtörtént: %1$s - Konfiguráció importálása - + A konfiguráció importálása megtörtént. - - Nem sikerült a konfiguráció importálása. Győzödj meg róla, hogy a fájlok itt találhatóak: %1$s @@ -518,7 +494,6 @@ VIGYÁZAT! Más alkalmazások kiolvashatják a backupból a titkos kulcsot, és A Syncthing le van tiltva - Nem sikerült létrehozni a konfigurációs fájlt Kamera @@ -618,5 +593,4 @@ VIGYÁZAT! Más alkalmazások kiolvashatják a backupból a titkos kulcsot, és Tallóz Nincs kiválasztott almappa Eszközazonosító megosztása ezzel - - + diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 80d6dc10..b288c2d2 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -16,10 +16,6 @@ Untuk berbagi data dengan perangkat lain, anda perlu menambah ID masing-masing p Jika ada masalah silakan laporkan lewat Github. Lanjutkan - - - - Tambah Folder @@ -221,7 +217,6 @@ Jika ada masalah silakan laporkan lewat Github. Syarat Operasi Perilaku Opsi Syncthing - Backup Debug Ujicoba @@ -231,24 +226,10 @@ Jika ada masalah silakan laporkan lewat Github. Ikuti pengaturan penghematan baterai Android - Gunakan Pemilihan Folder tahap lanjut - - Pilih sembarang folder dalam perangkat untuk penyelarasan - Jalankan Syncthing sebagai Superuser Ini merupakan fitur belum stabik yang mungkin menyebabkan masalah pada Syncthing dan perangkat anda. Jika menemui masalah, anda mungkin harus memasang ulang Syncthing. - Notifikasi - - Pilih jenis notifikasi - - - Normal - Prioritas Rendah - Tidak Ada - - Bahasa Ganti bahasa dalam aplikasi @@ -285,8 +266,6 @@ Jika ada masalah silakan laporkan lewat Github. Buat CPU tetap aktif saat Syncthing berjalan - Gunakan pengaturan ini jika anda mengalami pemutusan sambungan saat beroperasi dengan baterai. Ini akan menghasilkan peningkatan konsumsi baterai. - Gunakan Tor Gunakan hashing lawas @@ -299,15 +278,12 @@ Jika ada masalah silakan laporkan lewat Github. Anda yakin ingin mengimpor konfigurasi baru? Berkas yang ada akan ditimpa. - + Konfig sudah diekspor ke %1$s - Impor Konfigurasi - + Konfig sudah diimpor - - Impor konfig gagal, pastikan berkasnya dalam %1$s diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fdb51f82..d4b14cb3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -21,10 +21,6 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Errore Ignora - - - - Nuova Cartella @@ -245,7 +241,6 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Condizioni di funzionamento Comportamento Opzioni di Syncthing - Backup Debug Sperimentale @@ -260,24 +255,10 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Rispetta l\'impostazione di risparmio batteria di Android - Utilizza Selettore Cartella avanzato - - Selezionare una cartella sul dispositivo per la sincronizzazione - Esegui Syncthing come Superutente Questa è una caratteristica instabile che può causare problemi con Syncthing e con il dispositivo. In caso di problemi, potrebbe essere necessario reinstallare Syncthing. - Notifica - - Scegli tipo di notifica - - - Normale - Bassa priorità - Nessuno - - Lingua Cambia la lingua dell\'app @@ -329,8 +310,6 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Mantieni attiva la CPU quando syncthing è in esecuzione - Usa questa impostazione se rilevi disconnessioni inaspettate durante il funzionamento a batteria. Questo aumenterà il consumo della batteria. - Utilizza Tor Forza tutto il traffico attraverso Tor per una maggiore privacy. Richiede Orbot. Disabilita le opzioni proxy. @@ -361,15 +340,12 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Vuoi realmente importare una nuova configurazione? I files esistenti verranno sovrascritti. - + Config è stata esportata in %1$s - Importa Configurazione - + Configurazione importata - - Importazione della configurazione fallita. Assicurarsi che i file siano in %1$s @@ -521,7 +497,6 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Syncthing è stato terminato - Impossibile creare il file di configurazione Camera @@ -621,5 +596,4 @@ Si prega di segnalare eventuali problemi che si incontrano via Github. Sfoglia Nessuna sottocartella selezionata Condividi ID dispositivo con - - + diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 5fff3f9e..7ea3aa50 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -20,10 +20,6 @@ エラー 無視 - - - - フォルダーを追加 @@ -228,7 +224,6 @@ 実行条件 動作 同期オプション - バックアップ デバッグ 実験的 @@ -238,24 +233,10 @@ Android の節電設定に従う - 高度なフォルダー選択を使用 - - デバイス上の任意のフォルダーを選択できます - スーパーユーザーとして実行 これは Syncthing とお使いのデバイスに問題が生じる可能性のある、安定していない機能です。問題が発生した場合は、Syncthing の再インストールが必要な場合があります。 - 通知 - - 通知のタイプを選択します - - - 通常 - 優先度低 - なし - - 言語 アプリの言語を変更します @@ -300,8 +281,6 @@ 実行中は CPU をオンのままにする - バッテリーでの動作中に予期しない切断が発生する場合オンにしてください。バッテリー消費量が増える場合があります。 - Tor を使用する レガシーハッシュを使用する @@ -314,15 +293,12 @@ 新しい設定をインポートしてもよろしいですか? 既存のファイルは上書きされます。 - + 設定を %1$s にエクスポートしました - 設定のインポート - + 設定をインポートしました - - 設定のインポートに失敗しました。%1$s にファイルがあるか確認してください @@ -453,7 +429,6 @@ Syncthing は無効になりました - 設定ファイルの作成に失敗しました カメラ @@ -550,5 +525,4 @@ 閲覧 サブフォルダーが選択されていません 次とデバイス ID を共有 - - + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 61d32f29..b276a269 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -18,10 +18,6 @@ 계속 완료 오류 - - - - 폴더 추가 @@ -226,7 +222,6 @@ 작동 상태 동작 Syncthing 옵션 - 백업 디버그 실험적인 기능 @@ -236,24 +231,10 @@ 안드로이드 배터리 절약 설정 우선 - 고급 폴더 선택기 사용 - - 기기에서 동기화에 사용할 폴더를 골라 주세요 - Syncthing을 Superuser로 실행 이 기능은 불안정하며 Syncthing과 기기에 문제를 일으킬 수 있습니다. 문제가 발생한 경우 Syncthing을 재설치 해야 할 수도 있습니다. - 알림 - - 알림 종류를 선택하세요 - - - 일반 - 우선 순위 낮음 - 사용 안 함 - - 언어 언어 변경하기 @@ -298,8 +279,6 @@ Syncthing이 실행 중일 때 CPU를 깨어 있는 상태로 두기 - 만약 배터리로 사용중 예상하지 못한 접속 끊김이 발생 했다면 이 설정을 사용합니다. 이 기능은 배터리 소비를 늘립니다. - Tor 사용 레가시 해싱 쓰기 @@ -312,15 +291,12 @@ 새로운 설정을 불러오시겠습니까? 현재 존재하는 파일이 덮어쓰기됩니다.` - + 설정을 %1$s 로 내보내기했습니다 - 설정 불러오기 - + 설정을 불러왔습니다 - - 설정을 불러오지 못했습니다, 파일이 %1$s에 있는지 확인해 주세요 @@ -451,7 +427,6 @@ Syncthing이 비활성화되었습니다 - 구성 파일을 만드는데 실패 했습니다. 카메라 @@ -548,5 +523,4 @@ 탐색 하위 폴더가 선택되지 않았습니다 기기 ID 공유 - - + diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 448ce2ec..1e4e52bf 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -12,10 +12,6 @@ Velkommen til Syncthing for Android Feil - - - - Legg til Mappe @@ -209,24 +205,10 @@ Vennligst skru på WiFi for å velge nettverk. - Bruk avansert mappevelger - - Velg en mappe på enheten for synkronisering - Kjør Syncthing som superbruker Dette er en ustabil funksjon som kan forårsake problemer med Syncthing og med din enhet. Hvis det oppstår problemer kan du bli nødt til å reinstallere Syncthing. - Varsler - - Velg varslingstype - - - Normal - Lav prioritet - Ingen - - Enhetsnavn Lytteadresser for synkeprotokoll @@ -251,23 +233,18 @@ Hold prosessoren våken mens Syncthing kjører - Bruk denne innstillingen dersom du opplever uventede frakoblinger mens enheten går på batteri. Dette vil medføre økt batteriforbruk. - Ønsker du virkelig å eksportere innstillingene? Eksisterende filer vil bli overskrevet.\n\nADVARSEL! Andre applikasjoner kan være i stand til å lese den private nøkkelen fra sikkerhetskopien og bruke den til å laste ned eller endre synkroniserte filer. Er du sikker på at du vil importere innstillinger? Eksisterende filer vil bli skrevet over. - + Innstillingene ble eksportert til %1$s - Importer instillinger - + Instillingene ble importert - - Import av innstillinger mislyktes, sørg for at filene er i %1$s diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index ed3cf923..77163c4e 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -21,10 +21,6 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Fout Negeren - - - - Map toevoegen @@ -245,7 +241,6 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Uitvoervoorwaarden Gedrag Syncthing-opties - Back-up Debug Experimenteel @@ -260,24 +255,10 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Eerbiedig de batterijbesparingsinstellingen van Android - Gebruik geavanceerde mapkiezer - - Selecteer een map op het toestel om te synchroniseren - Syncthing uitvoeren als superuser Dit is een onstabiele functie die problemen kan veroorzaken met Syncthing en je apparaat. Als je problemen zou tegenkomen is het mogelijk dat je Syncthing opnieuw moet installeren. - Melding - - Kies het meldingstype - - - Normaal - Lage prioriteit - Geen - - Taal Wijzig de taal van de app @@ -329,8 +310,6 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Laat de CPU niet slapen wanneer Syncthing wordt uitgevoerd - Gebruik deze instelling als je onverwacht losgekoppeld wordt wanneer je op batterij werkt. Dit zal leiden tot verhoogd batterijverbruik. - Gebruik Tor Dwing alle verkeer door Tor voor verhoogde privacy. Schakelt proxyopties uit. @@ -361,15 +340,12 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Wil je een nieuwe configuratie echt importeren? Bestaande bestanden zullen worden overschreven. - + Configuratie is geëxporteerd naar %1$s - Configuratie importeren - + Configuratie geïmporteerd - - Importeren van configuratie mislukt, zorg dat de bestanden zich in %1$s bevinden @@ -521,7 +497,6 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Syncthing is beëindigd - Aanmaken van configuratiebestand mislukt Camera @@ -621,5 +596,4 @@ Als je problemen tegenkomt, meld ze dan via GitHub. Bladeren Geen onderliggende map geselecteerd Apparaat-ID delen met - - + diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index e6100886..91cb7c5b 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -12,10 +12,6 @@ Velkommen til Synchting for Android Feil - - - - Legg til mappe @@ -209,24 +205,10 @@ Skru på WiFi for å velje nettverk. - Bruk avansert mappeveljar - - Vel kva mappe som helst for synkronisering - Køyr Syncthing som superbrukar Dette er ein ustabil funksjon som kan forårsake problem med Syncthing og med din eining. Hvis det oppstår problem kan du bli nøydd til å installere Syncthing på nytt. - Varsling - - Vel varslingstype - - - Normal - Låg prioritet - Ingen - - Einingsnamn Lytteadresse for synkroniseringsprotokoll @@ -251,23 +233,18 @@ Hald prosessoren vaken medan Syncthing køyrer - Bruk denne innstillinga om du opplever uventa avkoplingar medan du køyrer på batteri. Dette vil føre til auka batteriforbruk. - Vil du verkeleg eksportere innstillingane? Eksisterande filer vil verte skrivne over. \n\nÅTVARING: Andre appar kan vere i stand til å lese den private nøkkelen frå tryggingskopien, og bruke den til å laste ned eller endre synkroniserte filer. Vil du verkeleg importere ei ny innstillingsfil? Eksisterande filer vil verte skrivne over. - + Innstillingar vart eksportert til %1$s - Importer innstillingar - + Innstillingar vart importerte - - Import av innstillingar mislukkast. Pass på at filene er i %1$s diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index 4c6e467e..e0019553 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -1,114 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index be9479c7..a336f31d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -20,10 +20,6 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Błąd Ignoru - - - - Dodaj katalog @@ -231,7 +227,6 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Warunki działania Zachowanie Ustawienia Syncthing - Kopia zapasowa Diagnozowanie błędów Eksperymentalne @@ -241,18 +236,10 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Respektuj ustawienia oszczędzania energii Androida - Zaawansowane wybieranie katalogów - - Wskazuje dowolny katalog na urządzeniu do zsynchronizowania - Synchronizuje zawartość z uprawnieniami użytkownika Superuser To jest niestabilna funkcja, która może sprawiać problemy z Syncthing i urządzeniami. W przypadku napotkania błędów możliwe, że niezbędne będzie przeinstalowanie programu. - Powiadomienie - - Wybiera rodzaj powiadomienia - Język Zmień język aplikacji @@ -297,8 +284,6 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Utrzymywanie wybudzonego CPU podczas działania - Używaj, jeśli doświadczasz nieoczekiwanych rozłączeń w trakcie działania na baterii. Spowoduje to zwiększone jej zużycie. - Korzystanie z Tor Użyj starego mechanizmu haszowania @@ -311,15 +296,12 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Zaimportować nowe ustawienia? Istniejące pliki zostaną zastąpione. - + Wyeksportowano ustawienia do %1$s - Importuj ustawienia - + Zaimportowano ustawienia - - Nie udało się zaimportować ustawień. Proszę upewnić się, że pliki znajdują się w położeniu %1$s. @@ -459,7 +441,6 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Syncthing jest wyłączony - Nie udało się stworzyć pliku konfiguracyjnego Kamera @@ -556,5 +537,4 @@ Proszę zgłaszać napotkane błędy programu za pośrednictwem serwisu Github.< Przeglądaj Żaden podfolder nie został wybrany Udostępnij ID urządzenia - - + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 13b2af42..241de990 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -21,10 +21,6 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.Erro Ignorar - - - - Adicionar pasta @@ -245,7 +241,6 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.Condições de execução Comportamento Opções do Syncthing - Backup Depuração Configurações experimentais @@ -260,24 +255,10 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.Honrar a configuração de economia de bateria do Android - Usar seletor de pasta avançado - - Selecione qualquer pasta do dispositivo para sincronização - Executar como Superusuário Este é um recurso instável que pode causar problemas com o Syncthing e seu dispositivo. Caso você encontre problemas, pode ser necessária a reinstalação do Syncthing. - Notificação - - Escolha o tipo da notificação - - - Normal - Baixa prioridade - Nenhuma - - Idioma Alterar o idioma do aplicativo @@ -324,8 +305,6 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.Conecte por um proxy Manter a CPU acordada - Marque esta opção se você observar desconexões inesperadas enquanto a bateria do dispositivo não está sendo carregada. Isto resultará em maior uso da bateria. - Usar Tor Force todo o tráfego através do Tor para aumentar privacidade. Orbot é necessário. Desabilita opções de proxy. @@ -356,15 +335,12 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github. Quer mesmo importar uma nova configuração? Arquivos existentes serão sobrescritos. - + A configuração foi salva em %1$s - Importar configuração - + A configuração foi importada - - A importação falhou. Verifique se os arquivos estão em %1$s @@ -501,7 +477,6 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.O Syncthing está desabilitado - Não foi possível criar o arquivo de configuração Câmera @@ -600,5 +575,4 @@ Por favor, nos avise sobre quaisquer problemas que você encontrar via Github.Navegar Nenhuma subpasta selecionada Compartilhe ID do dispositivo com - - + diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index ee915626..4062f761 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -18,10 +18,6 @@ Reporte, através do Github, quaisquer problemas que encontre, por favor.Continuar Exemplo Erro - - - - Adicionar pasta @@ -221,7 +217,6 @@ Reporte, através do Github, quaisquer problemas que encontre, por favor.Condições de execução Comportamento Opções do Syncthing - Cópia de segurança Depuração Experimental @@ -230,24 +225,10 @@ Reporte, através do Github, quaisquer problemas que encontre, por favor.Ligue o WiFi para seleccionar redes. - Usar selector de pasta avançado - - Seleccione qualquer pasta no dispositivo para sincronizar - Correr o Syncthing como superutilizador Esta é uma funcionalidade instável que pode causar problemas com o Syncthing e com o seu dispositivo. Se encontrar problemas, pode ter de reinstalar o Syncthing. - Notificação - - Escolha o tipo de notificação - - - Normal - Baixa prioridade - Nenhuma - - Nome do dispositivo Endereços de escuta do protocolo de sincronização @@ -274,8 +255,6 @@ Reporte, através do Github, quaisquer problemas que encontre, por favor.Manter a CPU acordada enquanto o Syncthing está a correr - Use esta definição se experimentar desconectações inesperadas enquanto estiver a trabalhar com a bateria. Isto irá resultar num aumento do consumo da carga da bateria. - Utilizar o Tor Usar verificação antiga @@ -288,15 +267,12 @@ Reporte, através do Github, quaisquer problemas que encontre, por favor. Quer mesmo importar a sua configuração? Os ficheiros existentes vão ser sobrepostos. - + A configuração foi exportada para %1$s - Importar configuração - + A configuração foi importada - - A importação da configuração falhou, assegure-se que os ficheiros estão em %1$s diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 653ffcbd..23d0b61a 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -23,10 +23,6 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Ignoră - - - - Adăugare director @@ -263,7 +259,6 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Condiții de rulare Comportament Opțiuni Syncthing - Copie de rezervă Depanare Experimental @@ -278,24 +273,10 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Se va respecta setarea de economisire a bateriei din Android - Folosește selectorul avansat de directoare - - Alegeți orice director de pe dispozitiv pentru sincronizare - Rulează ca root Aceasta este o funcție instabilă care ar putea cauza probleme atăt Syncthing cât și dispozitivului dumneavoastră. Dacă vă confruntați cu probleme, v-a trebui să reinstalați Syncthing. - Notificare - - Alegeți tipul de notificare - - - Normal - Prioritate mică - Nici una - - Limbă Alegeți limba de afișat în aplicație @@ -361,8 +342,6 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Ține procesorul activ când rulează - Folosiți această setare dacă vă confruntați cu deconectări neașteptate atunci când dispozitivul se alimentează de la baterie. Această opțiune poate duce la o creștere a consumului bateriei. - Folosește Tor Forțează tot traficul prin rețeaua Tor pentru a spori confidențialitatea. Necesită aplicația Orbot. Dezactivează opțiunile proxy. @@ -393,15 +372,12 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Chiar doriți să importați o configurație nouă? Fișierele existente vor fi suprascrise. - + Configurația a fost exportată în %1$s - Importă configurația - + Configurația a fost importată - - Importarea configurației a eșuat, asigurați-vă că fișierele sunt în %1$s @@ -556,7 +532,6 @@ Vă rugăm să raportați orice problemă întâlniți, prin intermediul GitHub. Syncthing a fost închis - Creerea fișierului de configurare a eșuat Un fișier de configurare esențial pentru această operație lipsește @@ -679,5 +654,4 @@ atunci când sunt înlocuite sau șterse de către Syncthing. Versiunile sunt ș Navighează Nu este selectat nici un subdirector Partajează ID dispozitiv cu - - + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 128b1346..332c1254 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -21,10 +21,6 @@ Ошибка Игнорировать - - - - Добавить папку @@ -247,7 +243,6 @@ Условия выполнения Поведение Настройки устройства - Резервная копия Отладка Экспериментальное @@ -262,24 +257,10 @@ Учитывать настройки энергосбережения Android - Использовать продвинутый выбор папок - - Выберите любую папку на устройстве для синхронизации - Запуск Syncthing с рут-правами Это нестабильная опция, которая может вызвать проблемы как с Syncthing так и с вашим устройством. Если вы столкнетесь с проблемами, переустановите Syncthing. - Уведомление - - Выбор метода уведомления - - - Нормально - Низкий - Никогда - - Язык Изменить язык приложения @@ -326,8 +307,6 @@ Подсоединиться через прокси Поддерживать CPU включенным, пока Syncthing работает - Используйте эту опцию, если у вас происходят потери соединения при работе от батареи. Эта опция увеличит расход заряда батареи. - Использовать Tor Для дополнительной приватности перенаправлять весь трафик через Tor. Требует наличия Orbot. Отключает опции прокси. @@ -358,15 +337,12 @@ Действительно хотите импортировать новую конфигурацию? Существующие файлы будут перезаписаны. - + Настройки экспортированы в %1$s - Импорт настроек - + Настройки импортированы - - Неудачное импортирование настроек, убедитесь что файлы находятся в %1$s @@ -522,7 +498,6 @@ Syncthing выключен - Ошибка при создании файла конфигурации Камера @@ -622,5 +597,4 @@ Обзор Подпапка не выбрана Поделиться ID устройства - - + diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a0897cd3..84ad58e7 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -12,10 +12,6 @@ Víta Vás Syncthing pre Android Chyba - - - - Pridať Adresár @@ -189,22 +185,8 @@ Nastavenia Syncthing - Použiť rozšírený dialóg pre volbu adresára - - Vyberte ľubovolný adresár pre synchronizáciu - Spúšťať Syncthing s root oprávneniami - Notifikácie - - Zvolte si druh notifikácií - - - Normálne - S nízkou prioritou - Žiadne - - Názov Zariadenia Adresa pre Sync Protokol @@ -226,15 +208,12 @@ Naozaj chcete importova konfiguráciu? Existujúce súbory budú prepísané. - + Konfigurácia bola exportovaná do %1$s - Importovať Konfiguráciu - + Konfigurácia bola importovaná - - Import konfigurácie zlyhal. Prosím, overte, že sú súbory dostupné v %1$s diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 00000000..e0019553 --- /dev/null +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 9f5d74e8..90ed9c04 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -23,10 +23,6 @@ Vänligen rapportera eventuella problem du stöter på via Github. Ignorera - - - - Lägg till mapp @@ -262,7 +258,6 @@ Vänligen rapportera eventuella problem du stöter på via Github. Körvillkor Beteende Syncthing alternativ - Säkerhetskopiera Felsök Experimentell @@ -277,24 +272,10 @@ Vänligen rapportera eventuella problem du stöter på via Github. Respektera Android-batterisparinställning - Använd avancerad mappväljare - - Välj någon mapp på enheten för synkronisering - Kör som superanvändare Detta är en instabil funktion som kan orsaka problem med Syncthing och med din enhet enhet. Om du stöter på problem, kan du behöva installera om Syncthing. - Avisering - - Välj aviseringstypen - - - Normal - Låg prioritet - Ingen - - Språk Ändra appens språk @@ -358,8 +339,6 @@ Vänligen rapportera eventuella problem du stöter på via Github. Håll CPU:n vaken medan Syncthing körs - Använd den här inställningen om du får oväntade frånkopplingar under batteridrift. Detta kommer att resultera i ökad batteriförbrukning. - Använd Tor Tvinga all trafik genom Tor för ökad integritet. Kräver Orbot. Inaktiverar proxyalternativ. @@ -390,15 +369,12 @@ Vänligen rapportera eventuella problem du stöter på via Github. Vill du verkligen importera en ny konfiguration? Befintliga filer kommer att skrivas över. - + Konfiguration exporterades till %1$s - Importera konfiguration - + Konfigurationen importerades - - Konfigurations importering misslyckades, se till att filerna finns i %1$s @@ -550,7 +526,6 @@ Vänligen rapportera eventuella problem du stöter på via Github. Syncthing avslutades - Misslyckades med att skapa konfigurationsfil En konfigurationsfil avgörande för drift saknas @@ -661,5 +636,4 @@ Vänligen rapportera eventuella problem du stöter på via Github. Bläddra Ingen undermapp är vald Dela enhetens ID med - - + diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d63fa9c7..fd84cf68 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -18,10 +18,6 @@ Eğer herhangi bir sorunla karşılaşırsan Github aracılığıyla bildir.Devam et Hata - - - - Klasör Ekleme @@ -218,7 +214,6 @@ Eğer herhangi bir sorunla karşılaşırsan Github aracılığıyla bildir.Çalışma Koşulları Davranış Syncthing Seçenekleri - Yedekleme Hata ayıklama Deneysel @@ -227,24 +222,10 @@ Eğer herhangi bir sorunla karşılaşırsan Github aracılığıyla bildir.Ağ seçmek için lütfen kablosuz bağlantınızı açın. - Gelişmiş Klasör Seçici kullan - - Eşzamanlama yapmak için aygıttan herhangi bir klasör seçin - Syncthing\'i Superuser/Ayrıcalıklı Kullanıcı olarak Çalıştır Bu, Syncting ve aygıtınız ile sorunlara neden olabilecek kararsız bir özelliktir. Eğer sorun yaşarsanız, Syncthing\'i yeniden yüklemeniz gerekebilir. - Bildirimler - - Bildirim türünü seç - - - Olağan - Düşük Öncelikli - Hiçbiri - - Aygıt Adı Eşzamanlama Protokolü Dinleme/Bağlanma Adresleri @@ -269,8 +250,6 @@ Eğer herhangi bir sorunla karşılaşırsan Github aracılığıyla bildir.Syncthing çalışırken CPU\'yu uyanık tut - Eğer batarya üzerinde çalışırken beklenmedik kopmalar yaşıyorsanız bu ayarı kullanın. Bu artırılmış batarya tüketimiyle sonuçlanacak. - Tor kullan @@ -279,15 +258,12 @@ Eğer herhangi bir sorunla karşılaşırsan Github aracılığıyla bildir. Yeni yapılandırmayı gerçekten içe aktarmak istiyor musun? Var olan dosyaların üzerine yazılacak. - + Yapılandırma şurada dışa aktarıldı: %1$s - Yapılandırmayı İçe Aktar - + Yapılandırma içe aktarıldı - - Yapılandırma içe aktarılamadı, dosyaların %1$s içinde olduğundan emin olun diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index ea7122e2..b0657db1 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -10,10 +10,6 @@ Продовжити Завершити Помилка - - - - Додати каталог @@ -184,16 +180,6 @@ Будь-ласка, увімкніть Wi-Fi, щоби вибрати мережі Відповідно до налаштувань енергозбереження пристрою в системі - Сповіщення - - Вибрати тип сповіщення - - - Нормальне - Низький пріоритет - Немає - - Мова Змінити мову пристрою @@ -233,14 +219,12 @@ Дійсно бажаєте імпортувати нову конфігурацію? Існуючі файли будуть перезаписані - + Налаштування експортовано в %1$s - Імпортувати налаштування - + Налаштування імпортовано - Змінні оточення diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 3b086299..cefacd3e 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -14,10 +14,6 @@ Lỗi Bỏ qua - - - - Thêm th.mục @@ -206,22 +202,8 @@ Hãy bật WiFi để lựa chọn mạng. - S.dụng trình chọn th.mục nâng cao - - Chọn bất kỳ th.mục nào trên th.bị để đồng bộ - Chạy Syncthing với quyền Superuser - Thông báo - - Chọn dạng thông báo - - - Thông thường - Ưu tiên thấp - Không thông báo - - Tên thiết bị Đồng bộ các đ.chỉ lắng nghe giao thức @@ -242,23 +224,18 @@ Giữ CPU thức khi Syncthing đang chạy - Dùng tuỳ chỉnh này nếu bạn bị mất kết nối bất ngờ khi đang dùng pin. Nó sẽ tiêu thụ nhiều pin hơn. - Có chắc là bạn muốn xuất cấu hình? Các tập tin hiện thời sẽ bị ghi đè.\n\nCẢNH BÁO! Các ứng dụng khác có thể đọc được khoá riêng tư từ vị trí sao lưu và dùng nó để tải về/chỉnh sửa các tập tin đã đồng bộ. Có chắc là bạn muốn nhập cấu hình mới? Các tập tin hiện tại sẽ bị chép đè lên. - + Cấu hình đã được xuất vào %1$s - Nhập cấu hình - + Cấu hình đã được nhập - - Nhập c.hình th.bại, hãy chắc rằng các t.tin nằm trong %1$s diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index b58f972f..cf993e9d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -20,10 +20,6 @@ 错误 忽略 - - - - 添加文件夹 @@ -230,7 +226,6 @@ 运行条件 行为 同步设置 - 备份 调试 实验性 @@ -240,24 +235,10 @@ 遵循 Android 电池省电模式设置 - 使用高级文件夹选择器 - - 可以选择设备上任何文件夹 - Syncthing 运行于超级用户 该项功能不稳定,可能导致您的设备和 Syncthing 出问题。如果遇到了问题,您可能要重新安装 Syncthing。 - 通知 - - 选择通知类型 - - - 常规 - 低优先级 - 隐藏 - - 语言 更改应用语言 @@ -302,8 +283,6 @@ 当 Syncthing 正在运行时保持 CPU 唤醒 - 使用此设置如果您在电池上运行时遇到意外的断开连接。这将会导致电量消耗的增加。 - 使用 Tor 使用传统哈希 @@ -316,15 +295,12 @@ 您确定要导入新配置?会覆盖现有配置。 - + 设置已导出至 %1$s - 导入设置 - + 设置已导入 - - 设置导入失败,请确保文件位于 %1$s @@ -455,7 +431,6 @@ Syncthing 已禁用 - 创建配置文件失败 摄像机 @@ -554,5 +529,4 @@ 浏览 未选中子文件夹 共享设备 ID 与 - - + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index f90a0df1..2f38d887 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -18,10 +18,6 @@ 繼續 完成 錯誤 - - - - 增加資料夾 @@ -226,7 +222,6 @@ 執行條件 行為 Syncthing 選項 - 備份 除錯 實驗性 @@ -236,24 +231,10 @@ 遵守 Android 節省電池設定 - 使用進階的資料夾選擇器 - - 選擇在裝置上的同步資料夾 - 以超級使用者執行 Syncthing 這是不穩定的功能,可能會對 Syncthing 與你的裝置造成問題。如果你遇到問題,你也許需要重新安裝 Syncthing。 - 通知 - - 選擇通知類型 - - - 一般 - 低優先權 - - - 語言 選擇應用程式語言 @@ -298,8 +279,6 @@ 當 Syncthing 正在執行時,保持 CPU 清醒 - 如果在電池操作上遇到斷線,使用這個設定。這可能會造成增加電池消耗量。 - 使用 Tor 使用過時的雜湊 @@ -312,15 +291,12 @@ 你確認要匯入新的設定?已存在的檔案將會被覆蓋。 - + 設定匯出到 %1$s - 匯入設定 - + 設定已匯入 - - 設定匯入失敗,請確認檔案在 %1$s @@ -451,7 +427,6 @@ Syncthing 已經停用 - 無法建立設定檔 相機 @@ -548,5 +523,4 @@ 瀏覽 無子資料夾被選擇 分享裝置識別代碼 - - + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 942e13f3..53c8e4df 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,8 +49,8 @@ Please report any problems you encounter via Github. - Confirm to stop service - For your consideration: You configured Syncthing to run as a service. Therefore it monitors run conditions and syncs at any time in the background when conditions match. You should only stop the service manually if you ran into severe problems. Otherwise, uncheck running as a service in the settings. Would you like to stop the service now until the next device reboot? + Confirm to quit app + For your consideration: You configured the app to start automatically on boot. Therefore it monitors run conditions and syncs at any time in the background when conditions match. You should only quit manually if you run into severe problems. Otherwise, disable \'Start automatically on boot \' in the settings. Would you like to quit now until the device rebooted? Add Folder @@ -349,24 +349,10 @@ Please report any problems you encounter via Github. Start service automatically on boot - Use advanced Folder Picker - - Select any folder on the device for syncing - Run Syncthing as Superuser Running Syncthing as root allows it to write to folders Android normally restricts to be readonly accessed. Use this feature cautious. - Notification - - Choose the notification type - - - Normal - Low Priority - None - - Language Change the app language @@ -625,8 +611,10 @@ Please report any problems you encounter via Github. Phone is not running on battery power. Syncthing is not running as the phone is currently power saving. Syncthing is not running as Android currently has \'Auto-sync data\' disabled. + Syncthing is not allowed to run on mobile data connection. Syncthing is running as mobile data is currently connected. Syncthing is allowed to run on mobile data connection but mobile data isn\'t connected. + Syncthing is not allowed to run on WiFi. Syncthing is allowed to run on WiFi and WiFi is currently connected. Syncthing is allowed to run on WiFi but WiFi isn\'t connected or the phone is in flight mode. Syncthing is allowed to run on metered and non-metered WiFi connections. @@ -637,6 +625,10 @@ Please report any problems you encounter via Github. You enabled \'Run on selected WiFi networks\' in the settings. Android location services are currently turned off. According to Android restrictions, Syncthing cannot determine the current WiFi network name to decide if it should run. Solution: Turn location on and reconnect WiFi. Syncthing is running as you allowed it to run when flight mode is active. + + + No WiFi SSID\'s whitelisted. Please specify some in the settings. + @@ -789,5 +781,9 @@ Please report any problems you encounter via Github. Browse No sub folder is selected Share device ID with + Turn the whitelist on to restrict sync happening only on specified WiFi networks. + Custom sync conditions + Allows you to specify exceptions to the global run conditions. + Specify sync conditions diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d88d22f0..3dc6477e 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -32,6 +32,11 @@ 8dp + +