diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e84e10b..09994a5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:localeConfig="@xml/locales_config"
+ android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
diff --git a/app/src/main/java/com/phpbg/easysync/ui/DavSettingsActivity.kt b/app/src/main/java/com/phpbg/easysync/ui/DavSettingsActivity.kt
index 2a7b17b..1604e3f 100644
--- a/app/src/main/java/com/phpbg/easysync/ui/DavSettingsActivity.kt
+++ b/app/src/main/java/com/phpbg/easysync/ui/DavSettingsActivity.kt
@@ -134,6 +134,10 @@ private fun Preferences(
)
)
Spacer(modifier = Modifier.height(8.dp))
+ if (uiState.settings.url.startsWith("http://", true)) {
+ Text(text = stringResource(R.string.dav_settings_url_insecure), color = MaterialTheme.colorScheme.error)
+ Spacer(modifier = Modifier.height(8.dp))
+ }
TextField(value = uiState.settings.username,
onValueChange = { stateChangeHandler(uiState.settings.copy(username = it)) },
modifier = Modifier.fillMaxWidth(),
diff --git a/app/src/main/java/com/phpbg/easysync/ui/MainActivity.kt b/app/src/main/java/com/phpbg/easysync/ui/MainActivity.kt
index 0272b74..51f92cc 100644
--- a/app/src/main/java/com/phpbg/easysync/ui/MainActivity.kt
+++ b/app/src/main/java/com/phpbg/easysync/ui/MainActivity.kt
@@ -172,7 +172,7 @@ private fun Main(
val davSettingsTitle = stringResource(R.string.dav_settings_title)
if (!showDavStatus.value) {
StatusTitleClickable(
- title = "DAV not configured.",
+ title = stringResource(R.string.home_dav_status_not_configured),
actionTitle = davSettingsTitle,
statusColor = Color.Gray,
statusIcon = Icons.Default.Settings,
@@ -180,7 +180,7 @@ private fun Main(
)
} else if (isDavLoading.value) {
StatusTitleClickable(
- title = "DAV loading.",
+ title = stringResource(R.string.home_dav_status_loading),
actionTitle = davSettingsTitle,
statusColor = Color.Gray,
statusIcon = Icons.Default.Schedule,
@@ -188,7 +188,7 @@ private fun Main(
)
} else if (isDavConnected.value) {
StatusTitleClickable(
- title = "DAV Connected.",
+ title = stringResource(R.string.home_dav_status_connected),
actionTitle = davSettingsTitle,
statusColor = Color.Green,
statusIcon = Icons.Default.CheckCircle,
@@ -196,7 +196,7 @@ private fun Main(
)
} else {
StatusTitleClickable(
- title = "DAV not connected.",
+ title = stringResource(R.string.home_dav_status_not_connected),
actionTitle = davSettingsTitle,
statusColor = Color.Red,
statusIcon = Icons.Default.Cancel,
@@ -207,14 +207,14 @@ private fun Main(
if (hasOptionalPermissions.value) {
StatusTitle(
- title = "Permissions granted",
+ title = stringResource(R.string.home_permissions_granted),
statusColor = Color.Green,
statusIcon = Icons.Default.CheckCircle
)
} else {
StatusTitleClickable(
- title = "Optional permissions missing. ",
- actionTitle = "Fix...",
+ title = stringResource(R.string.home_permissions_missing),
+ actionTitle = stringResource(R.string.home_permissions_action_fix),
statusColor = Color.Yellow,
statusIcon = Icons.Default.Warning,
clickHandler = {
@@ -263,12 +263,12 @@ private fun Main(
.fillMaxWidth()
.background(color = MaterialTheme.colorScheme.surfaceVariant),
verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Center
) {
val modifier = Modifier.height(32.dp)
Column(
modifier = Modifier
.padding(1.dp)
- .fillMaxWidth(0.5f)
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.End
@@ -281,7 +281,7 @@ private fun Main(
}
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
if (jobCount == 0) {
- PrimaryTextLarge(text = "Not")
+ PrimaryTextLarge(text = stringResource(R.string.home_files_not_running_prefix))
} else {
PrimaryTextLarge(text = formatCounter(jobCountPercent) + "%")
}
@@ -290,22 +290,21 @@ private fun Main(
Column(
modifier = Modifier
.padding(1.dp)
- .fillMaxWidth(0.5f)
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.Start
) {
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
- StdText(text = "local files")
+ StdText(text = stringResource(R.string.home_files_local))
}
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
- StdText(text = "synced")
+ StdText(text = stringResource(R.string.home_files_synced))
}
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
if (jobCount == 0) {
- StdText(text = "running")
+ StdText(text = stringResource(R.string.home_sync_running))
} else {
- StdText(text = "syncing")
+ StdText(text = stringResource(R.string.home_sync_syncing))
}
}
}
@@ -325,11 +324,9 @@ private fun Main(
}
fullSyncNowHandler()
}, enabled = syncEnabled) {
- Text(text = "Sync now", style = MaterialTheme.typography.labelLarge)
+ Text(text = stringResource(R.string.home_action_sync_now), style = MaterialTheme.typography.labelLarge)
}
}
-
- // TODO translations
}
// Floating bottom
diff --git a/app/src/main/java/com/phpbg/easysync/ui/SyncSettingsActivity.kt b/app/src/main/java/com/phpbg/easysync/ui/SyncSettingsActivity.kt
index c0c039f..ea7c7a3 100644
--- a/app/src/main/java/com/phpbg/easysync/ui/SyncSettingsActivity.kt
+++ b/app/src/main/java/com/phpbg/easysync/ui/SyncSettingsActivity.kt
@@ -101,24 +101,24 @@ private fun Main(
Title(text = stringResource(R.string.sync_settings_title))
Spacer(modifier = Modifier.height(16.dp))
SwitchSetting(
- title = "Sync on cellular",
- description = "Allow scheduled synchronization on cellular network",
+ title = stringResource(R.string.sync_settings_on_cellular_title),
+ description = stringResource(R.string.sync_settings_on_cellular_desc),
checked = syncOnCellular,
onCheckedChange = syncOnCellularHandler
)
SwitchSetting(
- title = "Sync on battery",
- description = "Allow scheduled synchronization on battery",
+ title = stringResource(R.string.sync_settings_on_battery_title),
+ description = stringResource(R.string.sync_settings_on_battery_desc),
checked = syncOnBattery,
onCheckedChange = syncOnBatteryHandler
)
Spacer(modifier = Modifier.height(16.dp))
- StdText("Conflicts handling")
- Description("If a file is modified on both side:")
+ StdText(stringResource(R.string.sync_settings_conflicts_title))
+ Description(stringResource(R.string.sync_settings_conflicts_desc))
val options = mapOf(
- ConflictStrategy.KEEP_LOCAL.name to "Keep local copy (overwrite remote copy)",
- ConflictStrategy.IGNORE.name to "Ignore file",
- ConflictStrategy.KEEP_REMOTE.name to "Keep remote copy (overwrite local copy)"
+ ConflictStrategy.KEEP_LOCAL.name to stringResource(R.string.sync_settings_conflicts_strategy_keep_local),
+ ConflictStrategy.IGNORE.name to stringResource(R.string.sync_settings_conflicts_strategy_ignore),
+ ConflictStrategy.KEEP_REMOTE.name to stringResource(R.string.sync_settings_conflicts_strategy_keep_remote)
)
RadioGroup(options, selected = conflictStrategy.name, onClick = conflictStrategyHandler)
}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 0986dfe..d8f7fab 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -6,11 +6,25 @@
Passwort ausblenden
Passwort
DAV-Einstellungen
+ Diese URL ist unsicher. Alle Ihre Daten werden von jedem lesbar sein. Erwägen Sie einen Wechsel zu HTTPS.
Benutzername
Der Remote-Ordner ist nicht leer. Alle Dateien werden heruntergeladen und mit Ihrem Gerät synchronisiert. Trotzdem speichern?
Speichern
Trotzdem speichern
Passwort anzeigen
+ Jetzt synchronisieren
+ DAV verbunden.
+ DAV wird geladen.
+ DAV nicht konfiguriert.
+ DAV nicht verbunden.
+ lokale Dateien
+ Nicht
+ synchronisiert
+ Berechtigungen erteilt
+ Optionale Berechtigungen fehlen.
+ Beheben…
+ läuft
+ synchronisiert
Berechtigungen
Um Ihre Dateien zu synchronisieren, benötigen wir vollen Zugriff auf Ihre Dateien. Gehen Sie zu den Einstellungen, um die Berechtigung zu aktivieren
Dateieinstellungen
@@ -28,5 +42,14 @@
Weiter
Synchronisationseinstellungen
Synchronisationseinstellungen
+ Konfliktbehandlung
+ Wenn eine Datei auf beiden Seiten geändert wurde:
+ Lokale Kopie behalten (Überschreibe die entfernte Kopie)
+ Datei ignorieren
+ Entfernte Kopie behalten (Überschreibe die lokale Kopie)
+ Synchronisieren bei Batteriebetrieb
+ Geplante Synchronisierung bei Batteriebetrieb erlauben
+ Synchronisieren über Mobilfunknetz
+ Geplante Synchronisierung über das Mobilfunknetz erlauben
Über, Hilfe
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index b7ab152..5c6e44c 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -10,7 +10,21 @@
Masquer le mot de passe
Sauvegarder quand même ?
Afficher le mot de passe
+ Synchroniser
+ DAV Connecté.
+ Connexion DAV en cours.
+ DAV non configuré.
+ DAV non connecté.
+ fichiers locaux
+ En
+ synchronisé
+ Permissions accordées
+ Permissions optionnelles manquantes.
+ Corriger…
+ attente
+ en cours
Paramètres DAV
+ Cette URL n\'est pas sécurisée. Vos données pourront être interceptées. Vous devriez utiliser HTTPS.
Permissions
Pour fonctionner l\'application doit accéder à tous vos fichiers. Cliquez sur \"Suivant\" pour autoriser l\'accès.
Suivant
@@ -28,5 +42,14 @@
Suivant
Paramètres de synchronisation
Paramètres de synchronisation
+ Conflits
+ Si un fichier est modifié des deux côtés:
+ Garder la copie locale (écraser la distante)
+ Ignorer
+ Garder la copie distante (écraser la locale)
+ Sur batterie
+ Autoriser la synchronisation quand le téléphone est sur batterie
+ Sur réseau mobile
+ Autoriser la synchronisation quand le téléphone est sur le réseau mobile
A propos, aide
\ No newline at end of file
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 48d6b35..3246b88 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -5,11 +5,25 @@
Скрыть пароль
Пароль
Настройки DAV
+ Этот URL-адрес небезопасен. Все ваши данные будут доступны для чтения кем либо. Подумайте о переходе на HTTPS.
Имя пользователя
Удалённая папка не пуста. Все файлы будут загружены и синхронизированы с вашим устройством. Все равно сохранить?
Сохранить
Сохранить всё равно
Отобразить пароль
+ Синхронизировать сейчас
+ DAV подключён.
+ DAV загружается.
+ DAV не настроен.
+ DAV не подключен.
+ локальные файлы
+ Не
+ синхронизированы
+ Разрешения предоставлены
+ Отсутствуют необязательные разрешения.
+ Исправить…
+ выполняется
+ синхронизация
Разрешения
Для синхронизации ваших файлов нам необходим полный доступ к вашим файлам. Зайдите в настройки, чтобы включить разрешение
Настройки файлов
@@ -27,5 +41,14 @@
Далее
Настройки синхронизации
Настройки синхронизации
+ Разрешение конфликтов
+ Если файл изменен на обеих сторонах:
+ Сохранить локальную копию (перезаписать удаленную копию)
+ Игнорировать файл
+ Сохранить удаленную копию (перезаписать локальную копию)
+ Синхронизация при работе от батареи
+ Разрешить запланированную синхронизацию при работе от батареи
+ Синхронизация по мобильному интернету
+ Разрешить запланированную синхронизацию по мобильному интернету
О приложении, помощь
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 81b7ff1..79ad368 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -7,11 +7,25 @@
Hide password
Password
DAV Settings
+ This URL is insecure. All your data will be readable by anyone. Consider switching to HTTPS.
Username
Remote folder is not empty. All files will be downloaded and synced with your device. Save anyway?
Save
Save anyway
Show password
+ Sync now
+ DAV Connected.
+ DAV loading.
+ DAV not configured.
+ DAV not connected.
+ local files
+ Not
+ synced
+ Permissions granted
+ Optional permissions missing.
+ Fix…
+ running
+ syncing
Permissions
In order to synchronize your files we need full access to your files. Go to settings to enable the permission
File settings
@@ -29,5 +43,14 @@
Next
Synchronization settings
Synchronization settings
+ Conflicts handling
+ If a file is modified on both side:
+ Keep local copy (overwrite remote file)
+ Ignore file
+ Keep remote copy (overwrite local file)
+ Sync on battery
+ Allow scheduled synchronization on battery
+ Sync on cellular
+ Allow scheduled synchronization on cellular network
About, help
\ No newline at end of file
diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..8879b90
--- /dev/null
+++ b/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/readme.md b/readme.md
index af79725..8c428ec 100644
--- a/readme.md
+++ b/readme.md
@@ -66,6 +66,9 @@ When you configure EasySync you select a specific folder on your DAV server. Thi
### Changes on DAV side are not immediately reflected
In order to preserve battery we cannot detect quickly DAV changes. If you need immediate sync use "Sync now" button on home screen.
+### Use a self-signed or a custom certificate
+You can add your own trusted certificate in android `Settings` > `Encryption and Credentials`
+
## Supported Android phones
* From Android 8 to latest releases
* Huawei phones may kill the app in background, be warned. These tips will help you:
@@ -74,7 +77,9 @@ In order to preserve battery we cannot detect quickly DAV changes. If you need i
## Supported DAV servers
It should work with any DAV compliant server.
-* Nextcloud / owncloud
+* Nextcloud / owncloud (full support: preserves file creation timestamps)
+* nginx (basic support: does not preserve file creation timestamps, no etag support)
+* apache (basic support: does not preserve file creation timestamps)
* *add your server here*
## Sync is slow on Nextcloud