From 757c01c186617250d1fc0d918630e2226eceb38d Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 13 Sep 2022 22:10:06 +0200 Subject: [PATCH 01/49] Update dependencies (including ical4android to address Kiev/Kyiv bug) See https://github.com/bitfireAT/davx5-ose/discussions/133 --- app/build.gradle | 5 +++-- ical4android | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 028f6e2c0..893f24e2a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -107,7 +107,7 @@ dependencies { implementation "com.google.dagger:hilt-android:${versions.hilt}" kapt "com.google.dagger:hilt-android-compiler:${versions.hilt}" - implementation 'androidx.appcompat:appcompat:1.5.0' + implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'androidx.browser:browser:1.4.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' @@ -138,7 +138,8 @@ dependencies { implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" implementation "com.squareup.okhttp3:okhttp-brotli:${versions.okhttp}" implementation "com.squareup.okhttp3:logging-interceptor:${versions.okhttp}" - implementation 'commons-io:commons-io:2.8.0' // don't update until API level 26 (Android 8) is the minimum API (DAVx5#130) + //noinspection GradleDependency - don't update until API level 26 (Android 8) is the minimum API [https://github.com/bitfireAT/davx5/issues/130] + implementation 'commons-io:commons-io:2.8.0' //noinspection GradleDependency - dnsjava 3+ needs Java 8/Android 7 implementation 'dnsjava:dnsjava:2.1.9' //noinspection GradleDependency diff --git a/ical4android b/ical4android index 2c31b0e88..238a3f255 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit 2c31b0e8860efaa7ba5ec53b244b48463b9cd694 +Subproject commit 238a3f25511d00559672f5f9e94d2afad8c19a18 -- GitLab From c517c9c3b5b91e016cc3b154ec11e04e42f5e4f5 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 13 Sep 2022 22:34:20 +0200 Subject: [PATCH 02/49] Bump version to 4.2.3.4-rc1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 893f24e2a..fc80ccc75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402030300 - versionName '4.2.3.3' + versionCode 402030400 + versionName '4.2.3.4-rc1' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() -- GitLab From e3c44f2e50bbf03191ce664af9522b87f9a9a9bd Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Mon, 19 Sep 2022 16:31:20 +0200 Subject: [PATCH 03/49] Update ical4android (enable relaxed valiation of email addresses); bump version to 4.2.3.4-rc.2 --- app/build.gradle | 4 ++-- ical4android | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fc80ccc75..c362c8996 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402030400 - versionName '4.2.3.4-rc1' + versionCode 402030401 + versionName '4.2.3.4-rc.2' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() diff --git a/ical4android b/ical4android index 238a3f255..86e0d7ccf 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit 238a3f25511d00559672f5f9e94d2afad8c19a18 +Subproject commit 86e0d7ccf54caca48c361b2dd27199ecac5149f4 -- GitLab From d4eaa0718ab90b9276f8bf1a0e8c6ef4a9ddbd6b Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Mon, 19 Sep 2022 16:36:52 +0200 Subject: [PATCH 04/49] Fetch translations from Transifex --- app/src/main/res/values-ca/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 637d032ee..919581326 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -47,7 +47,7 @@ No hi ha cap mercat d\'aplicacions disponible No necessito suport per les tasques.* Programari de codi obert - Ens alegra saber que utilitzes %s, que es programari de codi obert. El desenvolupament, manteniment i suport requereixen un gran treball. Si us plau, considera contribuir (hi ha moltes formes) o realitzar una donació. Seria molt apreciat! + Ens alegra saber que utilitzes %s, que és programari de codi obert. El desenvolupament, manteniment i suport requereixen un gran treball. Si us plau, considera contribuir (hi ha moltes formes) o realitzar una donació. Seria molt apreciat! Com contribuir/donar No mostrar en un futur proper diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3dc8a1c11..71c2196d4 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -5,6 +5,8 @@ La cuenta (ya) no existe Agenda DAVx⁵ Agendas + Eliminar + Cancelar Este campo es requerido Ayuda Administrar cuentas @@ -396,6 +398,8 @@ Contraseña Agregar montaje No hay un servicio WebDAV en esta URL + Eliminar punto de montaje + Los detalles de la conexión se perderán pero ningún archivo será eliminado. Accediendo al fichero WebDAV Descargando el fichero WebDAV Subiendo fichero WebDAV -- GitLab From e2c2e566b929d045179cd511bc44fde997453d9e Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 20 Sep 2022 18:49:05 +0200 Subject: [PATCH 05/49] Bump version to 4.2.3.4 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c362c8996..d859db939 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402030401 - versionName '4.2.3.4-rc.2' + versionCode 402030402 + versionName '4.2.3.4' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() -- GitLab From a7fcc087bc09ed92e0de5ac377c001b8941e1adb Mon Sep 17 00:00:00 2001 From: Sandelinos <26635624+Sandelinos@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:32:58 +0300 Subject: [PATCH 06/49] Add monochrome icon (#151) --- app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 476888c8a..f14eb8714 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -3,4 +3,5 @@ + -- GitLab From 8ff90954cd32d2ca62e27523b81bd499a9bcc0a3 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Thu, 22 Sep 2022 20:53:50 +0200 Subject: [PATCH 07/49] Don't run AccountsUpdatedListener while account is being renamed Don't run AccountsUpdatedListener while account is being renamed (closes bitfireAT/davx5#135) --- .../syncadapter/AccountsUpdatedListener.kt | 18 ++++++++++++++++- .../ui/account/RenameAccountFragment.kt | 20 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountsUpdatedListener.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountsUpdatedListener.kt index 68804cb70..03caa3f1b 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountsUpdatedListener.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountsUpdatedListener.kt @@ -23,6 +23,7 @@ import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import java.util.concurrent.Semaphore import java.util.logging.Level import javax.inject.Singleton @@ -44,6 +45,13 @@ class AccountsUpdatedListener private constructor( fun appDatabase(): AppDatabase } + /** + * This mutex (semaphore with 1 permit) will be acquired by [onAccountsUpdated]. So if you + * want to postpone [onAccountsUpdated] execution because you're modifying accounts non-transactionally, + * you can acquire the mutex by yourself. Don't forget to release it as soon as you're done. + */ + val mutex = Semaphore(1) + fun listen() { val accountManager = AccountManager.get(context) @@ -56,13 +64,21 @@ class AccountsUpdatedListener private constructor( * * 1. Remove related address book accounts. * 2. Remove related service entries from the [AppDatabase]. + * + * Before the accounts are cleaned up, the [mutex] is acquired. + * After the accounts are cleaned up, the [mutex] is released. */ @AnyThread override fun onAccountsUpdated(accounts: Array) { /* onAccountsUpdated may be called from the main thread, but cleanupAccounts requires disk (database) access. So we launch it in a separate thread. */ CoroutineScope(Dispatchers.Default).launch { - cleanupAccounts(context, accounts) + try { + mutex.acquire() + cleanupAccounts(context, accounts) + } finally { + mutex.release() + } } } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt index ca8c39859..b45c2c5ec 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt @@ -36,6 +36,7 @@ import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.resource.LocalAddressBook import at.bitfire.davdroid.resource.LocalTaskList import at.bitfire.davdroid.settings.AccountSettings +import at.bitfire.davdroid.syncadapter.AccountsUpdatedListener import at.bitfire.ical4android.TaskProvider import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint @@ -105,6 +106,7 @@ class RenameAccountFragment: DialogFragment() { @HiltViewModel class Model @Inject constructor( @ApplicationContext val context: Context, + val accountsUpdatedListener: AccountsUpdatedListener, val db: AppDatabase ): ViewModel() { @@ -129,11 +131,27 @@ class RenameAccountFragment: DialogFragment() { val accountManager = AccountManager.get(context) try { + /* https://github.com/bitfireAT/davx5/issues/135 + Take AccountsUpdatedListenerLock so that the AccountsUpdateListener doesn't run while we rename the account + because this can cause problems when: + 1. The account is renamed. + 2. The AccountsUpdateListener is called BEFORE the services table is updated. + → AccountsUpdateListener removes the "orphaned" services because they belong to the old account which doesn't exist anymore + 3. Now the services would be renamed, but they're not here anymore. */ + accountsUpdatedListener.mutex.acquire() + accountManager.renameAccount(oldAccount, newName, { if (it.result?.name == newName /* success */) viewModelScope.launch(Dispatchers.Default + NonCancellable) { onAccountRenamed(accountManager, oldAccount, newName, syncIntervals) - } + + // release AccountsUpdatedListener mutex at the end of this async coroutine + accountsUpdatedListener.mutex.release() + } else + // release AccountsUpdatedListener mutex now + accountsUpdatedListener.mutex.release() + + }, null) } catch (e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rename account", e) -- GitLab From fbbf2a6b07bbaefcdd291c35e66e61612402d2fb Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 23 Sep 2022 12:59:52 +0200 Subject: [PATCH 08/49] Add calendar and contacts provider to manifest/queries (for increased compatibility with apps like Huawei calendar) --- app/src/main/AndroidManifest.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 957d80859..da80a6293 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -284,6 +284,11 @@ + + + + -- GitLab From fc819eb001f44cb4742f6a866da873e32537fe71 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 27 Sep 2022 11:33:07 +0200 Subject: [PATCH 09/49] Update README - closes #153 - closes #152 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb83a4164..91090506a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ DAVx⁵ is licensed under the [GPLv3 License](LICENSE). News and updates: [@davx5app](https://twitter.com/davx5app) on Twitter -**Help, discussion, feature requests, bug reports: [DAVx⁵ forums](https://www.davx5.com/forums)** +**Help, feature requests, bug reports: [DAVx⁵ discussions](https://github.com/bitfireAT/davx5-ose/discussions)** Parts of DAVx⁵ have been outsourced into these libraries: @@ -36,7 +36,7 @@ USED THIRD-PARTY LIBRARIES The most important libraries which are used by DAVx⁵ (alphabetically): -* [dnsjava](http://www.xbill.org/dnsjava/) – [BSD License](http://www.xbill.org/dnsjava/dnsjava-current/LICENSE) -* [ez-vcard](https://github.com/mangstadt/ez-vcard) – [New BSD License](http://opensource.org/licenses/BSD-3-Clause) -* [iCal4j](https://github.com/ical4j/ical4j) – [New BSD License](http://sourceforge.net/p/ical4j/ical4j/ci/default/tree/LICENSE) +* [dnsjava](https://github.com/dnsjava/dnsjava) – [BSD License](https://github.com/dnsjava/dnsjava/blob/master/LICENSE) +* [ez-vcard](https://github.com/mangstadt/ez-vcard) – [New BSD License](https://github.com/mangstadt/ez-vcard/blob/master/LICENSE) +* [iCal4j](https://github.com/ical4j/ical4j) – [New BSD License](https://github.com/ical4j/ical4j/blob/develop/LICENSE.txt) * [okhttp](https://square.github.io/okhttp) – [Apache License, Version 2.0](https://square.github.io/okhttp/#license) -- GitLab From f5b08b60bf286ff0d01952cbeb7cbca12958c284 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Mon, 26 Sep 2022 14:17:59 +0200 Subject: [PATCH 10/49] Update ical4j (handle NPE when time zone is known to Android but not to ical4j) --- ical4android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ical4android b/ical4android index 86e0d7ccf..e88078548 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit 86e0d7ccf54caca48c361b2dd27199ecac5149f4 +Subproject commit e880785483f5e2e488982206cdaf1842e43dc36b -- GitLab From 8a7f51b7055f9c0878908b716059ea23a3a8c7cf Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 27 Sep 2022 11:39:14 +0200 Subject: [PATCH 11/49] Update dependencies, compile SDK level, build tools, gradle plugin --- app/build.gradle | 10 +++++----- build.gradle | 4 ++-- cert4android | 2 +- ical4android | 2 +- vcard4android | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d859db939..47e3f0fec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' android { - compileSdkVersion 32 - buildToolsVersion '32.0.0' + compileSdkVersion 33 + buildToolsVersion '33.0.0' defaultConfig { applicationId "at.bitfire.davdroid" @@ -101,7 +101,7 @@ dependencies { implementation project(':vcard4android') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' implementation "com.google.dagger:hilt-android:${versions.hilt}" @@ -111,8 +111,8 @@ dependencies { implementation 'androidx.browser:browser:1.4.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.fragment:fragment-ktx:1.5.2' + implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.fragment:fragment-ktx:1.5.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.paging:paging-runtime-ktx:3.1.1' diff --git a/build.gradle b/build.gradle index 9ca95659b..f51033204 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { aboutLibraries: '8.9.4', appIntro: '6.2.0', dav4jvm: 'c61e4b0c80a5a8de1df99b4997445bb323d3ea3d', - hilt: '2.43.2', + hilt: '2.44', kotlin: '1.7.10', okhttp: '4.10.0', // latest Apache Commons versions that don't require Java 8 (Android 7) @@ -29,7 +29,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "com.google.dagger:hilt-android-gradle-plugin:${versions.hilt}" classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${versions.aboutLibraries}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" diff --git a/cert4android b/cert4android index 7814052ea..eb47c00cb 160000 --- a/cert4android +++ b/cert4android @@ -1 +1 @@ -Subproject commit 7814052eaf3072ad2c8ed29606cc9f18c3b7921d +Subproject commit eb47c00cb05fe5d27e8640444cc60aa7c271b47a diff --git a/ical4android b/ical4android index e88078548..cfd553df5 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit e880785483f5e2e488982206cdaf1842e43dc36b +Subproject commit cfd553df575eb18b0acf51e9ddf1f11bc2b14e37 diff --git a/vcard4android b/vcard4android index 986ab0830..18017a475 160000 --- a/vcard4android +++ b/vcard4android @@ -1 +1 @@ -Subproject commit 986ab08307bf5e394ef051d3c6146f6a3b292519 +Subproject commit 18017a475c5e7c9dd6fbc5d5f222cbd2744b81be -- GitLab From 2b16cd6365d0773572ef4e37a2d5ff8ac747ce64 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 27 Sep 2022 12:04:53 +0200 Subject: [PATCH 12/49] Lint --- app/build.gradle | 5 +- app/src/androidTest/AndroidManifest.xml | 3 +- app/src/main/AndroidManifest.xml | 4 +- .../at/bitfire/davdroid/db/AppDatabase.kt | 2 +- .../davdroid/settings/AccountSettings.kt | 107 +++++++++--------- .../davdroid/webdav/DavDocumentsProvider.kt | 12 +- 6 files changed, 70 insertions(+), 63 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 47e3f0fec..96427eed4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,6 +51,9 @@ android { dataBinding = true } + // Java namespace for our classes (not to be confused with Android package ID) + namespace 'at.bitfire.davdroid' + flavorDimensions "distribution" productFlavors { ose { @@ -158,7 +161,7 @@ dependencies { androidTestImplementation 'androidx.test:rules:1.4.0' androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3' androidTestImplementation "com.squareup.okhttp3:mockwebserver:${versions.okhttp}" - androidTestImplementation 'io.mockk:mockk-android:1.12.3' + androidTestImplementation 'io.mockk:mockk-android:1.13.1' androidTestImplementation 'junit:junit:4.13.2' testImplementation "com.squareup.okhttp3:mockwebserver:${versions.okhttp}" diff --git a/app/src/androidTest/AndroidManifest.xml b/app/src/androidTest/AndroidManifest.xml index 4e6c77599..986f2f8ad 100644 --- a/app/src/androidTest/AndroidManifest.xml +++ b/app/src/androidTest/AndroidManifest.xml @@ -1,6 +1,5 @@ - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index da80a6293..25664fb8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - @@ -9,6 +8,7 @@ + diff --git a/app/src/main/java/at/bitfire/davdroid/db/AppDatabase.kt b/app/src/main/java/at/bitfire/davdroid/db/AppDatabase.kt index fc56d4c69..228e684de 100644 --- a/app/src/main/java/at/bitfire/davdroid/db/AppDatabase.kt +++ b/app/src/main/java/at/bitfire/davdroid/db/AppDatabase.kt @@ -251,7 +251,7 @@ abstract class AppDatabase: RoomDatabase() { writer.append("$tableName: ") db.query("SELECT COUNT(*) FROM $tableName").use { cursor -> if (cursor.moveToNext()) - writer.append("${cursor.getInt(0)} row(s), data not listed here\n\n") + writer.append("${cursor.getInt(0)} row(s), data not listed here\n\n") } } else { writer.append("$tableName\n") diff --git a/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt b/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt index 8d414c121..48da84423 100644 --- a/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt +++ b/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt @@ -507,67 +507,72 @@ class AccountSettings( * convert legacy unknown properties to the current format. */ private fun update_11_12() { - if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) - context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider -> - // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query - // to the given account! So all extended properties will be processed number-of-accounts times. - val extUri = ExtendedProperties.CONTENT_URI.asSyncAdapter(account) - - provider.query(extUri, arrayOf( - ExtendedProperties._ID, // idx 0 - ExtendedProperties.NAME, // idx 1 - ExtendedProperties.VALUE // idx 2 - ), null, null, null)?.use { cursor -> - while (cursor.moveToNext()) { - val id = cursor.getLong(0) - val rawValue = cursor.getString(2) - - val uri by lazy { - ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id).asSyncAdapter(account) - } - - when (cursor.getString(1)) { - UnknownProperty.CONTENT_ITEM_TYPE -> { - // unknown property; check whether it's a URL - try { - val property = UnknownProperty.fromJsonString(rawValue) - if (property is Url) { // rewrite to MIMETYPE_URL - val newValues = ContentValues(2) - newValues.put(ExtendedProperties.NAME, AndroidEvent.MIMETYPE_URL) - newValues.put(ExtendedProperties.VALUE, property.value) - provider.update(uri, newValues, null, null) - } - } catch (e: Exception) { - Logger.log.log(Level.WARNING, "Couldn't rewrite URL from unknown property to ${AndroidEvent.MIMETYPE_URL}", e) - } + if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) { + val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY) + if (provider != null) + try { + // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query + // to the given account! So all extended properties will be processed number-of-accounts times. + val extUri = ExtendedProperties.CONTENT_URI.asSyncAdapter(account) + + provider.query(extUri, arrayOf( + ExtendedProperties._ID, // idx 0 + ExtendedProperties.NAME, // idx 1 + ExtendedProperties.VALUE // idx 2 + ), null, null, null)?.use { cursor -> + while (cursor.moveToNext()) { + val id = cursor.getLong(0) + val rawValue = cursor.getString(2) + + val uri by lazy { + ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id).asSyncAdapter(account) } - "unknown-property" -> { - // unknown property (deprecated format); convert to current format - try { - val stream = ByteArrayInputStream(Base64.decode(rawValue, Base64.NO_WRAP)) - ObjectInputStream(stream).use { - (it.readObject() as? Property)?.let { property -> - // rewrite to current format + + when (cursor.getString(1)) { + UnknownProperty.CONTENT_ITEM_TYPE -> { + // unknown property; check whether it's a URL + try { + val property = UnknownProperty.fromJsonString(rawValue) + if (property is Url) { // rewrite to MIMETYPE_URL val newValues = ContentValues(2) - newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) - newValues.put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(property)) + newValues.put(ExtendedProperties.NAME, AndroidEvent.MIMETYPE_URL) + newValues.put(ExtendedProperties.VALUE, property.value) provider.update(uri, newValues, null, null) } + } catch (e: Exception) { + Logger.log.log(Level.WARNING, "Couldn't rewrite URL from unknown property to ${AndroidEvent.MIMETYPE_URL}", e) } - } catch(e: Exception) { - Logger.log.log(Level.WARNING, "Couldn't rewrite deprecated unknown property to current format", e) } - } - "unknown-property.v2" -> { - // unknown property (deprecated MIME type); rewrite to current MIME type - val newValues = ContentValues(1) - newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) - provider.update(uri, newValues, null, null) + "unknown-property" -> { + // unknown property (deprecated format); convert to current format + try { + val stream = ByteArrayInputStream(Base64.decode(rawValue, Base64.NO_WRAP)) + ObjectInputStream(stream).use { + (it.readObject() as? Property)?.let { property -> + // rewrite to current format + val newValues = ContentValues(2) + newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) + newValues.put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(property)) + provider.update(uri, newValues, null, null) + } + } + } catch(e: Exception) { + Logger.log.log(Level.WARNING, "Couldn't rewrite deprecated unknown property to current format", e) + } + } + "unknown-property.v2" -> { + // unknown property (deprecated MIME type); rewrite to current MIME type + val newValues = ContentValues(1) + newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) + provider.update(uri, newValues, null, null) + } } } } + } finally { + provider.closeCompat() } - } + } } @Suppress("unused","FunctionName") diff --git a/app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt b/app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt index 87b148239..aba454fa9 100644 --- a/app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt +++ b/app/src/main/java/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt @@ -244,7 +244,7 @@ class DavDocumentsProvider: DocumentsProvider() { val parentUrl = parent.toHttpUrl(db) val folder = DavCollection(client.okHttpClient, parentUrl) - folder.propfind(1, *DAV_FILE_FIELDS) { response, relation -> + folder.propfind(1, *DAV_FILE_FIELDS) { response, relation -> Logger.log.fine("$relation $response") val resource: WebDavDocument = @@ -486,11 +486,11 @@ class DavDocumentsProvider: DocumentsProvider() { if (appendNumber != 0) { val extension: String? = MimeTypeMap.getFileExtensionFromUrl(displayName) - if (extension != null) { - val baseName = safeName.removeSuffix(".$extension") - return "${baseName}_$appendNumber.$extension" - } else - return "${safeName}_$appendNumber" + if (extension != null) { + val baseName = safeName.removeSuffix(".$extension") + return "${baseName}_$appendNumber.$extension" + } else + return "${safeName}_$appendNumber" } else return safeName } -- GitLab From ce3f3b7cc44e85bc6e5b2adad5fb7ded4344f7c8 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 27 Sep 2022 15:32:41 +0200 Subject: [PATCH 13/49] Update vcard4android (disable LABEL generation); version bump to 4.2.4-beta.1 --- app/build.gradle | 4 ++-- vcard4android | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 96427eed4..dcbaff394 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402030402 - versionName '4.2.3.4' + versionCode 402040000 + versionName '4.2.4-beta.1' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() diff --git a/vcard4android b/vcard4android index 18017a475..581eac411 160000 --- a/vcard4android +++ b/vcard4android @@ -1 +1 @@ -Subproject commit 18017a475c5e7c9dd6fbc5d5f222cbd2744b81be +Subproject commit 581eac4117634bf59eba14b69acb8bb1cce95d2a -- GitLab From c635dc8aa3eaf096540efeb6e6f6011fa229a0f4 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Mon, 3 Oct 2022 10:48:36 +0200 Subject: [PATCH 14/49] Add pre-set base URLs --- app/src/main/assets/known-base-urls.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/known-base-urls.txt b/app/src/main/assets/known-base-urls.txt index c25e951c3..0068686a3 100644 --- a/app/src/main/assets/known-base-urls.txt +++ b/app/src/main/assets/known-base-urls.txt @@ -1,5 +1,7 @@ carddav.a1.net aol.com +calendar.dingtalk.com/dav/ +cloud.disroot.org dav.edis.at dav.fruux.com caldav.gmx.net @@ -11,6 +13,7 @@ calendar.mail.ru mailbox.org mailfence.com posteo.de:8443 +dav.runbox.com live.teambox.eu spica.t-online.de caldav.calendar.yahoo.com -- GitLab From 99710ca94e3af4f08809dd05bd54abc6dd14bd5d Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Sat, 8 Oct 2022 18:57:44 +0200 Subject: [PATCH 15/49] Update Manual URL --- .../java/at/bitfire/davdroid/ui/OseAccountsDrawerHandler.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/OseAccountsDrawerHandler.kt b/app/src/main/java/at/bitfire/davdroid/ui/OseAccountsDrawerHandler.kt index dd15c7bfc..fe513b494 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/OseAccountsDrawerHandler.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/OseAccountsDrawerHandler.kt @@ -20,6 +20,7 @@ class OseAccountsDrawerHandler @Inject constructor(): BaseAccountsDrawerHandler( companion object { const val COMMUNITY_URL = "https://github.com/bitfireAT/davx5-ose/discussions" + const val MANUAL_URL = "https://manual.davx5.com" } override fun onNavigationItemSelected(activity: Activity, item: MenuItem) { @@ -42,7 +43,7 @@ class OseAccountsDrawerHandler @Inject constructor(): BaseAccountsDrawerHandler( R.id.nav_manual -> UiUtils.launchUri( activity, - App.homepageUrl(activity).buildUpon().appendPath("manual").build() + Uri.parse(MANUAL_URL) ) R.id.nav_faq -> UiUtils.launchUri( -- GitLab From 31fb7ec190c67f95ab78a05802b26f7377817d46 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 11 Oct 2022 10:09:10 +0200 Subject: [PATCH 16/49] CalDAV/CardDAV UI: replace checkbox by switch (bitfireAT/davx5#143) Closes bitfireAT/davx5#142 --- app/src/main/res/layout/account_caldav_item.xml | 2 +- app/src/main/res/layout/account_carddav_item.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/account_caldav_item.xml b/app/src/main/res/layout/account_caldav_item.xml index a04962941..d39316e49 100644 --- a/app/src/main/res/layout/account_caldav_item.xml +++ b/app/src/main/res/layout/account_caldav_item.xml @@ -23,7 +23,7 @@ android:paddingBottom="4dp" android:orientation="horizontal"> - - Date: Tue, 11 Oct 2022 10:41:39 +0200 Subject: [PATCH 17/49] Use Material switches for preferences --- app/src/main/res/layout/view_preference_switch.xml | 5 +++++ app/src/main/res/values/styles.xml | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 app/src/main/res/layout/view_preference_switch.xml diff --git a/app/src/main/res/layout/view_preference_switch.xml b/app/src/main/res/layout/view_preference_switch.xml new file mode 100644 index 000000000..10733b786 --- /dev/null +++ b/app/src/main/res/layout/view_preference_switch.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b0d9e9e41..fe7350c45 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -55,6 +55,8 @@ @color/secondaryTextColor @color/backgroundColor + + @style/MySwitchPreference + -- GitLab From d2614bd87e7af3daa8fa1ae9e1bad90e3d2d58c3 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 12 Oct 2022 17:29:23 +0200 Subject: [PATCH 18/49] Create an option to pre-select the read-only setting for address books (bitfireAT/davx5#141) * [WIP] add managed restriction to force read-only addressbooks * Honor app-wide read-only address book setting when syncing address books * reflect status of force read-only address books setting in the GUI Co-authored-by: Sunik Kupfer --- .../davdroid/resource/LocalAddressBook.kt | 23 +++++++++++++++---- .../davdroid/settings/DefaultsProvider.kt | 3 ++- .../at/bitfire/davdroid/settings/Settings.kt | 3 +++ .../AddressBooksSyncAdapterService.kt | 21 +++++++++++++++-- .../ui/account/AddressBooksFragment.kt | 21 ++++++++++++++--- .../ui/account/CollectionsFragment.kt | 9 +++++++- 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt index eba09f817..c49a1cbda 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt @@ -46,7 +46,16 @@ open class LocalAddressBook( const val USER_DATA_URL = "url" const val USER_DATA_READ_ONLY = "read_only" - fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, info: Collection): LocalAddressBook { + /** + * Creates a local address book. + * + * @param context app context to resolve string resources + * @param provider contacts provider client + * @param mainAccount main account this address book (account) belongs to + * @param info collection where to take the name and settings from + * @param forceReadOnly `true`: set the address book to "force read-only"; `false`: determine read-only flag from [info] + */ + fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, info: Collection, forceReadOnly: Boolean): LocalAddressBook { val account = Account(accountName(mainAccount, info), context.getString(R.string.account_type_address_book)) val userData = initialUserData(mainAccount, info.url.toString()) Logger.log.log(Level.INFO, "Creating local address book $account", userData) @@ -61,7 +70,7 @@ open class LocalAddressBook( values.put(ContactsContract.Settings.SHOULD_SYNC, 1) values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1) addressBook.settings = values - addressBook.readOnly = !info.privWriteContent || info.forceReadOnly + addressBook.readOnly = forceReadOnly || !info.privWriteContent || info.forceReadOnly return addressBook } @@ -199,7 +208,13 @@ open class LocalAddressBook( return number } - fun update(info: Collection) { + /** + * Updates the address book settings. + * + * @param info collection where to take the settings from + * @param forceReadOnly `true`: set the address book to "force read-only"; `false`: determine read-only flag from [info] + */ + fun update(info: Collection, forceReadOnly: Boolean) { val newAccountName = accountName(mainAccount, info) if (account.name != newAccountName && Build.VERSION.SDK_INT >= 21) { @@ -209,7 +224,7 @@ open class LocalAddressBook( account = future.result } - val nowReadOnly = !info.privWriteContent || info.forceReadOnly + val nowReadOnly = forceReadOnly || !info.privWriteContent || info.forceReadOnly if (nowReadOnly != readOnly) { Constants.log.info("Address book now read-only = $nowReadOnly, updating contacts") diff --git a/app/src/main/java/at/bitfire/davdroid/settings/DefaultsProvider.kt b/app/src/main/java/at/bitfire/davdroid/settings/DefaultsProvider.kt index 3390bba51..9484d41a5 100644 --- a/app/src/main/java/at/bitfire/davdroid/settings/DefaultsProvider.kt +++ b/app/src/main/java/at/bitfire/davdroid/settings/DefaultsProvider.kt @@ -26,7 +26,8 @@ class DefaultsProvider( override val booleanDefaults = mutableMapOf( Pair(Settings.DISTRUST_SYSTEM_CERTIFICATES, false), - Pair(Settings.SYNC_ALL_COLLECTIONS, false) + Pair(Settings.SYNC_ALL_COLLECTIONS, false), + Pair(Settings.FORCE_READ_ONLY_ADDRESSBOOKS, false) ) override val intDefaults = mapOf( diff --git a/app/src/main/java/at/bitfire/davdroid/settings/Settings.kt b/app/src/main/java/at/bitfire/davdroid/settings/Settings.kt index 67599ded1..31d058fcf 100644 --- a/app/src/main/java/at/bitfire/davdroid/settings/Settings.kt +++ b/app/src/main/java/at/bitfire/davdroid/settings/Settings.kt @@ -38,5 +38,8 @@ object Settings { /** whether detected collections are selected for synchronization for default */ const val SYNC_ALL_COLLECTIONS = "sync_all_collections" + + /** whether all address books are forced to be read-only */ + const val FORCE_READ_ONLY_ADDRESSBOOKS = "force_read_only_addressbooks" } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/AddressBooksSyncAdapterService.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/AddressBooksSyncAdapterService.kt index 275ab782c..fed850c1f 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/AddressBooksSyncAdapterService.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/AddressBooksSyncAdapterService.kt @@ -21,6 +21,12 @@ import at.bitfire.davdroid.db.Service import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.resource.LocalAddressBook import at.bitfire.davdroid.settings.AccountSettings +import at.bitfire.davdroid.settings.Settings +import at.bitfire.davdroid.settings.SettingsManager +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.components.SingletonComponent import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import java.util.logging.Level @@ -35,6 +41,15 @@ class AddressBooksSyncAdapterService : SyncAdapterService() { appDatabase: AppDatabase ) : SyncAdapter(context, appDatabase) { + @EntryPoint + @InstallIn(SingletonComponent::class) + interface AddressBooksSyncAdapterEntryPoint { + fun settingsManager(): SettingsManager + } + + val entryPoint = EntryPointAccessors.fromApplication(context, AddressBooksSyncAdapterEntryPoint::class.java) + val settingsManager = entryPoint.settingsManager() + override fun sync(account: Account, extras: Bundle, authority: String, httpClient: Lazy, provider: ContentProviderClient, syncResult: SyncResult) { try { val accountSettings = AccountSettings(context, account) @@ -85,6 +100,8 @@ class AddressBooksSyncAdapterService : SyncAdapterService() { return false } + val forceAllReadOnly = settingsManager.getBoolean(Settings.FORCE_READ_ONLY_ADDRESSBOOKS) + // delete/update local address books for (addressBook in LocalAddressBook.findAll(context, contactsProvider, account)) { val url = addressBook.url.toHttpUrl() @@ -96,7 +113,7 @@ class AddressBooksSyncAdapterService : SyncAdapterService() { // remote CollectionInfo found for this local collection, update data try { Logger.log.log(Level.FINE, "Updating local address book $url", info) - addressBook.update(info) + addressBook.update(info, forceAllReadOnly) } catch (e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rename address book account", e) } @@ -108,7 +125,7 @@ class AddressBooksSyncAdapterService : SyncAdapterService() { // create new local address books for ((_, info) in remoteAddressBooks) { Logger.log.log(Level.INFO, "Adding local address book", info) - LocalAddressBook.create(context, contactsProvider, account, info) + LocalAddressBook.create(context, contactsProvider, account, info, forceAllReadOnly) } } finally { contactsProvider?.closeCompat() diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/AddressBooksFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/AddressBooksFragment.kt index 4a8e2da8b..ff5e8741d 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/AddressBooksFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/AddressBooksFragment.kt @@ -11,6 +11,12 @@ import at.bitfire.davdroid.PermissionUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.AccountCarddavItemBinding import at.bitfire.davdroid.db.Collection +import at.bitfire.davdroid.settings.Settings +import at.bitfire.davdroid.settings.SettingsManager +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.components.SingletonComponent class AddressBooksFragment: CollectionsFragment() { @@ -53,9 +59,18 @@ class AddressBooksFragment: CollectionsFragment() { class AddressBookViewHolder( parent: ViewGroup, accountModel: AccountActivity.Model, - val fragmentManager: FragmentManager + val fragmentManager: FragmentManager, ): CollectionViewHolder(parent, AccountCarddavItemBinding.inflate(LayoutInflater.from(parent.context), parent, false), accountModel) { + @EntryPoint + @InstallIn(SingletonComponent::class) + interface AddressBookViewHolderEntryPoint { + fun settingsManager(): SettingsManager + } + + private val settings = EntryPointAccessors.fromApplication(parent.context, AddressBookViewHolderEntryPoint::class.java).settingsManager() + private val forceReadOnlyAddressBooks = settings.getBoolean(Settings.FORCE_READ_ONLY_ADDRESSBOOKS) // managed restriction + override fun bindTo(item: Collection) { binding.sync.isChecked = item.sync binding.title.text = item.title() @@ -67,12 +82,12 @@ class AddressBooksFragment: CollectionsFragment() { binding.description.visibility = View.VISIBLE } - binding.readOnly.visibility = if (item.readOnly()) View.VISIBLE else View.GONE + binding.readOnly.visibility = if (item.readOnly() || forceReadOnlyAddressBooks) View.VISIBLE else View.GONE itemView.setOnClickListener { accountModel.toggleSync(item) } - binding.actionOverflow.setOnClickListener(CollectionPopupListener(accountModel, item, fragmentManager)) + binding.actionOverflow.setOnClickListener(CollectionPopupListener(accountModel, item, fragmentManager, forceReadOnlyAddressBooks)) } } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt index f4e197b46..b379497ae 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt @@ -226,7 +226,8 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList class CollectionPopupListener( private val accountModel: AccountActivity.Model, private val item: Collection, - private val fragmentManager: FragmentManager + private val fragmentManager: FragmentManager, + private val forceReadOnly: Boolean = false ): View.OnClickListener { override fun onClick(anchor: View) { @@ -244,6 +245,12 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList else isVisible = false } + + if (item.type == Collection.TYPE_ADDRESSBOOK && forceReadOnly) { + // managed restriction "force read-only address books" is active + isChecked = true + isEnabled = false + } } popup.menu.findItem(R.id.delete_collection).isVisible = item.privUnbind -- GitLab From bec9f8bcfb9acec55138c078f7bcd6293615c980 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 14 Oct 2022 23:06:56 +0200 Subject: [PATCH 19/49] Fetch translations from Transifex (including new translations) --- .tx/config | 20 +- app/src/main/assets/translators.json | 2 +- app/src/main/res/values-ar/strings.xml | 15 +- app/src/main/res/values-eu/strings.xml | 4 + app/src/main/res/values-hr/strings.xml | 361 +++++++++++++++ app/src/main/res/values-ko/strings.xml | 418 +++++++++++++++++ app/src/main/res/values-nb/strings.xml | 218 +++++++++ app/src/main/res/values-nl/strings.xml | 4 + app/src/main/res/values-ru/strings.xml | 6 +- app/src/main/res/values-sk/strings.xml | 15 +- app/src/main/res/values-sl/strings.xml | 229 ++++++++++ app/src/main/res/values-sr/strings.xml | 92 +++- app/src/main/res/values-sv/strings.xml | 423 ++++++++++++++++++ app/src/main/res/values-zh-rTW/strings.xml | 143 +++--- .../android/fr-FR/full_description.txt | 5 + .../android/fr-FR/short_description.txt | 1 + .../metadata/android/hr/full_description.txt | 5 + .../metadata/android/hr/short_description.txt | 1 + .../metadata/android/it/full_description.txt | 5 + .../metadata/android/ko/full_description.txt | 5 + .../metadata/android/ko/short_description.txt | 1 + .../metadata/android/ru/full_description.txt | 2 +- .../metadata/android/si/short_description.txt | 1 + .../{sl-SI => sl}/full_description.txt | 0 .../{sl-SI => sl}/short_description.txt | 0 .../metadata/android/sr/full_description.txt | 5 + .../metadata/android/sr/short_description.txt | 1 + .../metadata/android/sv/full_description.txt | 5 + .../metadata/android/sv/short_description.txt | 1 + scripts/fetch-translations.sh | 2 +- 30 files changed, 1895 insertions(+), 95 deletions(-) create mode 100644 app/src/main/res/values-hr/strings.xml create mode 100644 app/src/main/res/values-ko/strings.xml create mode 100644 app/src/main/res/values-nb/strings.xml create mode 100644 app/src/main/res/values-sl/strings.xml create mode 100644 app/src/main/res/values-sv/strings.xml create mode 100644 fastlane/metadata/android/fr-FR/full_description.txt create mode 100644 fastlane/metadata/android/fr-FR/short_description.txt create mode 100644 fastlane/metadata/android/hr/full_description.txt create mode 100644 fastlane/metadata/android/hr/short_description.txt create mode 100644 fastlane/metadata/android/it/full_description.txt create mode 100644 fastlane/metadata/android/ko/full_description.txt create mode 100644 fastlane/metadata/android/ko/short_description.txt create mode 100644 fastlane/metadata/android/si/short_description.txt rename fastlane/metadata/android/{sl-SI => sl}/full_description.txt (100%) rename fastlane/metadata/android/{sl-SI => sl}/short_description.txt (100%) create mode 100644 fastlane/metadata/android/sr/full_description.txt create mode 100644 fastlane/metadata/android/sr/short_description.txt create mode 100644 fastlane/metadata/android/sv/full_description.txt create mode 100644 fastlane/metadata/android/sv/short_description.txt diff --git a/.tx/config b/.tx/config index 37d6937ea..8b2d7db5f 100644 --- a/.tx/config +++ b/.tx/config @@ -4,27 +4,23 @@ host = https://www.transifex.com [davx5.app] source_file = app/src/main/res/values/strings.xml source_lang = en -minimum_perc = 0 +minimum_perc = 20 file_filter = app/src/main/res/values-/strings.xml -trans.de = app/src/main/res/values-de/strings.xml -trans.tr_TR = app/src/main/res/values-tr/strings.xml -trans.zh_CN = app/src/main/res/values-zh/strings.xml +lang_map = ar_SA: ar, fi_FI: fi, fr_FR: fr-rFR, nb_NO: nb, sk_SK: sk, sl_SI: sl, tr_TR: tr, zh_CN: zh, zh_TW: zh-rTW type = ANDROID [davx5.metadata-short-description] -file_filter = fastlane/metadata/android//short_description.txt -minimum_perc = 100 source_file = fastlane/metadata/android/en-US/short_description.txt source_lang = en -trans.sl_SI = fastlane/metadata/android/sl-SI/short_description.txt -trans.zh_CN = fastlane/metadata/android/zh/short_description.txt +minimum_perc = 100 +file_filter = fastlane/metadata/android//short_description.txt +lang_map = ar_SA: ar, fi_FI: fi, fr_FR: fr-FR, nb_NO: nb, sk_SK: sk, sl_SI: sl, tr_TR: tr, zh_CN: zh, zh_TW: zh-TW type = TXT [davx5.metadata-full-description] -file_filter = fastlane/metadata/android//full_description.txt -minimum_perc = 100 source_file = fastlane/metadata/android/en-US/full_description.txt source_lang = en -trans.sl_SI = fastlane/metadata/android/sl-SI/full_description.txt -trans.zh_CN = fastlane/metadata/android/zh/full_description.txt +minimum_perc = 100 +file_filter = fastlane/metadata/android//full_description.txt +lang_map = ar_SA: ar, fi_FI: fi, fr_FR: fr-FR, nb_NO: nb, sk_SK: sk, sl_SI: sl, tr_TR: tr, zh_CN: zh, zh_TW: zh-TW type = TXT diff --git a/app/src/main/assets/translators.json b/app/src/main/assets/translators.json index 90603ca2f..418b7a7ef 100644 --- a/app/src/main/assets/translators.json +++ b/app/src/main/assets/translators.json @@ -1 +1 @@ -{"ar_SA":["abdunnasir"],"bg":["dpa_transifex"],"ca":["Kintu","jordibrus","zagur"],"cs":["pavelb","tomas.odehnal"],"da":["Tntdruid_","knutztar","mjjzf","twikedk"],"de":["Atalanttore","TheName","Wyrrrd","YvanM","amandablue","anestiskaci","corppneq","crit12","hammaschlach","maxkl","nicolas_git","owncube"],"el":["KristinaQejvanaj","anestiskaci","diamond_gr"],"es":["Ark74","Elhea","GranPC","aluaces","jcvielma","plaguna","polkhas","xphnx"],"eu":["Osoitz","Thadah","cockeredradiation"],"fa":["Numb","ahangarha","amiraliakbari","joojoojoo","maryambehzi","mtashackori","taranehsaei"],"fi_FI":["raketti"],"fr":["AlainR","Amadeen","Floflr","Llorc","LoiX07","Novick","Poussinou","Thecross","YvanM","alkino2","boutil","callmemagnus","chfo","chrcha","grenatrad","jokx","mathieugfortin","vincen","ÉricB."],"fr_FR":["Llorc","Poussinou","chrcha"],"gl":["aluaces","pikamoku"],"hu":["Roshek","jtg"],"it":["Damtux","FranzMari","ed0","malaerba","noccio","nwandy","rickyroo","technezio"],"it_IT":["malaerba"],"ja":["Naofumi","yanorei32"],"nb_NO":["elonus"],"nl":["XtremeNova","davtemp","dehart","erikhubers","frankyboy1963","glotzbach","toonvangerwen"],"pl":["TORminator","TheName","Valdnet","gsz","mg6","oskarjakiela"],"pt":["amalvarenga","wanderlei.huttel"],"pt_BR":["wanderlei.huttel"],"ru":["aigoshin","anm","astalavister","nick.savin","vaddd"],"sk_SK":["brango67","tiborepcek"],"sl_SI":["MrLaaky","uroszor"],"sr":["daimonion"],"sv":["campbelldavid"],"szl":["chlodny"],"tr_TR":["ooguz","pultars"],"uk":["androsua","olexn","twixi007"],"uk_UA":["astalavister"],"zh_CN":["anolir","jxj2zzz79pfp9bpo","linuxbckp","mofitt2016","oksjd","phy","spice2wolf"],"zh_TW":["linuxbckp","mofitt2016","phy","waiabsfabuloushk"]} +{"ar_SA":["abdunnasir"],"bg":["dpa_transifex"],"ca":["Kintu","jordibrus","zagur"],"cs":["pavelb","tomas.odehnal"],"da":["Tntdruid_","knutztar","mjjzf","twikedk"],"de":["Atalanttore","TheName","Wyrrrd","YvanM","amandablue","anestiskaci","corppneq","crit12","hammaschlach","maxkl","nicolas_git","owncube"],"el":["KristinaQejvanaj","anestiskaci","diamond_gr"],"es":["Ark74","Elhea","GranPC","aluaces","jcvielma","plaguna","polkhas","xphnx"],"eu":["Osoitz","Thadah","cockeredradiation"],"fa":["Numb","ahangarha","amiraliakbari","joojoojoo","maryambehzi","mtashackori","taranehsaei"],"fr":["AlainR","Amadeen","Floflr","Llorc","LoiX07","Novick","Poussinou","Thecross","YvanM","alkino2","boutil","callmemagnus","chfo","chrcha","grenatrad","jokx","mathieugfortin","paullbn","vincen","ÉricB."],"fr_FR":["Llorc","Poussinou","chrcha"],"gl":["aluaces","pikamoku"],"hu":["Roshek","jtg"],"it":["Damtux","FranzMari","ed0","malaerba","noccio","nwandy","rickyroo","technezio"],"it_IT":["malaerba"],"ja":["Naofumi","yanorei32"],"nb_NO":["elonus"],"nl":["XtremeNova","davtemp","dehart","erikhubers","frankyboy1963","glotzbach","toonvangerwen"],"pl":["TORminator","TheName","Valdnet","gsz","mg6","oskarjakiela"],"pt":["amalvarenga","wanderlei.huttel"],"pt_BR":["wanderlei.huttel"],"ru":["aigoshin","anm","astalavister","nick.savin","vaddd"],"sk_SK":["brango67","tiborepcek"],"sl_SI":["MrLaaky","uroszor"],"sr":["daimonion"],"sv":["campbelldavid"],"szl":["chlodny"],"tr_TR":["ooguz","pultars"],"uk":["androsua","olexn","twixi007"],"uk_UA":["astalavister"],"zh_CN":["anolir","jxj2zzz79pfp9bpo","linuxbckp","mofitt2016","oksjd","phy","spice2wolf"],"zh_TW":["linuxbckp","mofitt2016","phy","waiabsfabuloushk"]} diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 1fc6e0f73..f3f3f2509 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -14,8 +14,10 @@ تحذيرات المزامنة المشاكل غير الفادحة في المزامنة ، مثل بعض الملفات غير الصالحة أخطاء الشبكة و عمليات الإدخال/الإخراج - أوقات المهل، مشاكل الاتصال ، …الخ (مؤقتة في العادة) + أوقات المهل، مشاكل الاتصال ، ...الخ (مؤقتة في العادة) + المزيد من المعلومات + مهام @@ -38,7 +40,6 @@ موقع الويب دليل الاستخدام الأسئلة الشائعة - المساعدة / المنتدى تبرَّع مرحباً بك في DAVx⁵ !\n\n يمكنك إضافة حساب CalDAV أو CardDAV الآن. تم تعطيل المزامنة التلقائية على مستوى النظام @@ -46,6 +47,7 @@ فشل اكتشاف الخدمة لم يتمكن التطبيق من تجديد قائمة المجموعة + الإعدادات @@ -56,11 +58,6 @@ التسجيل مفعَّل التسجيل معطَّل الاتصال - تجاوز إعدادات الوكيل - إستخدم إعدادات وكيل مخصَّصة - إستخدم إعدادات الوكيل الافتراضية في النظام - اسم مضيف وكيل HTTP - منفذ وكيل HTTP الأمن عدم الثقة في شهادات النظام هيئات توثيق النظام و تلك التي أضافها المستخدم لن تكون محل ثقة @@ -207,6 +204,10 @@ حدث خطأ HTTP. حدث خطأ في الإدخال/الإخراج. عرض التفاصيل + + + اسم المستخدم + كلمة المرور أذونات DAVx⁵ مطلوب أذونات إضافية diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index c72ca1efc..1fd6e9b45 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -5,6 +5,8 @@ Kontua ez da existitzen (dagoeneko) DAVx⁵ Helbide liburua Helbide liburuak + Kendu + Utzi Eremu hau beharrezkoa da Laguntza Kudeatu kontuak @@ -394,6 +396,8 @@ Pasahitza Gehitu muntaia Ez dago WebDAV zerbitzurik URL honetan + Kendu muntaia-puntua + Konexio xehetasunak galduko dira, baina ez da fitxategirik ezabatuko. WebDAV fitxategia atzitzen WebDAV fitxategia deskargatzen WebDAV fitxategia kargatzen diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml new file mode 100644 index 000000000..705f21a96 --- /dev/null +++ b/app/src/main/res/values-hr/strings.xml @@ -0,0 +1,361 @@ + + + + DAVx⁵ + Račun (više) ne postoji + DAVx⁵ Adresar + Adresari + Pomoć + Upravljaj računima + Dijeli + Debugging + Ostale važne poruke + Statusne poruke niskog prioriteta + Sinkronizacija + Sinkronizacijske greške + Važne greške koje zaustavljaju sinkronizaciju poput neočekivanih odgovora poslužitelja + Sinkronizacijska upozorenja + Sinkronizacijski problemi koji nisu fatalni poput određenih nevaljanih datoteka + Mrežne i I/O greške + Vremensko ograničenje, greške povezivanja, itd. (obično privremeno) + + Vaši podaci. Vaš izbor. + Preuzmite kontrolu. + Redoviti intervali sinkronizacije + Onemogućeno (nije preporučeno) + Omogućeno (preporučeno) + Za sinkronizaciju u redovitim intervalima, %s mora imati omogućen rad u pozadini. Inače, Android može zaustaviti sinkronizaciju u bilo kojem trenutku. + Ne trebam redovita sinkroniziranja. + %s kompatibilnost + Ovaj uređaj vjerojatno blokira sinkronizaciju. Ukoliko ste zahvaćeni ovim problemom, morati ćete ga riješiti ručno sami. + Tražene izmjene su napravljene. Ne podsjećaj me više. + * Ostavi neoznačeno za podsjetnik kasnije. Moguće je resetirati u aplikacijskim postavkama / %s. + Više informacija + Podrška za zadatke + Ukoliko su zadatci podržani od strane vašeg poslužitelja, moguće ih je sinkronizirati sa podržanom aplikacijom za zadatke: + OpenTasks + dodatne aplikacije.]]> + Tasks + nisu podržane (još).]]> + Trgovina aplikacijama nije dostupna + Ne trebam podršku za zadatke.* + Softver otvorenog koda + Sretni smo što upotrebljavate %s, softver otvorenog koda. Razvoj, održavanje i podrška težak su posao. Molimo razmislite o doprinosu (mnogo je načina) ili o donaciji. Biti ćemo vam vrlo zahvalni! + Kako doprinijeti/donirati + Ne prikazuj u bliskoj u bliskoj budućnosti + + Dopuštenja + %s treba dopuštenja kako bi radio ispravno. + Sve od ispod + Koristi ovo za aktiviranje svih mogućnosti (preporučeno) + Sva dopuštenja odobrena + Dopuštenja kontakata + Bez sinkronizacije kontakata (nije preporučeno) + Moguća sinkronizacija kontakata + Dopuštenja kalendara + Bez sinkronizacije kalendara (nije preporučeno) + Moguća sinkronizacija kalendara + OpenTasks dopuštenja + Dopuštenja zadataka + Bez sinkronizacije zadataka (nije instalirano) + Moguća sinkronizacija zadataka + Zadrži dopuštenja + Dopuštenja mogu biti automatski resetirana (nije preporučeno) + Dopuštenja neće biti automatski resetirana + Ukloni dopuštenja ukoliko se aplikacija ne upotrebljava + Ukoliko prekidač ne radi, koristi postavke aplikacije / Dopuštenja. + Postavke aplikacije + + WiFi SSID dopuštenja + Kako bi se pristupilo trenutnom WiFi imenu (SSID), ovi uvjeti trebaju biti zadovoljeni: + Dopuštenja lokacije odobrena + Dopuštenja lokacije odbijena + Pozadinska dopuštenja lokacije + Dopusti cijelo vrijeme + %s ]]> + %s]]> + %s koristi dopuštenje za lokaciju samo kako bi se utvrdilo sadašnje WiFi SSID za SSID-ograničenim računa. To će se dogoditi čak i kada je aplikacija u pozadini. Podaci o lokaciji se ne prikupljaju, pohranjuju, obrađuju ili šalju bilo gdje. + Lokacija uvijek omogućena + Lokacijske usluge su omogućene + Lokacijske usluge su onemogućene + + Prijevodi + Bibiloteke + Verzija %1$s(%2$d) + Kompilirano na %s + Ova verzija ispunjava uvjete za distribuciju samo na Google Play trgovini. + Ovaj program dolazi BEZ APSOLUTNO BILO KAKVOG JAMSTVA. To je besplatni softver i možete ga distribuirati pod određenim uvjetima. + Thanks to: %s]]> + + Couldn\'t create log file + Now logging all %s activities + Pregledaj/podijeli + Onemogući + + Otvori navigacijski pretinac + Zatvori navigacijski pretinac + CalDAV/CardDAV Sync Adapter + About / License + Beta feedback + Molimo instalirajte aplikaciju za e-poštu + Molimo instalirajte web preglednik + Postavke + Novosti & aktualnosti + Vanjske poveznice + Web stranica + Upute + FAQ + Doniraj + Pravila o zaštiti privatnosti + Nema internet veze. Android neće pokrenuti sinkronizaciju. + Dobrodošli u DAVx⁵!\n\nSada možete dodati CalDAV/CardDAV račun. + Automatska sinkronizacija je onemogućena na razini sustava + Omogući + Sinkroniziraj sve račune + + Detekcija servisa nije uspjela + Nije moguće osvježiti popis zbirki + + + Pokrenuto u prednjem planu + Na nekim uređajima, ovo je neophodno za automatsku sinkronizaciju. + + Postavke + Debugging + Prikaži debug informacije + Pregledaj/podijeli softver i konfiguracijske detalje + Verbose logging + Logging je aktivan + Logging je onemogućen + Zadrži u prednjem planu + Može pomoći ukoliko vaš uređaj sprečava automatsku sinkronizaciju + Veza + Sigurnost + Dopuštenja aplikacije + Pregledajte dopuštenja potrebna za sinkronizaciju + Ukidanje povjerenja sistemskim certifikatima + Sistemski i korisnički dodani CA-i neće biti od povjerenja + Sistemski i korisnički dodani CA-i su od povjerenja (preporučeno) + Resetiraj certifikate od (ne)povjerenja + Reseira povjerenje svih prilagođenih certifikata + Svi prilagođeni certifikati su obrisani + Korisničko sučelje + Postavke obavijesti + Uredi izvore obavještavanja i njihove postavke + Resetiraj naznake + Ponovno omogućuje naznake koje su prethodno bile odbačene + Sve naznake će ponovno biti prikazane + Integracija + Tasks aplikacija + Sinkronizira sa %s + Kompatibilna aplikacija za zadatke nije pronađena + + CardDAV + CalDAV + Webcal + Bez sinkronizacije kontakata (nedostaju dopuštenja) + Bez sinkronizacije kalendara (nedostaju dopuštenja) + Bez sinkronizacije zadataka (nedostaju dopuštenja) + Bez sinkronizacije kalendara i zadataka (nedostaju dopuštenja) + Nije moguće pristupiti kalendarima (nedostaju dopuštenja) + Dopuštenja + Ne postoji adresar (još). + Ne postoji kalendar (još). + Ne postoje pretplate na kalendar (još). + Povucite prstom prema dolje za osvježavanje popisa sa poslužitelja. + Sinkroniziraj sada + Upravo sinkronizira + Postavke računa + Preimenuj račun + Ne spremljeni lokalni podatci mogu biti odbačeni. Ponovna sinkronizacija je potrebna nakon preimenovanja. Novi naziv računa: + Preimenuj + Račun nije moguće preimenovati + Obriši račun + Stvarno izbrisati račun? + Sve lokalne kopije adresara, kalendara i popisa zadataka biti će izbrisane. + sinkroniziraj ovu zbirku + read-only + kalendar + popis zadataka + Prikaži samo osobno + Osvježi popis adresara + Kreiraj novi adresar + Osvježi popis kalendara + Kreiraj novi kalendar + Aplikacija sa Webcal mogućnostima nije pronađena + Instaliraj ICSx⁵ + + Dodaj račun + Prijavi se sa adresom e-pošte + Adresa e-pošte + Potrebna je valjana adresa e-pošte + Lozinka + Lozinka je potrebna + Prijava sa URL-om i korisničkim imenom + URL mora započeti sa http(s):// + Korisničko ime + Korisničko ime je potrebno + Osnovni URL + Prijava sa URL-om i klijentskim certifikatom + Odaberi certifikat + Prijava + Kreiraj račun + Naziv računa + Koristite svoju adresu e-pošte kao naziv računa jer Android će koristiti naziv računa kao ORGANIZER polje za događaje koje kreirate. Nije moguće imati dva računa sa istim imenom. + Metoda kontaktnih grupa: + Potreban je naziv računa + Naziv računa se već koristi + Nije moguće napraviti račun + Napredna prijava (posebne namjene) + Koristi korisničko ime/lozinka + Koristi klijentski certifikat + Certifikat nije pronađen + Instaliraj certifikat + Detektiranje konfiguracije + Pričekajte, postavljanje upita poslužitelju... + Nije moguće pronaći CalDAV ili CardDAV uslugu. + Korisničko ime (adresa e-pošte) / lozinka pogrešni? + Prikaži detalje + + Postavke %s + Sinkronizacija + Interval sinkr. kontakata + Samo ručno + Svakih %d minuta + odmah nakon lokalnih izmjena + Interval sinkr. kalendara + Interval sinkr. zadataka + + Samo ručno + Svakih 15 minuta + Svakih 30 minuta + Svaki sat + Svaka 2 sata + Svaka 4 sata + Jednom dnevno + + Sinkroniziraj preko WiFi + Sinkronizacija je ograničena na WiFi veze + Vrsta veze se ne uzima u obzir + WiFi SSID ograničenje + Sinhronizirat će se samo preko %s + Sinkronizirat će se samo preko %s (potrebne su aktivne usluge lokacije) + Koristit će se sve WiFi veze + Zarezom odijeljeni nazivi (SSIDa) dozvoljenih WiFi mreža (ostaviti prazno za sve mreže) + WiFi SSID ograničenje zahtijeva daljnje postavke + Upravljaj + Više informacija (FAQ) + Autentifkacija + Korisničko ime + Unesite korisničko ime: + Lozinka + Ažurirajte lozinku vezanu uz vaš poslužitelj. + Unesite svoju lozinku: + Pseudonim klijentskog certifikata + Nije odabran nijedan certifikat + CalDAV + Vremensko ograničenje za prošli događaj + Svi događaju biti će sinkronizirani + + Događaji duži od jednog dana u prošlosti bit će zanemareni + Događaji duži od %d dana u prošlosti bit će zanemareni + Događaji duži od %d dana u prošlosti bit će zanemareni + + Događaji koji su prošli više od ovog broja dana bit će zanemareni (može biti 0). Ostavite prazno za sinkronizaciju svih događaja. + Zadani podsjetnik + + Zadani podsjetnik jednu minuta prije događaja + Zadani podsjetnik %d minuta prije događaja + Zadani podsjetnik %d minuta prije događaja + + Zadani podsjetnici nisu kreirani + Ako će se stvoriti zadani podsjetnici za događaje bez podsjetnika: željeni broj minuta prije događaja. Ostavite prazno da biste onemogućili zadane podsjetnike. + Upravljaj bojama kalendara + Boje kalendara se resetiraju pri svakoj sinkronizaciji + Boje kalendara mogu biti postavljene od strane drugih aplikacija + Podrška za boju događaja + Boje događaja su sinkronizirane + Boje događaja nisu sinkronizirane + CardDAV + Metoda kontaktnih grupa + + Grupe su odvojene vCards + Grupe su kategorije po kontaktima + + Promijeni metodu grupe + + Kreiraj adresar + Moj adresar + Kreiraj kalendar + Vremenska zona + Mogući unosi u kalendar + Događaji + Zadatci + Bilješke / dnevnik + Kombinirano (događaji i zadaci) + Boja + Izrada zbirke + Naslov + Potreban je naslov + Opis + opcionalno + Mjesto pohrane + Kreiraj + Obriši zbirku + Jeste li sigurni? + Ova zbirka (%s) i njeni podatci biti će trajno uklonjeni. + Ovi podatci biti će obrisani sa poslužitelja. + Brisanje zbirke + Prisilno samo za čitanje + Svojstva + Adresa (URL): + Kopiraj URL + Vlasnik: + + Debug info + Debug info priložen je uz ovu poruku (zahtijeva podršku za privitke aplikacije koja će primiti poruku). + HTTP greška + Greška na poslužitelju + WebDAV greška + I/O greška + Zahtjev je odbijen. Pojedinosti potražite u uključenim resursima i debug informacijama. + Traženi resurs ne postoji (više). Pojedinosti potražite u uključenim resursima i debug informacijama. + Greška sa poslužiteljske strane. Molimo obratite se podršci za poslužitelja. + Dogodila se neočekivana pogreška. Pojedinosti potražite u debug informacijama. + Pogledaj pojedinosti + Debug info je prikupljen + Uključeni resursi + Povezano s problemom + Udaljeni resurs: + Lokali resurs: + Pregledaj u aplikaciji + Logovi + Opsežniji logovi su dostupni + Pregledaj logove + + Dogodila se greška. + Dogodila se HTTP greška. + Dogodila se I/O greška. + Prikaži detalje + + + Korisničko ime + Lozinka + + DAVx⁵ dopuštenja + Dodatna dopuštenja su potrebna + %s prestar + Najmanja potrebno verzija: %1$s + Autentifikacija nije uspjela (provjerite podatke za prijavu) + Mrežna ili I/O greška – %s + HTTP poslužiteljska greška – %s + Greška lokalne pohrane – %s + Pokušaj ponovno + Pregledaj stavku + Primljen je nevažeći kontakt sa poslužitelja + Primljen je nevažeći dogđaj sa poslužitelja + Primljen je nevažeći zadatak sa poslužitelja + Zanemarivanje jednog ili više nevaljanih resursa + + DAVx⁵: Sigurnost veze + DAVx⁵ je naišao na nepoznati certifikat. Želite li mu vjerovati? + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml new file mode 100644 index 000000000..70128d4d2 --- /dev/null +++ b/app/src/main/res/values-ko/strings.xml @@ -0,0 +1,418 @@ + + + + DAVx⁵ + 계정이 존재하지 않음 (anymore) + DAVx⁵ 주소록 + 주소록 + 이 field는 필수입니다. + 도움말 + 관리 계정 + 공유하기 + 데이터베이스 손상 + 모든 계정이 로컬에서 제거되었습니다. + Debugging + 기타 중요한 메시지 + Low-priority status messages + 동기화 + 동기화 오류 + 예기치 않은 서버 응답과 같이 동기화를 중지하는 중요한 오류 + 동기화 warning + 특정 잘못된 파일과 같은 치명적이지 않은 동기화 문제 + 네트워크 및 I/O 에러 + 시간 초과, 연결 문제 등(대개 일시적) + + 당신의 데이터. 당신의 선택. + 관리. + 정기적 동기화 주기 + 사용 안 함(권장하지 않음) + 사용(권장) + 정기적으로 동기화하려면 백그라운드에서 %s이 실행되도록 허용해야 합니다. 그렇지 않으면 Android는 언제든지 동기화를 일시 중지할 수 있습니다. + 나는 정기적인 동기화 주기가 필요하지 않다.* + %s 호환성 + 이 장치는 동기화를 차단합니다. 영향을 받는 경우 이 문제를 수동으로만 해결할 수 있습니다. + 필요한 설정을 완료했습니다. 더 이상 다시 수행하지 마세요.* + * 나중에 알림이 표시되도록 선택 해제된 상태로 둡니다. / 앱 설정에서 재설정할 수 있습니다. / %s + 상세 정보 + jtx Board + + 작업 지원 + 서버에서 작업을 지원하는 경우 지원되는 작업 앱과 동기화할 수 있습니다. + OpenTasks + 추가 앱이 필요할 수 있습니다..]]> + 할일 목록 + 아직 지원되지 않습니다.(yet)]]> + 사용 가능한 앱 스토어 없음 + 업무 지원은 필요 없습니다.* + 오픈-소스 소프트웨어 + 오픈 소스 소프트웨어인 %s를 사용해 주셔서 기쁩니다. 개발, 유지보수 및 지원은 힘든 작업입니다. (기여나 기부를 고려해 보세요. 그것은 매우 감사할 일 것 입니다!) + 기여/기부 방법 + 가까운 시일 내에 표시 안 함 + + 권한 + %s이 제대로 작동하려면 사용 권한이 필요합니다 + 아래의 모든 것 + 이를 통해 모든 기능을 사용할 수 있습니다(권장). + 모든 권한 부여 + 연락처 권한 + 연락처 동기화 하지않음 (권장하지 않음) + 연락처 동기화 가능 + 캘린더 권한 + 캘린더 동기화 없음(권장하지 않음) + 캘린더를 동기화 할 수 있음 + jtx Board 권한 + 동기화할 작업, 일지 & 노트가 없음(설치되지 않음) + 동기화할 작업, 일지, 노트가 없음 + 동기회 가능한 작업, 일지, 노트 + OpenTasks 권한 + 작업 권한 + 작업 동기화 되지 않음 (설치되지 않음) + 할일 목록 동기화 하지않음 + 할일 목록 동기화 가능 + 권한 유지 + 권한이 자동으로 재설정됨(권장하지 않음) + 권한이 자동으로 재설정 되지않음 + 권한을 선택하세요 > \"앱을 사용하지 않을 경우 사용 권한 제거\" + 스위치가 작동하지 않으면 앱 설정 / 사용 권한을 사용하십시오. + 앱 설정 + + WiFi SSID 권한 + 현재 WiFi 이름(SSID)에 액세스할 수 있으려면 다음 조건을 충족해야 합니다. + 상세 위치 권한 + 위치 권한 부여 + 위치 권한 거부 + 백그라운드 위치 권한 + 항상 허용 + %s로 설정됨]]> + %s로 설정되지 않음 ]]> + %s은 SSID 제한 계정에 대한 현재 WiFi의 SSID를 확인하는 데만 위치 권한을 사용합니다. 이것은 앱이 백그라운드에 있을 때에도 발생할 것이다. 어떤 위치 데이터도 수집, 저장, 처리 또는 어디로든 전송되지 않습니다. + 위치 정보 항상 사용 + 위치 서비스를 사용할 수 있습니다. + 위치 서비스가 거부되었습니다. + + 번역 + 라이브러리 + 버전 %1$s (%2$d) + %s에서 컴파일 + © Ricki Hirner, Bernhard Stockmann (bitfire web engineering GmbH) and contributors + 이 버전은 Google Play를 통해서만 배포될 수 있습니다. + 이 프로그램은 보증 없이 제공됩니다. 그것은 무료 소프트웨어이며, 특정한 조건 하에서 재배포하는 것을 환영합니다. + Thanks to: %s]]> + + log file을 만들 수 없습니다. + 이제 모든 %s 활동을 logging합니다. + 보기/공유 + 사용 안함 + + 탐색 창 열기 + 탐색 창 닫기 + CalDAV/CardDAV 동기화 어댑터 + 관련 / 라이센스 + 베타 피드백 + 이메일 클라이언트를 설치하십시오. + 웹 브라우저를 설치해 주십시오. + 설정 + 뉴스 & 업데이트 + + 외부 링크 + 웹 사이트 + 메뉴얼 + FAQ + 커뮤니티 + 기부 + 개인 정보 보호 정책 + 인터넷에 연결할 수 없습니다. Android가 동기화를 실행하지 않습니다. + 저장 공간이 부족합니다. Android가 동기화를 실행하지 않습니다. + DAVx⁵에 오신 것을 환영 합니다!/n/n +당신은 CalDAV/CardDAV 계정을 지금 추가 할 수 있습니다. + 시스템 전체 자동 동기화가 비활성화됩니다. + 활성 + 모든 계정 동기화 + + 서비스 검색 실패 + collection 목록을 새로 고칠 수 없습니다. + + foreground에서 실행할 수 없습니다. + 배터리 최적화 허용목록 필요 + + foreground에서 실행중 + 일부 장치에서는 자동 동기화를 위해 이 작업이 필요합니다. + + 설정 + Debugging + debug info 보기 + 소프트웨어 및 구성 세부 정보 보기/공유 + 상세 로그 + logging이 활성되었습니다. + logging이 비활성화되었습니다. + 배터리 최적화 + 앱이 허용목록에 포함(권장) + 앱이 허용목록에 미포함(권장하지 않음) + foreground에서 유지 + 장치가 자동 동기화를 차단하는 경우 도움이 될 수 있습니다. + 연결 + 프록시 타입 + + 기본값 + No proxy + HTTP + SOCKS (for Orbot) + + 프록시 호스트 이름 + 프록시 포트 + 보안 + 앱 권한 + 동기화에 필요한 사용 권한 검토 + 신뢰할 수 없는 시스템 인증 + 시스템 및 사용자 추가한 CA를 신뢰할 수 없음 + 시스템 및 사용자 추가한 CA를 신뢰할 수 있음(권장) + 신뢰할 수 있는(없는) 인증서 재설정 + 모든 사용자 지정 인증서를 재설정합니다. + 모든 사용자 지정 인증서가 확인되었습니다. + 사용자 인터페이스 + 알림 설정 + 알림 채널 및 해당 설정 관리 + 테마 선택 + + 시스템 디자인 + 밝은 테마 + 어두운 테마 + + 힌트 재설정 + 이전에 해제된 힌트를 다시 사용 + 모든 힌트가 다시 표기 + 통합 + 테스크 앱 + %s과 동기화 + 호환되는 작업 앱을 찾을 수 없습니다. + + CardDAV + CalDAV + Webcal + 연락처 동기화 되지않음 (missing permissions) + 캘린더가 동기화되지 않음 (missing permissions) + 할일목록이 동기화 되지않음 (missing permissions) + 캘린더 및 할일 목록이 동기화되지 않음(missing permissions) + 캘린더에 접근할 수 없음 (missing permissions) + 권한 + 주소록이 없다. (yet) + 캘린더가 없다.(yet) + 구독하는 캘린더가 없습니다. (yet) + 서버에서 목록을 새로 고치려면 아래로 스와이프하세요. + 동기화 + 동기화 중 + 계정 설정 + 계정 이름 바꾸기 + 저장되지 않은 로컬 데이터는 삭제될 수 있습니다. 이름을 변경한 후 다시 동기화해야 합니다. 새 계정 이름: + 이름 바꾸기 + 계정 이름을 바꿀 수 없습니다. + 계정 삭제 + 정말 계정을 삭제하시겠습니까? + 주소록, 캘린더 및 업무 목록의 모든 로컬 복사본이 삭제됩니다. + 이 collection을 동기화합니다. + 읽기전용 + 캘린더 + 할일 목록 + 일지 + 개인만 표시 + 주소록 목록 새로 고침 + 새 주소록 만들기 + 캘린더 목록 새로 고침 + 새 캘린더 작성 + Webcal 지원 앱을 찾을 수 없습니다. + ICSx⁵를 설치합니다. + + 계정 추가 + 이메일 주소로 로그인 + 이메일 주소 + 올바른 이메일 주소가 필요합니다. + 비밀번호 + 비밀번호가 필요합니다. + 로그인 URL 과 사용자이름 + URL은 반드시 http(s)://로 시작되어야 합니다. + 사용자 이름 + 사용자 이름이 필요합니다. + 기본 URL + URL 및 클라이언트 인증서로 로그인 + 인증서 선택 + 로그인 + 계정 생성 + 계정 이름 + 따옴표(\')를 사용하면 일부 장치에서 문제가 발생하는 것으로 보고되었습니다. + Android는 사용자가 만든 이벤트에 대해 계정 이름을 ORGANGER 필드로 사용하므로 전자 메일 주소를 계정 이름으로 사용합니다. 이름이 같은 두 개의 계정을 가질 수 없습니다. + 연락처 분류 방법: + 계정 이름 필요 + 계정 이름이 이미 사용되었습니다. + 계정을 만들 수 없습니다. + Advanced 로그인 (special use cases) + 사용자 이름/비밀번호 사용 + 클라이언트 인증서 사용 + 인증서를 찾을 수 없음 + 인증서 설치 + 구성 탐색 + 잠시 기다려 주십시오. 서버를 쿼리하고 있습니다... + CalDAV 또는 CardDAV 서비스를 찾을 수 없습니다. + 사용자 이름 (email address) / 비밀번호 가 잘못되었습니까? + 자세히 + + 설정: %s + 동기화 + 주기적 연락처 동기화 + 직접 선택 + 매 %d 분 + 로컬 변경시 즉시 + 주기적 캘린더 동기화 + 주기적으로 작업 동기화 + + 직접 선택 + 매 15분마다 + 매 30분마다 + 매 1시간마다 + 매 2시간마다 + 매 4시간마다 + 매일 한번 + + WiFi로만 동기화 + 동기화는 WiFi 연결로 제한됩니다. + 연결 유형은 고려되지 않습니다. + WiFi SSID 제한 + 다음에 대해서만 동기화됨 %s + %s에서만 동기화 수행(active location services 필요) + 모든 WiFi 연결이 사용됩니다. + 쉼표로 구분된 허용되는 WIFI 네트워크의 이름(모두 빈칸으로 두세요) + WiFi SSID 제한에 추가 설정이 필요함 + 관리 + 추가 정보(FAQ) + 인증 + 사용자 이름 + 사용자 이름 입력: + 비밀번호 + 귀하의 서버에 비밀번호 업데이트. + 비밀번호를 입력: + 클라이언트 인증서 별칭 + 인증서를 선택하지 않음 + CalDAV + 지난 이벤트 시간 제한 + 모든 이벤트가 동기화 됩니다. + + 지난 이벤트 중 %d일은 무시됩니다. + + 지난 일 수보다 많은 이벤트는 무시됩니다(0일). 모든 이벤트를 동기화하려면 비워 두십시오. + 기본 리마인더 + + 이벤트 %d분 전 기본 리마인더 + + 기본 리마인더이 생성되지 않았습니다 + 리마인더없이 이벤트에 대해 default 리마인더가 생성되어야 하는 경우: 이벤트 시작 전 원하는 시간. default 리마인더을 사용하지 않으려면 비워 두십시오. + 캘린더 색상 관리 + 캘린더 색상은 동기화할 때마다 재설정됩니다. + 다른 앱에서 캘린더 색상을 설정할 수 있습니다. + 이벤트 색상 지원 + 이벤트 색상이 동기화 되었습니다. + 이벤트 색상이 동기화되지 않았습니다. + CardDAV + 연락처 분류 방법 + + 별도의 전자 명함으로 분류 + 연락처 별 항목으로 분류 + + 분류 방식 변경 + + 주소록 생성 + 내 주소록 + 캘린더 생성 + 시간대 + 가능한 캘린더 항목 + 이벤트 + 할일 목록 + 메모 및 저널 + 통합 (이벤트 및 작업) + 색상 + collection을 만드는 중 + 제목 + 제목이 필요합니다. + 설명 + 선택 + 저장 위치 + 저장 위치가 필요합니다. + 생성 + collection 삭제 + 확실합니까? + 이 collection(%s) 및 모든 데이터가 영구적으로 제거됩니다. + 이러한 데이터는 서버에서 삭제되어야 한다. + collection 삭제중 + 읽기-전용으로 만들기 + Properties + 주소 (URL): + URL 복사 + 소유자: + + Debug info + ZIP 아카이브 + debug info and logs을 포함 + 아카이브를 공유하여 컴퓨터로 전송하거나 email로 보내거나 support ticket에 첨부합니다. + 아카이브를 공유 + 이 메시지에 첨부된 Debug info(requires attachment support of the receiving app) + HTTP 에러 + 서버 에러 + WebDAV 에러 + I/O 에러 + 요청이 거부되었습니다. 자세한 내용은 관련 리소스 및 디버그 정보를 확인하십시오. + 요청한 리소스가 (더 이상) 존재하지 않습니다. 자세한 내용은 관련 리소스 및 Debug info를 확인하십시오. + 서버 측 문제가 발생했습니다. server support에 문의하십시오 + 예기치 않은 오류가 발생했습니다. 자세한 내용은 debug info를 참조하십시오. + 상세 설명보기 + Debug info가 수집되었습니다. + 관련 리소스 + 관련된 문제 + 원격 리소스: + 로컬 리소스: + 앱으로 보기 + Logs + 상세 logs를 사용할 수 있습니다. + logs 보기 + + 에러가 발생 하였습니다. + HTTP 에러가 발생 하였습니다. + I/O 에러가 발생 하였습니다. + 자세히 + + 동기화가 일시 중지됨 + 사용 가능한 공간이 거의 없음 + + WebDAV mounts + 사용된 할당량: %1$s / 사용가능한 할당량: %2$s + 공유 콘텐츠 + Unmount + Add WebDAV mount + WebDAV 마운트를 추가하여 클라우드 파일에 직접 액세스하십시오! + WebDAV 마운트의 작동 방법은 설명서를 참조하십시오.]]> + 이름 표기 + WebDAV URL + 잘못된 URL + 사용자 이름 + 비밀번호 + Add mount + 이 URL에 WebDAV 서비스가 없습니다. + Accessing WebDAV file + Downloading WebDAV file + Uploading WebDAV file + WebDAV mount + + DAVx⁵ 권한 + 추가 권한 필요 + %s는 너무 오래되었습니다. + 최소 필요 버전: %1$s + 인증 실패(로그인 자격 증명 확인) + 네트워크 혹은 I/O 에러 – %s + HTTP 서버 오류 – %s + Local storage 오류 – %s + 다시하기 + 항목 보기 + 서버로부터 잘못된 연락처를 받았습니다. + 서버에서 잘못된 이벤트를 수신했습니다. + 서버에서 잘못된 작업을 수신했습니다. + 하나 이상의 잘못된 리소스 무시 + + DAVx²: 연결 보안 + DAVx®에서 알 수 없는 인증서를 발견했습니다. 신뢰할 수 있습니까? + diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml new file mode 100644 index 000000000..ef94ebc15 --- /dev/null +++ b/app/src/main/res/values-nb/strings.xml @@ -0,0 +1,218 @@ + + + + DAVx⁵ + DAVx⁵-adressebok + Adressebøker + Hjelp + Behandle kontoer + Feilsøking + Andre viktige beskjeder + Synkronisering + Synkroniseringsfeil + Viktige feil som avbryter synkronisering, som uventede svar fra serveren + Ikke-kritiske synkroniseringsproblem, som enkelte ugyldige filer + Nettverk- og I/O-feil + + Mer informasjon + Oppgaver + + Kontakt-tilgang + Kalender-tilgang + OpenTasks-tilganger + + + Bibliotek + Versjon %1$s(%2$d) + Kompilert på %s + Denne versjonen kan bare distribueres over Google Play. + Dette programmet kommer uten NOEN FORM FOR GARANTI. Det er fri programvare, og du er velkommen til å redistribuere det under gitte forhold. + + Kan ikke opprette loggfil + + Åpne navigasjonsskuff + Lukk navigasjonsskuff + CalDAV/CardDAV -synkroniseringsadapter + Om / Lisens + Tilbakemelding om beta-en + Innstillinger + Nyheter og oppdateringer + Eksterne lenker + Nettside + Manuell + O-S-S + Doner + Velkommen til DAVx⁵.\n\nDu kan legge til en CalDAV/CardDAV-konto nå. + Systemomspennende automatisk synkronisering avskrudd + Skru på + + Tjenesteoppdagelse mislyktes + Kunne ikke gjenoppfriske innsamlingsliste + + + + Innstillinger + Feilretting + Vis feilrettingsinfo + Vis/del programvare- og oppsettsdetaljer + Grundig logging + Logging er aktivert + Logging er skrudd av + Tilkobling + Sikkerhet + Fjern tiltro til systemsertifikater + System og brukertillagte sertifikatsmyntigheter vil ikke bli tiltrodd + System- og bruker -tillagte sertifikatsmyndigheter vil bli tiltrodd (anbefalt) + Tilbakestill (ikke)tiltrodde sertifikater + Tilbakestiller tillit til alle egendefinerte sertifikater + Alle egendefinerte sertifikater har blitt fjernet + Brukergrensesnitt + Varselsinnstillinger + Tilbakestill hint + Skrur på hint som har blitt avslått tidligere + Alle hint vil bli vist igjen + + CardDAV + CalDAV + Webcal + Det eksisterer ingen adressebøker (enda). + Det eksisterer ingen kalendere (enda). + Du abonnerer ikke på noen kalendere (enda). + Dra ned for å oppdatere listen fra serveren. + Synkroniser nå + Synkroniserer nå + Kontoinnstillinger + Gi konto nytt navn + Ulagret lokal data kan bli avslått. Ny synkronisering kreves etter ny navngivning. Nytt kontonavn: + Gi nytt navn + Slett konto + Vil du virkeling slette kontoen? + Alle lokale kopier av adressebøker, kalendere og gjøremålslister vil bli slettet. + synkroniser denne samlingen + kun lesbar + kalender + oppgaveliste + Gjenoppfrisk adressebokliste + Opprett ny adressebok + Gjenoppfrisk kalenderliste + Opprett ny kalender + Fant ingen programmer med støtte for Webcal + Installer ICSx⁵ + + Legg til konto + Innlogging med e-postadresse + E-postadresse + Gyldig e-postadresse påkrevd + Passord + Passord kreves + Logg inn med nettadresse og brukernavn + Nettadresse må begynned med http(s):// + Brukernavn + Brukernavn påkrevd + Landings-nettadresse + Logg inn + Opprett konto + Kontonavn + Bruk din e-postadresse som kontonavn fordi Android vil bruke kontonavnet som ORGANISATOR-felt for hendelser du oppretter. Du kan ikke ha to kontoer med samme navn. + Kontaktgruppemetode: + Kontonavn påkrevd + Brukernavnet er allerede i bruk + Kontonavnet kan ikke opprettes + Oppdagelse av oppsett + Vent, spør tjener… + Fant ikke CalDAV eller CardDAV-tjeneste. + Vis fler detaljer + + Innstillinger: %s + Synkronisering + Intervall for kontaktsynkronisering + Åpne manuelt + Hvert %d minutt + umiddelbart ved lokale endringer + Kalendersynkroniseringsintervall + Gjøremålssynkroniseringsintervall + + Bare manuelt + Hvert kvarter + Hver halvtime + Hver time + Hver andre time + Hver fjerde time + Én gang om dagen + + Bare synk. over Wi-Fi + Synkronisering er begrenset til Wi-Fi -tilkoblinger + Tilkoblingstypen blir ikke tatt i betraktning + Wi-Fi SSID -begrensning + Vil kun synkronisere over %s + Vil bare synkronisere over %s (krever å ha lokasjonstjenester aktivert) + Alle Wi-Fi -tilkoblinger vil bli brukt + Kommainndelte navn (SSID-er) på tillatte Wi-Fi -nettverk (la stå tomt for alle) + Mer informasjon (FAQ) + Identitetsbekreftelse + Brukernavn + Skriv inn brukernavn: + Passord + Oppdater passordet i henhold til din tjener. + Skriv inn passordet ditt: + CalDAV + Tidsgrense for tidligere hendelser + Alle gjøremål vil bli synkronisert + + Gjøremål for mer enn én dag siden vil bli sett bort fra + Gjøremål for mer enn %d dager siden vil bli sett bort fra + + Hendelser som er mer enn dette antallet dager i fortid vil bli ignorert (kan være 0). La stå tomt for å synkronisere alle hendelser. + Velg kalenderfarger + Støtte for fargelegging av hendelser + CardDAV + Kontaktgruppemetode + Endre gruppemetode + + Opprett adressebok + Min adressebok + Opprett kalender + Tidssone + Mulige kalenderhendelser + Hendelser + Oppgaver + Kombinert (hendelser og gjøremål) + Farge + Oppretter samling + Tittel + Tittel kreves + Beskrivelse + valgfri + Lagringslokasjon + Opprett + Slett samling + Er du sikker? + Denne samlingen (%s) og all dens data vil bli permanent slettet. + Disse datene blir slettet fra serveren. + Sletter samling + Tving kun lesbar + Egenskaper + Adresse (URL): + Kopier nettadresse + + Feilrettingsinfo + + En feil har inntruffet + En HTTP-feil har inntruffet. + En I/O-feil har inntruffet. + Vis detaljer + + + Brukernavn + Passord + + DAVx⁵-tilganger + Ytterligere tilganger kreves + Nettverk- og I/O-feil - %s + HTTP-tjenerfeil - %s + Feil med lokallagring - %s + Forsøk igjen + Fikk ugyldig kontakt fra server + + DAVx⁵: Tilkoblingssikkerhet + DAVx⁵ har støtt på et ukjent sertifikat. Har du tiltro til det? + diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 2714f0271..72f544317 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -5,6 +5,8 @@ Account bestaat niet (of niet meer) DAVx⁵ Adresboek Adresboeken + Verwijder + Annuleer Dit veld is verplicht Hulp Accounts beheren @@ -394,6 +396,8 @@ Wachtwoord Koppeling toevoegen Geen WebDAV-service op deze URL + Verwijder het koppelpunt + Verbindingsgegevens gaan verloren, maar er worden geen bestanden gewist. WebDAV-bestand openen WebDAV-bestand downloaden WebDAV-bestand uploaden diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d02f77982..cf0ec9b8e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -112,12 +112,12 @@ О программе / Лицензия Отзыв о бета-тестировании Пожалуйста, установите почтовый клиент - Пожалуйста, установите веб-браузер + Пожалуйста, установите браузер Настройки Новости и обновления Инструменты Внешние ссылки - Веб-сайт + Сайт Руководство FAQ Сообщество @@ -137,7 +137,7 @@ Необходимо добавить в белый список оптимизации батареи Запущен в приоритетном режиме - Для автоматической синхронизации на некоторых устройствах. + Требуется для автоматической синхронизации на некоторых устройствах. Настройки Отладка diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 8ed69f382..0064c430c 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -16,6 +16,8 @@ Sieťové a V/V chyby Vypršanie času, problémy spojenia, atď. (často dočasné) + Viac informácii + Úlohy @@ -40,7 +42,6 @@ Webové sídlo Manuál FAQ - Pomoc / Fóra Darovať Zásady bezpečnosti Žiadne pripojenie do internetu. Android nestpustí synchronizáciu. @@ -50,6 +51,7 @@ Zisťovanie služby zlyhalo Nie je možné obnoviť zoznam kolekcií + Nastavenia @@ -60,11 +62,6 @@ Protokolovanie je aktívne Protokolovanie je zakázané Spojenie - Prepísať nastavenie proxy - Použiť užívateľské nastavenie proxy - Použiť nastavenie proxy platné pre systém - Meno hostiteľa HTTP proxy - Číslo portu HTTP proxy Zabezpečenie Nedôverovať systémovým certifikátom Nebude sa dôverovať systémovým a požívateľom pridaným certifikátom @@ -128,7 +125,7 @@ Meno účtu sa už používa Nie je možné vytvoriť používateľský účet Zisťuje sa konfigurácia - Čakajte, prosím, zasiela sa dopyt na server… + Čakajte, prosím, zasiela sa dopyt na server... Nie je možné nájsť služby CalDAV ani CardDAV. Zobraziť podrobnosti @@ -226,6 +223,10 @@ Vyskytla sa HTTP chyba. Vyskytla sa V/V chyba. Zobraziť detaily + + + Meno používateľa + Heslo Oprávnenia DAVx⁵ Vyžadujú sa dodatočné oprávnenia diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml new file mode 100644 index 000000000..5723652d1 --- /dev/null +++ b/app/src/main/res/values-sl/strings.xml @@ -0,0 +1,229 @@ + + + + DAVx⁵ + DAVx⁵ imenik + Seznami s stiki + Pomoč + Urejanje prijav + Razhroščevalnik + Ostale pomembne nastavitve + Sinhronizacija + Napake v sinhronizaciji + Pomembne napake, ki zaustavijo sinhronizacijo(npr. nepričakovani odgovori strežnika) + Opozorila med sinhronizacijo + Neusodni problemi v sinhronizaciji npr. določene neveljavne datoteke + Omrežje in I/O napake + Pavze, povezave v povezavi z omrežjem, itd. (ponavadi začasno) + + Več informacij + Naloge + + + + Knjižnice + Verzija %1$s (%2$d) + Združeno na %s + Ta verzija je na voljo samo za distribucijo preko Google Play. + Ta program ne vsebuje NIČ garancije. To je brezplačna programska oprema in jo lahko pod določenimi pogoji delite naprej. + + Ni bilo mogoče ustvariti zapisnika + + Odpri navigacijski predal + Zapri navigacijski predal + CalDAV/CardDAV sinhronizacijski adapter + O aplikaciji / licenca + Beta povratne aplikacije + Nastavitve + Novice & posodobitve + Zunanje povezave + Spletna stran + Priročnik + Pogosta vprašanja + Prispevaj + Dobrodošli v DAVx⁵!\n\nZdaj lahko dodate CalDAV/CardDAV račun. + Sistemska avtomatska sinhronizacija je izklopljena + Omogoči + + Zaznava storitve ni uspela + Zbirke ni bilo mogoče osvežiti + + + + Nastavitve + Razhroščevalnik + Prikaži informacije razhroščevalnika + Preglej/deli podrobnosti programske opreme in konfiguracije + Podrobno zapisovanje procesov + Zapisovanje je aktivno + Zapisovanje je onemogočeno + Povezava + Varnost + Nezaupaj sistemskim cerfitikatom + Sistemski in od uporabnika dodani certifikati ne bodo zaupani + Sistemski in od uporabnika dodani certifikati bodo zaupani(priporočeno) + Ponastavi (ne)zaupane certifikate + Ponastavi zaupanje vse lastnih certifikatov + Vsi lastni certifikati so bili odstranjeni + Uporabniški vmesnik + Nastavitve opozoril + Uredi kanale opozoril in njihove nastavitve + Ponastavi namige + Ponovno omogoči namige, ki si bilo predhodno izključeni + Vsi namigi bodo ponovno prikazani + + CardDAV + CalDAV + Webcal + Trenutno ni nobenega imenika (še). + Trenutno ni nobenega koledarja (še). + Trenutno ni nobene koledar naročnine (še). + Potegni navzdol za osvežitev strežniškega seznama. + Sinhroniziraj zdaj + Sinhronizacija v teku + Nastavitve računa + Preimenuj račun + Neshranjeni lokalni podatki bodo izbrisani. Ponovna sinhronizacija je potrebna po preimenovanju. Novo ime računa: + Preimenuj + Izbriši račun + Ali res želite izbrisati račun? + Vse lokalne kopije imenika, koledarjev in seznamov opravil bodo izbrisane. + sinhroniziraj to zbirko + samo za branje + koledar + seznam opravil + Osveži seznam imenikov + Ustvari nov imenik + Osveži seznam koledarjev + Ustvari nov koledar + Nobena Webcal sposobna aplikacija ni bila najdena + Namesti ICSx⁵ + + Dodaj račun + Prijava z email naslovom + Email naslov + Potreben je veljaven email naslov + Geslo + Zahtevano je geslo + Prijava z URL in uporabniškim imenom + URL se mora začeti s http(s):// + Uporabniško ime + Zahtevano je uporabniško ime + URL osnova + Prijava z URL in certifikatom uporabnika + Izberi certifikat + Prijava + Ustvari račun + Ime računa + Uporabi email naslov kot ime računa, ker bo Android uporabil to ime računa kot organizacijsko povelj za dogodke, ki jih ustvariš. Dveh računov z istim imenom ni mogoče imeti. + Metoda skupine kontaktov: + Zahtevano je ime računa + Ima računa že obstaja + Računa ni bilo mogoče ustvariti + Zaznava konfiguracije + Prosim počakajte, povezava s strežnikom je v teku... + CalDAV ali CardDAV storitve ni bilo mogoče najti. + Pokaži podrobnosti + + Nastavitve: %s + Sinhronizacija + Kontakti interval sinhronizacije + Samo ročno + Vsakih %d minut + takoj po lokalnih spremembah + Koladar interval sinhronizacije + Naloge interval sinhronizacij + + Samo ročno + Vsakih 15 minut + Vsakih 30 minut + Vsako uro + Vsaki 2 uri + Vsake 4 ure + Enkrat na dan + + Sinhronizacija samo preko Wifi + Sinhronizacije je omejena na Wifi omrežja + Tip povezave ni upoštevan + WiFI SSIF omejitev + Bo sinhroniziralo samo preko %s + Bo sinhroniziralo samo preko %s (potrebuje aktivirano določanje lokacije) + Vse WiFi povezave bodo uporabljene + Z vejico ločena imena (SSID) dovoljenih WiFi omrežij (pusti prazno za vse) + Več informacij (pogosta vprašanja) + Avtentikacija + Uporabniško ime + Vnesi uporabniško ime: + Geslo + Posodobi geslo ustrezajoč strežniku. + Vnesi vaše geslo: + Alias certifikata klienta + CalDAV + Pretekli dogodek časovna omejitev + Vsi dogodki bodo sinhronizirani + + Dogodki starejši od enega dne v preteklosti bodo prezrti + Dogodki starejši od %d dni v preteklosti bodo prezrti + Dogodki starejši od %d dni v preteklosti bodo prezrti + Dogodki starejši od %d dni v preteklosti bodo prezrti + + Dogodki, ki so v preteklosti več kot ta številka dni bodo prezrti (lahko je 0). Pusti prazno za sinhronizacijo vseh dogodkov. + Uredi barve koledarjev + Podpora barva dogodka + CardDAV + Metoda skupine kontaktov + Spremeni metodo skupine + + Ustvari imenik + Moj imenik + Ustvari koledar + Časovna zona + Mogoči koledarski vnosi + Dogodki + Naloge + Beležnice / dnevnik + Združeno ( dogodki in naloge) + Barva + Ustvarjenje zbirke + Naslov + Zahtevan je naslov + Opis + opcionalno + Lokacija shrambe + Ustvari + Izbriši zbirko + Si prepričan? + Ta zbirka (%s) in njena vsebina bodo za stalno izbrisane. + Ti podatki bodo izbrisani iz strežnika + Izbris zbirke + Prisili samo za branje + Lastnosti + Naslov (URL): + Kopiraj URL + + Informacije razhroščevalnika + + Zgodila se je napaka + Zgodila se je HTTP napaka. + I/O napaka se je zgodila. + Pokaži podrobnosti + + + Uporabniško ime + Geslo + + DAVx⁵ dovoljenja + Dodatna dovoljenja so zahtevana + Avtentikacija ni uspela (preverite podatke prijave) + Omrežna ali I/O napaka -- %s + HTTP strežniška napaka -- %s + Napaka lokalne shrambe -- %s + Poskusi ponovno + Prikaži predmet + S strežnika so bili prejeti neveljavni kontakti + S strežnika so bili prejeti neveljavni dogodki + S strežnika so bili prejeti neveljavni dogodki + Eden ali več neveljavnih virov bo ignoriranih + + DAVx⁵: Varnost povezave + DAVx⁵ je naletel na neznan certifikat. Ali mu zaupate? + diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index b47339b34..24bc913cd 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -2,28 +2,66 @@ ДАВдроид + Налог не постоји (више) ДАВдроид адресар Адресари + Уклони + Поништи + Ово поље је обавезно Помоћ Управљај налозима + Подели + База података је корумпирана + Сви налози су уклоњени локално. Тражење грешака Остале важне поруке + Статусне поруке ниског приоритета Синхронизација Грешке синхронизације + Упозорења синхронизације Мрежне и У/И грешке + Ваши подаци. Ваш избор. + Преузмите контролу. + Регуларни интервали синхронизације + Онемогућено (није препоручено) + Омогућено (препоручено) + Не требају ми регуларни интервали синхронизације.* + Овај уређај вероватно блокира синхронизацију. Ако је тако, овај проблем можете решити једино ручно. + Изменио сам потребна подешавања. Не подсећај ме више.* + * Остави непотврђено да би био подсетнут касније. Може бити ресетовано у подешавањима / %s. Још информација + Задаци + Не треба ми подршка за задатке.* + Софтвер отвореног кода + Не приказуј у блиској будућности + Дозволе + %s захтева дозволе да би исправно радила. + Све испод + Све дозволе су дате Дозволе за контакте + Без синхронизације контаката (није препоручено) Дозволе за календар Дозволе за задатке + Дозволе за задатке + Задржи дозволе + Подешавања апликације + Дозвола прецизне локације + Дозволи сво време + Локација је увек омогућена + Услуга локације је омогућена + Услуга локације је онемогућена + Преводи Библиотеке Издање %1$s (%2$d) Компилован %s Овај програм НЕМА НИКАКВЕ ГАРАНЦИЈЕ. Бесплатан је софтвер којег можете слободно да делите под одређеним условима. + Прегледај/подели + Онемогући Отвори навигациону фиоку Затвори навигациону фиоку @@ -32,14 +70,20 @@ Повратне информације бета издања Поставке Новости и ажурирања + Алати Вањске везе Веб-сајт Приручник ЧПП + Заједница Донирај + Политика приватности + Нема везе са интернетом. Андроид неће вршити синхронизацију. + Недовољно слободног простора. Андроид неће вршити синхронизацију. Добро дошли у ДАВдроид!\n\nМожете сада да додате КалДАВ/КардДАВ налог. Синхронизација је системски искључена Укључи + Синхронизуј све налоге Откривање услуге није успело Не могох да освежим списак збирки @@ -51,8 +95,11 @@ Прикажи податке за исправљање грешака Приказ/дељење детаља софтвера и поставки Исцрпна евиденција + Оптимизација батерије Повезивање Безбедност + Дозволе апликације + Прегледај дозволе неопходне за синхронизацију Посумњај у системске сертификате Системски и кориснички додати сертификати неће бити поуздани Системски и кориснички додати сертификати ће бити поуздани (препоручљиво) @@ -60,13 +107,26 @@ Ресетуј поуздање свих прилагођених сертификата Сви прилагођени сертификати су уклоњени Корисничко сучеље + Подешавања обавештења + Управљај каналима обавештења и њиховим подешавањима + Изабери тему + + Према систему + Светла + Тамна + Ресетуј савете Поновно приказивање претходно одбачених савета Сви савети ће поново бити приказани + Интеграција КардДАВ КалДАВ Вебкал + Дозволе + Нема именика (још увек). + Нема календара (још увек). + Повуците на доле да би сте освежили списак са сервера. Синхронизуј одмах Синхронизујем Поставке налога @@ -80,6 +140,8 @@ само-за-читање календар листа задатака + журнал + Прикажи само личне Освежи списак адресара Направи нови адресар Освежи списак календара @@ -88,8 +150,8 @@ Додај налог Пријавите се адресом е-поште - Е-адреса - Исправна е-адреса је обавезна + Адреса е-поште + Исправна адреса е-поште је обавезна Лозинка Лозинка је обавезна Пријавите се УРЛ-ом и корисничким именом @@ -105,7 +167,13 @@ Користите вашу е-адресу за назив налога јер Андроид користи назив налога за поље ОРГАНИЗАТОР за догађаје које направите. Не можете имати два налога истог назива. Режим група контаката: Назив налога је обавезан + Назив налога је већ заузет Не могох направити налог + Напредна пријава (посебни случајеви) + Користи корисничко име/лозинку + Користи сертификат клијента + Сертификат није пронађен + Инсталирај сертификат Откривање конфигурације Сачекајте, шаљем упит серверу… Не могох да нађем КалДАВ или КардДАВ услугу. @@ -134,6 +202,8 @@ Синхронизовање само преко %s Коришћење свих бежичних мрежа Имена (ССИД) дозвољених мрежа. одвојена зарезом (оставите празно за све мреже) + Управљај + Још информација (ЧПП) Аутентификација Корисничко име Унесите корисничко име: @@ -141,6 +211,7 @@ Ажурирајте лозинку за ваш сервер. Унесите лозинку: Псеудоним сертификата клијента + Није изабран сертификат КалДАВ Ограничење догађаја у прошлости Сви догађаји се синхронизују @@ -150,17 +221,30 @@ Догађаји старији од %d дана ће бити занемарени Догађаји старији од овог броја дана ће бити занемарени (може бити 0). Оставите празно за синхронизацију свих догађаја. + Предефинисани подсетник Управљај бојама календара Подршка за боју догађаја + Боје догађаја су синхронизоване + Боје догађаја нису синхронизоване КардДАВ Режим група контаката Измени режим група Направи адресар Мој адресар + Направи календар + Временска зона + Догађаји + Задаци Комбиновано (догађаји и задаци) + Боја Правим збирку + Наслов Наслов је обавезан + Опис + опционо + Локација складишта + Локација складишта је обавезна Направи Обриши збирку Да ли сте сигурни? @@ -169,8 +253,11 @@ Својства Адреса (УРЛ): Копирај УРЛ + Власник: Подаци за исправљање грешака + Прикажи детаље + Записи Прикажи записе Десила се грешка. @@ -179,6 +266,7 @@ Прикажи детаље + Име за приказ Корисничко име Лозинка diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml new file mode 100644 index 000000000..6899badc0 --- /dev/null +++ b/app/src/main/res/values-sv/strings.xml @@ -0,0 +1,423 @@ + + + + DAVx⁵ + Kontot finns inte (längre) + DAVx⁵ Adressbok + Adressböcker + Ta bort + Avbryt + Detta fālt är obligatoriskt + Hjälp + Hantera konton + Dela + Databasen är korrupt + Alla konton har blivit borttagna lokalt. + Felsökning + Andra viktiga meddelanden + Statusmeddelanden med låg prioritet + Synkronisering + Synkroniseringsfel + Viktiga fel som stoppar synkronisering, såsom oväntade serversvar + Synkroniseringsvarningar + Icke allvarliga synkroniseringsfel såsom vissa felaktiga filer + Nätverk och I/O fel + Tidsgräns eller anslutningsproblem etc. (ofta temporärt) + + Din data. Ditt val. + Ta kontroll + Regelbundna synkroniseringsintervall + Inaktiverat (ej rekommenderat) + Aktiverat (rekommenderat) + För att programmet skall kunna köra regelbunden synkronisering %s måste det tillåtas att köra i bakgrunden. Annars kan Android pausa synkroniseringen när som helst. + Jag behöver inte regelbunden synkronisering.* + %s kompatibilitet + Den här enheten blockerar troligen synkronisering. Om du är drabbad måste det lösas manuellt. + Jag har gjort alla inställningar som behövs. Påminn mig inte igen.* + * Låt stå för att påminna mig senare. Kan bli återställt i appens inställningar / %s. + Mer information + jtx Bord + + Ärendestöd + Om ärenden stöds av din server kan de synkroniseras med en ärendeapp som stöds: + OpenTasks + ytterligare appar .]]> + Tasks + stöds inte (ännu).]]> + Ingen app butik tillgänglig + Jag behöver inte stöd för att-göra.* + Öppen källkod mjukvara + Vi är glada att du använder %s som är mjukvara med öppen källkod. Utveckling och drift innebär hårt arbete. Bidra gärna på något sätt (det finns många sätt) eller donera. Det skulle vara mycket hjälpsamt! + Hur man kan bidra/donera + Visa inte inom en snar framtid + + Behörigheter + %s behöver behörighet för att kunna fungera + Allt nedanstående + Använd detta för att aktivera alla funktioner (rekommenderat) + Alla behörigheter godkända + kontaktbehörigheter + Synkronisera inte kontakter (ej rekommenderat) + Synkronisering av kontakter möjlig + Kalenderbehörigheter + Synkronisera inte kalendern (ej rekommenderat) + Synkronisering av kalender möjlig + jtx Bordsbehörigheter + Ingen uppgift, journaler & anteckningssynkronisering (ej installerad) + Ingen synkronisering av uppgifter, journaler, anteckningar + Synkronisering av uppgifter, journaler, anteckningar är möjlig + OpenTasks-behörigheter + Tasks behörighet + Ingen synkronisering av uppgifter (ej installerat) + Ingen synkronisering av uppgifter + Uppgiftssynronisering möjlig + Behåll behörigheter + Behörigheter kan återställas automatiskt (rekommenderas inte) + Behörigheterna återställs inte automatiskt + Klicka på Behörigheter > avmarkera \"Ta bort behörigheter om appen inte används\" + Om en brytare inte fungerar, använd app-inställningar->behörigheter + App-inställningar + + WiFi SSID-behörigheter + För att kunna komma åt det aktuella WiFi-namnet (SSID) måste dessa villkor vara uppfyllda: + Behörighet för exakt plats + Behörighet för platsdata beviljat + Behörighet för platsdata nekad + Behörighet för platsdata i bakgrunden + Tillåt hela tiden + %s ]]> + %s ]]> + %s använder platsbehörigheten endast för att bestämma den aktuella WiFi:s SSID för konton med SSID-begränsning. Detta kommer att hända även när appen är i bakgrunden. Ingen platsdata samlas in, lagras, bearbetas eller skickas någonstans. + Plats alltid påslagen + Platstjänster är påslagna + Platstjänster är avstängda + + Översättningar + Bibliotek + Version %1$s (%2$d) + Kompilerad på %s + © Ricki Hirner, Bernhard Stockmann (bitfire web engineering GmbH) och bidragsgivare + Den här versionen är endast berättigad för distribution genom Google Play + Detta program levereras med ABSOLUT INGEN GARANTI. Det är fri programvara, och du kan vidaredistribuera den under vissa förutsättningar. + Tack till: %s ]]> + + Kunde inte skapa loggfil + Loggar nu alla %s aktiviteter + Visa/dela + Inaktivera + + Öppna navigeringslådan + Stäng navigeringslådan + CalDAV/CardDAV Synk Adapter + Om / Licens + Betafeedback + Installera en e-postklient + Installera en webbläsare + Inställningar + Nyheter & uppdateringar + Verktyg + Externa länkar + Websida + Manual + FAQ + Gemenskap + Donera + Integritetspolicy + Ingen internetanslutning. Android kommer inte att köra synkronisering. + Lagringsutrymme lågt. Android kommer inte att köra synkronisering. + Välkommen till DAVx⁵!\n\nDu kan lägga till ett CalDAV/CardDAV-konto nu. + Systemomfattande automatisk synkronisering är inaktiverad + Aktivera + Synkronisera alla konton + + Servicedetektering misslyckades + Det gick inte att uppdatera samlingslistan + + Kan inte köras i förgrunden + Vitlista för batterioptimering krävs + + Arbetar i förgrunden + På vissa enheter är detta nödvändigt för automatisk synkronisering. + + Inställningar + Felsökning + Visa felsökningsinformation + Visa/dela programvara och konfigurationsdetaljer + Omfattande loggning + Loggning är påslagen + Loggning är avstängd + Batterioptimering + Appen är vitlistad (rekommenderat) + Appen är inte vitlistad (rekommenderas ej) + Håll i förgrunden + Kan hjälpa om din enhet förhindrar automatisk synkronisering + Anslutning + Proxy typ + + Systemstandard + Ingen proxy + HTTP + SOCKS (för Orbot) + + Proxy hostnamn + Proxy port + Säkerhet + App behörigheter + Granska behörigheter som krävs för synkronisering + Misstro systemcertifikat + System- och användartillagda certifikatutfärdare kommer inte att vara betrodda + System- och användartillagda certifikatutfärdare kommer att vara betrodda (rekommenderat) + Återställ (o)betrodda certifikat + Återställer förtroendet för alla anpassade certifikat + Alla anpassade certifikat har rensats + Användargränssnitt + Aviseringsinställningar + Hantera aviseringskanaler och deras inställningar + Välj tema + + Systemstandard + Ljus + Mörk + + Återställ tips + Återaktiverar tips som har avvisats tidigare + Alla tips kommer visas igen + Integrering + Tasks appen + Synkroniserar med %s + Ingen kompatibel task-app hittades + + CardDAV + CalDAV + Webcal + Ingen synkronisering av kontakter (saknar behörigheter) + Ingen synkronisering av kalender (saknar behörigheter) + Ingen synkronisering av uppgifter (saknar behörigheter) + Ingen kalender eller uppgiftssynkronisering (saknade behörigheter) + Kan inte komma åt kalendrar (saknade behörigheter) + Behörigheter + Det finns inga adressböcker (ännu). + Det finns inga kalendrar (ännu). + Det finns inga kalenderprenumerationer (ännu). + Svep nedåt för att uppdatera listan från servern. + Synkronisera nu + Synkroniserar nu + Kontoinställningar + Byt namn på kontot + Lokala data som inte har sparats kan avvisas. Omsynkronisering krävs efter byte av namn. Nytt kontonamn: + Byt namn + Kunde inte ändra namn på kontot + Ta bort kontot + Vill du verkligen ta bort kontot? + Alla lokala kopior av adressböcker, kalendrar och uppgiftslistor kommer att raderas. + synkronisera denna samling + skrivskyddad + kalender + uppgiftslista + Journal + Visa endast personligt + Uppdatera adressbokslistan + Skapa ny adressbok + Uppdatera kalenderlistan + Skapa ny kalender + Ingen Webcal-kompatibel app hittades + Installera ICSx⁵ + + Lägg till konto + Logga in med e-postadress + E-postadress + Giltig e-postadress krävs + Lösenord + Lösenord krävs + Logga in med URL och användarnamn + URL måste börja med http(s):// + Användarnamn + Användarnamn krävs + Bas-URL + Logga in med URL och klientcertifikat + Välj certifikat + Logga in + Skapa konto + Kontonamn + Användning av apostrof (\'), har rapporterats orsaka problem på vissa enheter. + Använd din e-postadress som kontonamn eftersom Android kommer att använda kontonamnet som fält för ARRANGÖR för händelser du skapar. Du kan inte ha två konton med samma namn. + Kontaktgruppsmetod: + Konto namn krävs + Kontonamn är upptaget + Konto kunde inte skapas + Avancerad inloggning (särskilda användningsfall) + Använd användarnamn/lösenord + Använd klientcertifikat + Inget certifikat funnet + Installera certifikat + Konfigurationsdetektering + Vänligen vänta, frågar efter server... + Det gick inte att hitta CalDAV eller CardDAV-tjänsten. + Användarnamn (e-postadress) / lösenord är fel? + Visa detaljer + + Inställningar: %s + Synkronisering + Intervall för kontaktsynkronisering + Bara manuellt + Var %d minut + omedelbart på lokala förändringar + Intervall för kalendersynkronisering + Intervall för uppgiftssynkronisering + + Endast manuellt + Var 15:e minut + Var 30:e minut + Varje timme + Var 2:e timme + Var 4:e timme + En gång om dagen + + Synkronisera endast via WiFi + Synkronisering är begränsad till WiFi-anslutningar + Anslutningstyp beaktas inte + WiFi SSID-begränsning + Synkroniserar endast över %s + Synkroniseras endast över %s (kräver aktiva platstjänster) + Alla WiFi-anslutningar kommer att användas + Kommaseparerade namn (SSID) för tillåtna WiFi-nätverk (lämna tomt för alla) + WiFi SSID-begränsning kräver ytterligare inställningar + Hantera + Mer information (FAQ) + Autentisering + Användarnamn + Skriv in användarnamn + Lösenord + Uppdatera lösenordet enligt din server. + Ange ditt lösenord: + Klientcertifikatalias + Inget certifikat valt + CalDAV + Tidsgräns för tidigare händelser + Alla händelser kommer att synkroniseras + + Händelser mer än en dag i det förflutna kommer att ignoreras + Händelser mer än %d dagar i det förflutna kommer att ignoreras + + Händelser som är fler än detta antal dagar i det förflutna kommer att ignoreras (kan vara 0). Lämna tomt för att synkronisera alla händelser. + Standardpåminnelse + + Standard påminnelse en minut före händelsen + Standard påminnelse %d minuter före händelsen + + Inga standardpåminnelser är skapade + Om standardpåminnelser ska skapas för händelser utan påminnelse: önskat antal minuter före händelsen. Lämna tomt för att inaktivera standardpåminnelser. + Hantera kalenderfärger + Kalenderfärger nollställs vid varje synkronisering + Kalenderfärger kan sättas av andra appar. + Stöd för händelsefärger + Händelsefärger synkroniseras + Händelsefärger synkroniseras inte + CardDAV + Kontaktgruppsmetod + + Grupper är separata vCards + Grupper är per-kontaktkategorier + + Ändra gruppmetod + + Skapa adressbok + Min adressbok + Skapa kalender + Tidzon + Möjliga kalenderposter + Händelser + Ärenden + Anteckningar / journal + Kombinerat (händelser och ärenden) + Färg + Skapar samling + Titel + Titel krävs + Beskrivning + valfritt + Lagringsplats + Lagringsplats krävs + Skapa + Ta bort samling + Är du säker? + Denna samling(%s) och all dess data tas bort permanent. + Denna data blir borttagen från servern. + Tar bort samling + Tvinga endast läsning + Egenskaper + Adress (URL): + Kopiera URL + Ägare: + + Felsöknings information + ZIP arkiv + Innehåller felsökningsinformation och loggar + Dela arkivet för att överföra det till en dator, för att skicka det via e-post eller för att bifoga det till ett supportärende. + Dela arkiv + Felsökningsinformation bifogad i det här meddelandet (kräver stöd för bilagor från den mottagande appen). + HTTP-fel + Server-fel + WebDAV-fel + I/O-fel + Begäran har avslagits. Kontrollera involverade resurser och felsökningsinformation för detaljer. + Den begärda resursen finns inte (längre). Kontrollera involverade resurser och felsökningsinformation för detaljer. + Ett problem på serversidan uppstod. Kontakta din serversupport. + An unexpected error has occured. View debug info for details.  + Visa detaljer + Felsökningsinformation har samlats in + Inblandade resurser + Relaterat till problemet + Fjärrresurs: + Lokal resurs: + Visa med appen + Loggar + Utförliga loggar finns tillgängliga + Visa loggar + + Ett fel har uppstått. + Ett HTTP-fel har uppstått. + Ett I/O-fel har uppstått. + Visa detaljer + + Synkronisering pausad + Nästan inget ledigt utrymme kvar + + WebDAV-fästen + Använd kvot: %1$s / tillgängligt: %2$s + Dela innehåll + Avmontera + Lägg till WebDAV-fäste + Direkt åtkomst till dina filer i molnet genom att lägga till en WebDAV montering! + hur WebDAV monteringar fungerar .]]> + Visningsnamn + WebDAV URL + Felaktig URL + Användarnamn + Lösenord + Lägg till fäste + Ingen WebDAV-tjänst på denna URL + Ta bort monteringspunkt + Anslutningsdetealjer kommer att gå förlorade men inga filer tas bort. + Åtkomst till WebDAV-fil + Laddar ner WebDAV-fil + Laddar upp WebDAV-fil + WebDAV-fäste + + DAVx⁵-behörigheter + Ytterligare behörigheter krävs + %s för gammal + Minsta obligatoriska version: %1$s + Autentisering misslyckades (kontrollera inloggningsuppgifterna) + Nätverks- eller I/O-fel - %s + HTTP server fel - %s + Lokalt lagringsfel - %s + Försök igen + Visa objekt + Fick ogiltig kontakt från servern + Fick ogiltig händelse från servern + Fick ogiltigt ärende från servern + Ignorerar en eller flera ogiltiga resurser + + DAVx⁵: Anslutningssäkerhet + DAVx⁵ har stött på ett okänt certifikat. Vill du lita på det? + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b321324a0..81a63e0ee 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -2,37 +2,54 @@ DAVx⁵ - 賬戶不存在 (anymore) + 帳號(已)不存在 DAVx⁵ 通訊錄 通訊錄 + 此為必填欄位 幫助 管理帳號 + 分享 + 資料庫損毀 + 所有帳號已在本地刪除 除錯 其他重要訊息 + 低優先的狀態訊息 同步 同步錯誤 - 同步中止,由於伺服器響應不尋常等原因而出錯 + 導致同步停止的嚴重錯誤,如異常的伺服器回應 同步警告 - 可忽略的同步問題,比如一些無效文件 - 網際網絡和輸入輸出錯誤 - 超時,連接問題等(臨時問題) + 可忽略的同步問題,比如一些無效檔案 + 網路和輸入輸出錯誤 + 逾時、連線問題等等(通常為暫時性) - 自已數據自已揀 - - 量力而為 + 您的資料,您的選擇 + 權力在握 定期同步間隔 - 煞停 (不建議) - 推進 (建議) - 我不需要定期同步間隔 - 裝置可能解除了同步功能。如果你正受影響,請手動解決此問題。 - 所需設定已完成,不用再提醒我 - 更多訊息 + 停用(不建議) + 啟用(建議) + 為了定期進行同步,必須允許 %s 在背景運行,否則 Android 可能會隨時暫停同步。 + 我不需要定期同步間隔* + %s 相容性 + 該裝置可能阻擋了同步,若您受到影響,只能手動解決。 + 所需設定已完成,不用再提醒我* + * 取消勾選則稍後會再次提醒,可於設定中重置 / %s + 更多資訊 + + 待辦事項支援 + 如果你的服務器支持任務,它們可以與支援任務的app同步: + 額外的app.]]> + 任務 + 尚未支援]]> + 沒有應用商店可用 + 通訊錄權限 + 行事曆權限 + OpenTasks 權限 - - 版本號%1$s(%2$d) - 在%s上進行編譯 + 函式庫 + 版本號 %1$s(%2$d) + 編譯於 %s 本功能僅在Google Play上面發行的程式上可用。 我們「完全不保證」本程式無瑕疵。這是個自由軟體,歡迎您在符合公用授權條款的情況下任意散布它。 @@ -51,7 +68,6 @@ 我們的網站 使用説明書 常見問答 - 幫助/論壇 贊助我們 隱私權政策 網際網絡沒有連接。Android不會進行同步。 @@ -61,21 +77,18 @@ 未發現遠端服務 無法更新清單 + 設定 除錯 顯示除錯訊息 檢視/分享本軟體及設定檔細節 - 多餘的除錯訊息 - 除錯訊息記錄在活動狀態 - 除錯訊息記錄在關閉狀態 + 詳細除錯記錄 + 日誌記錄已啟用 + 日誌記錄已停用 + 電池最佳化 網路連線 - 自訂代理伺服器 - 正在使用自訂的代理伺服器設定值 - 正在使用系統預設的代理伺服器設定值 - HTTP 代理伺服器主機名稱或網址 - HTTP 代理伺服器通訊埠 安全性 不信任系統憑證 系統憑證和使用者自訂憑證將不被信任 @@ -93,27 +106,29 @@ CardDAV聯絡人檔案 CalDav行事曆檔案 Webcal網際網絡行事曆 - (目前)沒有地址簿。 - (目前)沒有行事曆。 - (目前)沒有行事曆訂閲。 - 下劃更新伺服器上面的列表 + (目前)沒有通訊錄 + (目前)沒有行事曆 + (目前)沒有行事曆訂閲 + 下拉可從伺服器獲取最新清單 立即同步 同步中 帳號設定 重新命名帳號 - 尚未儲存的本地資料可能會消失。重新命名後必須再次執行同步。新的帳號名稱: + 尚未儲存的本地資料可能會消失。重新命名後必須再次執行同步。新的帳號名稱: 重新命名 + 無法重新命名帳號 刪除帳號 - 真的要刪除帳號? + 確定要刪除帳號? 這台裝置上這個帳號的通訊錄、行事曆和工作清單將被刪除。 同步這個行事曆或工作清單 - 只讀 + 唯讀 行事曆 - 事項清單 - 刷新通訊錄清單 + 待辦事項 + 只顯示個人 + 更新通訊錄清單 建立新的通訊錄 - 刷新行事曆清單 - 建立新的行事曆 + 更新行事曆清單 + 建立新行事曆 未找到支援Webcal的APP 安裝ICSx⁵ @@ -149,7 +164,7 @@ 只手動同步 每 %d 分鐘,以及在本裝置上修改時 行事曆同步間隔 - 工作清單同步間隔 + 待辦事項同步間隔 僅手動 每15分鐘自動 @@ -162,35 +177,37 @@ 只用 WiFi 同步 只於 WiFi 連線時同步 任何網路連線都可使用 - 特定的 WiFi SSID 連線 + 限用特定 WiFi SSID 只在%s連線時同步 - 只在%s連線時同步(需要開啓的定位服務) + 只在%s連線時同步(需要啟用定位服務) 所有 WiFi 連線都可以使用 - 使用逗號分割的名稱 (SSIDs) 表示的 WiFi 連綫(留空則代表全部) - 更多訊息(FAQ) - 登入驗證 + 使用逗號分割的名稱 (SSIDs) 表示的 WiFi 連線(留空則代表全部) + 管理 + 更多資訊(常見問題) + 認證 使用者帳號 輸入帳號名稱: 密碼 您在伺服器上使用中的密碼 - 輸入密碼: - 客戶端鑒權別名 - CalDav(行事曆檔案) - 過去項目的時間限制 - 將會同步所有項目 + 輸入密碼: + 客戶端憑證別名 + 未選擇憑證 + CalDAV + 過去活動的時間限制 + 將會同步所有活動 - %d 天之前的項目會被忽略 + %d 天之前的活動會被忽略 - 這個天數之前的項目將被忽略 (可設為0)。留白,則所有項目都會同步。 - 默認的提醒方式 + 此天數前的活動將會被忽略(可設為零),若留空則同步所有活動 + 預設提醒 - 事項%d分鐘之前的默認提醒方式 + 預設在活動前 %d 分鐘提醒 - 未創建默認的提醒方式 - 如果默認的提醒方式在創建時沒有這一項:在事項前幾分鐘,就可以留空來關閉默認的提醒方式。 + 未設定預設提醒 + 當沒有提醒的活動需要加入預設提醒時,活動開始前多少分鐘出發提醒。留空則停用預設提醒。 管理行事曆的顏色 - 設定事項的顔色 - CardDAV(聯絡人檔案) + 設定活動的顔色 + CardDAV 聯絡人群組的儲存格式 群組存成額外的 VCard 檔案 @@ -200,12 +217,12 @@ 建立通訊錄 我的通訊錄 - 創建行事曆 + 建立行事曆 時區 - 獲取行事曆 - 事件 - 任務 - 筆記/日志 + 可使用的行事曆項目 + 活動 + 事務 + 筆記/日誌 合併 (事件和任務) 顔色 建立新行事曆或工作清單 @@ -231,6 +248,10 @@ HTTP 發生錯誤 讀寫錯誤 顯示細節 + + + 使用者帳號 + 密碼 DAVx⁵ 權限 需要額外的權限 diff --git a/fastlane/metadata/android/fr-FR/full_description.txt b/fastlane/metadata/android/fr-FR/full_description.txt new file mode 100644 index 000000000..2ab5b8357 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/full_description.txt @@ -0,0 +1,5 @@ +DAVx⁵ est une application de gestion et synchronisation CalDAV/CardDAV sous Android compatible avec les application de contact et les calendriers Android. + +Utilisez-la avec votre serveur personnel ou un hôte de confiance pour garder vos contacts, événements et tâches sous contrôle. + +Pour plus d'information et pour consulter la liste des serveurs/services testés consultez le site web. \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/short_description.txt b/fastlane/metadata/android/fr-FR/short_description.txt new file mode 100644 index 000000000..b0bc47afc --- /dev/null +++ b/fastlane/metadata/android/fr-FR/short_description.txt @@ -0,0 +1 @@ +Synchronisation et Client CalDAV/CardDAV \ No newline at end of file diff --git a/fastlane/metadata/android/hr/full_description.txt b/fastlane/metadata/android/hr/full_description.txt new file mode 100644 index 000000000..bf73d070c --- /dev/null +++ b/fastlane/metadata/android/hr/full_description.txt @@ -0,0 +1,5 @@ +DAVx⁵ je aplikacija za upravljanje i sinkronizaciju CalDAV / CardDAV za Android koja se izvorno integrira s Android kalendarom / aplikacijama za kontakt. + +Koristite ga s vlastitim poslužiteljem ili s pouzdanom uslugom iznajmljivanja poslužitelja kako biste svoje kontakte, događaje i zadatke držali pod svojom kontrolom. + +Za više informacija i popis testiranih poslužitelja / usluga pogledajte na web lokaciji. \ No newline at end of file diff --git a/fastlane/metadata/android/hr/short_description.txt b/fastlane/metadata/android/hr/short_description.txt new file mode 100644 index 000000000..c806f24be --- /dev/null +++ b/fastlane/metadata/android/hr/short_description.txt @@ -0,0 +1 @@ +CalDAV / CardDAV sinkronizacija i klijent \ No newline at end of file diff --git a/fastlane/metadata/android/it/full_description.txt b/fastlane/metadata/android/it/full_description.txt new file mode 100644 index 000000000..67c57cb70 --- /dev/null +++ b/fastlane/metadata/android/it/full_description.txt @@ -0,0 +1,5 @@ +DAVx⁵ è un'applicazione CalDAV/CardDAV di controllo e sincronizzazione per Android che è nativamente integrata con le applicazione Android di calendario/contatti. + +Utilizzalo con il tuo server o con un ospite fidato per mantenere sotto controllo i tuoi contatti, aventi o attività. + +Per maggiori informazioni e per una lista di server/servizi testati, guarda nel sito Web. \ No newline at end of file diff --git a/fastlane/metadata/android/ko/full_description.txt b/fastlane/metadata/android/ko/full_description.txt new file mode 100644 index 000000000..83e5966a4 --- /dev/null +++ b/fastlane/metadata/android/ko/full_description.txt @@ -0,0 +1,5 @@ +DAVx²는 안드로이드용 CalDAV/CardDAV 관리 및 동기화 앱으로 안드로이드 캘린더/연락처 앱과 기본적으로 통합된다. + +연락처, 이벤트 및 작업을 제어하기 위해 자신의 서버 또는 신뢰할 수 있는 호스트에게 사용합니다. + +자세한 내용과 테스트된 서버/서비스 목록은 웹 사이트를 참조하십시오. \ No newline at end of file diff --git a/fastlane/metadata/android/ko/short_description.txt b/fastlane/metadata/android/ko/short_description.txt new file mode 100644 index 000000000..998e8dcc8 --- /dev/null +++ b/fastlane/metadata/android/ko/short_description.txt @@ -0,0 +1 @@ +CalDAV/CardDAV 동기화 및 클라이언트 \ No newline at end of file diff --git a/fastlane/metadata/android/ru/full_description.txt b/fastlane/metadata/android/ru/full_description.txt index 52a9186ff..a85b5a55a 100644 --- a/fastlane/metadata/android/ru/full_description.txt +++ b/fastlane/metadata/android/ru/full_description.txt @@ -2,4 +2,4 @@ DAVx⁵ - приложение для управления и синхрониз Используйте его с вашим собственным сервером или доверенным хостером, чтобы держать ваши контакты, события и задачи под контролем. -Для получения дополнительной информации и списка протестированных серверов/служб, посетите веб-сайт. \ No newline at end of file +Для получения дополнительной информации и списка протестированных серверов/служб, посетите сайт. \ No newline at end of file diff --git a/fastlane/metadata/android/si/short_description.txt b/fastlane/metadata/android/si/short_description.txt new file mode 100644 index 000000000..eaf7241fd --- /dev/null +++ b/fastlane/metadata/android/si/short_description.txt @@ -0,0 +1 @@ +CalDAV/CardDAV සමමුහූර්තය හා අනුග්‍රාහකය \ No newline at end of file diff --git a/fastlane/metadata/android/sl-SI/full_description.txt b/fastlane/metadata/android/sl/full_description.txt similarity index 100% rename from fastlane/metadata/android/sl-SI/full_description.txt rename to fastlane/metadata/android/sl/full_description.txt diff --git a/fastlane/metadata/android/sl-SI/short_description.txt b/fastlane/metadata/android/sl/short_description.txt similarity index 100% rename from fastlane/metadata/android/sl-SI/short_description.txt rename to fastlane/metadata/android/sl/short_description.txt diff --git a/fastlane/metadata/android/sr/full_description.txt b/fastlane/metadata/android/sr/full_description.txt new file mode 100644 index 000000000..5f61de44a --- /dev/null +++ b/fastlane/metadata/android/sr/full_description.txt @@ -0,0 +1,5 @@ +DAVx⁵ је апликација за управљање и синхорнизацију КалДАВ/КардДАВ-а за Андроид која се нормално интегрише са Адроид календар/контакт апликацијама. + +Користите је са својим сервером или са добављачем од поверења да би сте држали своје контакте, догађаје и задатке под контролом. + +За више информација и листу проверених сервера/услуга, погледајте веб-сајт. \ No newline at end of file diff --git a/fastlane/metadata/android/sr/short_description.txt b/fastlane/metadata/android/sr/short_description.txt new file mode 100644 index 000000000..577945d3a --- /dev/null +++ b/fastlane/metadata/android/sr/short_description.txt @@ -0,0 +1 @@ +КалДАВ/КардДАВ синхронизација и клијент \ No newline at end of file diff --git a/fastlane/metadata/android/sv/full_description.txt b/fastlane/metadata/android/sv/full_description.txt new file mode 100644 index 000000000..1643af3b4 --- /dev/null +++ b/fastlane/metadata/android/sv/full_description.txt @@ -0,0 +1,5 @@ +DAVx⁵ är en CalDAV/CardDAV-hanterings- och synkroniseringsapp för Android som integreras med Android-kalender-/kontaktappar. + +Använd den med din egen server eller med en betrodd värd för att hålla dina kontakter, händelser och uppgifter under din kontroll. + +För mer information och en lista över testade servrar/tjänster, ta en titt på webbplatsen. \ No newline at end of file diff --git a/fastlane/metadata/android/sv/short_description.txt b/fastlane/metadata/android/sv/short_description.txt new file mode 100644 index 000000000..71feec5f1 --- /dev/null +++ b/fastlane/metadata/android/sv/short_description.txt @@ -0,0 +1 @@ +CalDAV/CardDAV Synkronisering och klient \ No newline at end of file diff --git a/scripts/fetch-translations.sh b/scripts/fetch-translations.sh index 8b95b454d..2f5502c87 100755 --- a/scripts/fetch-translations.sh +++ b/scripts/fetch-translations.sh @@ -2,7 +2,7 @@ TX_TOKEN=`awk '/password =/ { print $3; }' <$HOME/.transifexrc` -(cd .. && tx pull -f) +(cd .. && tx pull -a --use-git-timestamps) curl -H "Authorization: Bearer $TX_TOKEN" 'https://rest.api.transifex.com/team_memberships?filter\[organization\]=o:bitfireAT&filter\[team\]=o:bitfireAT:t:davx5-team' \ | ./rewrite-translators.rb >../app/src/main/assets/translators.json -- GitLab From 9bd564b2c6f461f05ae6282f2fae47cc8d60c162 Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Thu, 13 Oct 2022 16:34:47 +0200 Subject: [PATCH 20/49] fix crash when accounts vanish (closes bitfireAT/davx5#140) (bitfireAT/davx5#148) --- .../davdroid/resource/LocalAddressBook.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt index c49a1cbda..7e4e28f08 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt @@ -75,13 +75,19 @@ open class LocalAddressBook( return addressBook } + /** + * Finds and returns all the local address books belonging to a given main account + * + * @param mainAccount the main account to use + * @return list of [mainAccount]'s address books + */ fun findAll(context: Context, provider: ContentProviderClient?, mainAccount: Account) = AccountManager.get(context) .getAccountsByType(context.getString(R.string.account_type_address_book)) .map { LocalAddressBook(context, it, provider) } .filter { try { it.mainAccount == mainAccount - } catch(e: IllegalStateException) { + } catch(e: IllegalArgumentException) { false } } @@ -110,6 +116,13 @@ open class LocalAddressBook( return bundle } + /** + * Finds and returns the main account of the given address book's account (sub-account) + * + * @param account the address book account to find the main account for + * @return the associated main account + * @throws IllegalArgumentException if the given account is not a address book account or does not have a main account + */ fun mainAccount(context: Context, account: Account): Account = if (account.type == context.getString(R.string.account_type_address_book)) { val manager = AccountManager.get(context) @@ -144,7 +157,7 @@ open class LocalAddressBook( private var _mainAccount: Account? = null /** - * The associated main account which this address book accounts belongs to. + * The associated main account which this address book's accounts belong to. * * @throws IllegalArgumentException when [account] is not an address book account or when no main account is assigned */ -- GitLab From 0f124cf5b5aae71aec1006aa096c7582a0b5a1e2 Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Fri, 21 Oct 2022 12:29:19 +0200 Subject: [PATCH 21/49] LocalAddressBook: update read-only flag of groups, too (bitfireAT/davx5#153) * LocalAddressBook: update read-only flag of groups, too Co-authored-by: Ricki Hirner --- .../java/at/bitfire/davdroid/resource/LocalAddressBook.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt index 7e4e28f08..3244d9553 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt @@ -253,6 +253,11 @@ open class LocalAddressBook( val dataValues = ContentValues(1) dataValues.put(ContactsContract.Data.IS_READ_ONLY, if (nowReadOnly) 1 else 0) provider!!.update(syncAdapterURI(ContactsContract.Data.CONTENT_URI), dataValues, null, null) + + // update group rows + val groupValues = ContentValues(1) + groupValues.put(Groups.GROUP_IS_READ_ONLY, if (nowReadOnly) 1 else 0) + provider!!.update(groupsSyncUri(), groupValues, null, null) } // make sure it will still be synchronized when contacts are updated -- GitLab From 951c29e66a8a62e0f7cfaee9bc673e244dbd484f Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 21 Oct 2022 13:39:49 +0200 Subject: [PATCH 22/49] Force sync after resetting read-only contacts (bitfireAT/davx5#154) * Force sync after resetting read-only contacts * Rename variable for clarity --- .../syncadapter/ContactsSyncManager.kt | 14 ++++++++++-- .../davdroid/syncadapter/SyncManager.kt | 22 ++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt index 2401a0a0d..09c3abb0f 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt @@ -166,31 +166,38 @@ class ContactsSyncManager( override fun processLocallyDeleted() = if (readOnly) { + var modified = false for (group in localCollection.findDeletedGroups()) { Logger.log.warning("Restoring locally deleted group (read-only address book!)") localExceptionContext(group) { it.resetDeleted() } + modified = true } for (contact in localCollection.findDeletedContacts()) { Logger.log.warning("Restoring locally deleted contact (read-only address book!)") localExceptionContext(contact) { it.resetDeleted() } + modified = true } - false + modified } else // mirror deletions to remote collection (DELETE) super.processLocallyDeleted() override fun uploadDirty(): Boolean { + var modified = false + if (readOnly) { for (group in localCollection.findDirtyGroups()) { Logger.log.warning("Resetting locally modified group to ETag=null (read-only address book!)") localExceptionContext(group) { it.clearDirty(null, null) } + modified = true } for (contact in localCollection.findDirtyContacts()) { Logger.log.warning("Resetting locally modified contact to ETag=null (read-only address book!)") localExceptionContext(contact) { it.clearDirty(null, null) } + modified = true } } else @@ -198,7 +205,10 @@ class ContactsSyncManager( groupStrategy.beforeUploadDirty() // generate UID/file name for newly created contacts - return super.uploadDirty() + var superModified = super.uploadDirty() + + // return true when any operation returned true + return modified or superModified } override fun generateUpload(resource: LocalAddress): RequestBody = diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt index 443f75ba7..41c07d4c4 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt @@ -155,8 +155,8 @@ abstract class SyncManager, out CollectionType: L Logger.log.info("Querying server capabilities") var remoteSyncState = queryCapabilities() - Logger.log.info("Sending local deletes/updates to server") - val modificationsSent = processLocallyDeleted() || uploadDirty() + Logger.log.info("Processing local deletes/updates") + val modificationsPresent = processLocallyDeleted() || uploadDirty() if (extras.containsKey(SyncAdapterService.SYNC_EXTRAS_FULL_RESYNC)) { Logger.log.info("Forcing re-synchronization of all entries") @@ -169,14 +169,14 @@ abstract class SyncManager, out CollectionType: L localCollection.forgetETags() } - if (modificationsSent || syncRequired(remoteSyncState)) + if (modificationsPresent || syncRequired(remoteSyncState)) when (syncAlgorithm()) { SyncAlgorithm.PROPFIND_REPORT -> { Logger.log.info("Sync algorithm: full listing as one result (PROPFIND/REPORT)") resetPresentRemotely() // get current sync state - if (modificationsSent) + if (modificationsPresent) remoteSyncState = querySyncState() // list and process all entries at current sync state (which may be the same as or newer than remoteSyncState) @@ -305,9 +305,12 @@ abstract class SyncManager, out CollectionType: L protected abstract fun queryCapabilities(): SyncState? /** - * Processes locally deleted entries and forwards them to the server (HTTP `DELETE`). + * Processes locally deleted entries. This can mean: * - * @return whether resources have been deleted from the server + * - forwarding them to the server (HTTP `DELETE`) + * - resetting their local state so that they will be downloaded again because they're read-only + * + * @return whether local resources have been processed so that a synchronization is always necessary */ protected open fun processLocallyDeleted(): Boolean { var numDeleted = 0 @@ -342,9 +345,12 @@ abstract class SyncManager, out CollectionType: L } /** - * Uploads locally modified resources to the server. + * Processes locally modified resources to the server. This can mean: + * + * - uploading them to the server (HTTP `PUT`) + * - resetting their local state so that they will be downloaded again because they're read-only * - * @return whether resources have been uploaded + * @return whether local resources have been processed so that a synchronization is always necessary */ protected open fun uploadDirty(): Boolean { var numUploaded = 0 -- GitLab From a493f0a9a9ef3011d2709267effd070e988cde71 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 21 Oct 2022 13:39:49 +0200 Subject: [PATCH 23/49] Update dependencies --- app/build.gradle | 4 ++-- build.gradle | 2 +- ical4android | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dcbaff394..e0f008985 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -123,7 +123,7 @@ dependencies { implementation 'androidx.security:security-crypto:1.1.0-alpha03' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'com.google.android.flexbox:flexbox:3.0.0' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.google.android.material:material:1.7.0' def room_version = '2.4.3' implementation "androidx.room:room-runtime:$room_version" @@ -161,7 +161,7 @@ dependencies { androidTestImplementation 'androidx.test:rules:1.4.0' androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3' androidTestImplementation "com.squareup.okhttp3:mockwebserver:${versions.okhttp}" - androidTestImplementation 'io.mockk:mockk-android:1.13.1' + androidTestImplementation 'io.mockk:mockk-android:1.13.2' androidTestImplementation 'junit:junit:4.13.2' testImplementation "com.squareup.okhttp3:mockwebserver:${versions.okhttp}" diff --git a/build.gradle b/build.gradle index f51033204..394805e25 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' + classpath 'com.android.tools.build:gradle:7.3.1' classpath "com.google.dagger:hilt-android-gradle-plugin:${versions.hilt}" classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${versions.aboutLibraries}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" diff --git a/ical4android b/ical4android index cfd553df5..bbabc7187 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit cfd553df575eb18b0acf51e9ddf1f11bc2b14e37 +Subproject commit bbabc7187d7dcb738115592d33846e7b4fd01c17 -- GitLab From 66282c10e67cefefb161cd238fc0854f7cff5642 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 21 Oct 2022 13:39:49 +0200 Subject: [PATCH 24/49] Version bump to 4.2.4-rc.1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e0f008985..0af6fc29a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402040000 - versionName '4.2.4-beta.1' + versionCode 402040001 + versionName '4.2.4-rc.1' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() -- GitLab From 7b70cf45fc46754a9aeea3cfec78d97deeda9382 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 21 Oct 2022 13:39:49 +0200 Subject: [PATCH 25/49] Fetch translations from Transifex --- app/src/main/res/values-bg/strings.xml | 9 ++++++++- fastlane/metadata/android/bg/full_description.txt | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 256d30511..fd93f9946 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -134,6 +134,7 @@ Грешка при презареждане Не може да работи на преден план + Необходимо е да спрете оптимизирането на батерията за приложението Работи на преден план На някои устройства това е необходимо, за да работи автоматичното синхронизиране. @@ -146,6 +147,8 @@ Дневникът е включен Дневникът е изключен Оптимизиране на батерията + Приложението е в белия списък (препоръчително) + Приложението не е в белия списък (непрепоръчително) Поддържане на преден план Може да помогне ако устройството възпрепятства автоматичното синхронизиране Връзка @@ -164,6 +167,8 @@ Оттегляне на доверието в системните сертификати Издатели на сертификати познати на системата или добавени от потребителя няма да бъдат доверени Издателите на сертификатите познати на системата или добавени от потребителя ще бъдат доверени (препоръчително) + Нулиране на (не)доверените сертификати + Нулиране на доверието към всички потребителски сертификати Всички потребителски сертификати са премахнати Потребителски интерфейс Настройки за съобщенията @@ -293,7 +298,7 @@ Събития от преди повече от един ден ще бъдат пренебрегнати Събития от преди повече от %dдена ще бъдат пренебрегнати - Събития преди повече от този брой дни в миналото ще бъдат пренебрегнати + Събитията преди повече от зададения брой дни в миналото ще бъдат пренебрегнати (може да бъде 0). За да бъдат синхронизирани всички събития оставете празно. Подразбирано напомняне Подразбирано напомняне една минута преди събитието @@ -356,6 +361,7 @@ Грешка на входа/изхода Заявката е отказана. За подробности проверете свързаните със завката ресурси и информацията за отстраняване на дефекти. Заявеният ресурс не съществува (вече). За подробности проверете свързаните със завката ресурси и информацията за отстраняване на дефекти. + Възникнал е проблем от страна на сървъра. Свържете се с поддръжката му. Възникнала е неочаквана грешка. За подробности проверете информацията за отстраняване на дефекти. Подробности Информацията за отстраняване на дефекта е събрана @@ -391,6 +397,7 @@ Монтиране Няма услуга на WebDAV на адреса Премахване на точката на монтиране + Ще бъдат изгубени подробности за връзката, но файлове няма да бъдат премахвани. Достъпва се файл на WebDAV Изтегля се файл на WebDAV Изпраща се файл на WebDAV diff --git a/fastlane/metadata/android/bg/full_description.txt b/fastlane/metadata/android/bg/full_description.txt index 5dd0b65aa..b4ad603e1 100644 --- a/fastlane/metadata/android/bg/full_description.txt +++ b/fastlane/metadata/android/bg/full_description.txt @@ -1,5 +1,5 @@ -DAVx⁵ е приложение за Android, което синхронизира данни по протола CalDAV/CardDAV и се интегрира с приложенията за календар и контакти. +DAVx⁵ е приложение за Android, което синхронизира данни по протокола CalDAV/CardDAV и се интегрира с приложенията за календар и контакти. -Използвайте я със собствен сървър или с доверен доставчик и държите контактите, събитията и задачите си под контрол. +Използвайте я със собствен сървър или с доверен доставчик и държите контактите, събитията и задачите си под свой контрол. За повече информация и списък на проверени сървъри и услуги посетете страницата. \ No newline at end of file -- GitLab From a8e21bed8b944975a17508accec5481dc63830fc Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 21 Oct 2022 13:39:49 +0200 Subject: [PATCH 26/49] Force downloading all contacts after resetting read-only contacts when collection supports Collection Sync --- .../syncadapter/ContactsSyncManager.kt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt index 09c3abb0f..82e84f788 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt @@ -159,10 +159,11 @@ class ContactsSyncManager( } } - override fun syncAlgorithm() = if (hasCollectionSync) - SyncAlgorithm.COLLECTION_SYNC - else - SyncAlgorithm.PROPFIND_REPORT + override fun syncAlgorithm() = + if (hasCollectionSync) + SyncAlgorithm.COLLECTION_SYNC + else + SyncAlgorithm.PROPFIND_REPORT override fun processLocallyDeleted() = if (readOnly) { @@ -179,6 +180,12 @@ class ContactsSyncManager( modified = true } + /* This is unfortunately dirty: When a contact has been inserted to a read-only address book + that supports Collection Sync, it's not enough to force synchronization (by returning true), + but we also need to make sure all contacts are downloaded again. */ + if (modified) + localCollection.lastSyncState = null + modified } else // mirror deletions to remote collection (DELETE) @@ -200,6 +207,10 @@ class ContactsSyncManager( modified = true } + // see same position in processLocallyDeleted + if (modified) + localCollection.lastSyncState = null + } else // we only need to handle changes in groups when the address book is read/write groupStrategy.beforeUploadDirty() -- GitLab From 31a61f508d44224e06ae5421572d14d6f5acb292 Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Tue, 25 Oct 2022 11:05:24 +0200 Subject: [PATCH 27/49] Version bump to 4.2.4 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0af6fc29a..c2f6e70a1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { defaultConfig { applicationId "at.bitfire.davdroid" - versionCode 402040001 - versionName '4.2.4-rc.1' + versionCode 402040002 + versionName '4.2.4' buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" setProperty "archivesBaseName", "davx5-ose-" + getVersionName() -- GitLab From d32b21a465a64be2c72a071345e7ec4e3e04319d Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Tue, 25 Oct 2022 11:22:34 +0200 Subject: [PATCH 28/49] Update F-Droid changelog --- .../metadata/android/en-US/changelogs/402040002.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/402040002.txt diff --git a/fastlane/metadata/android/en-US/changelogs/402040002.txt b/fastlane/metadata/android/en-US/changelogs/402040002.txt new file mode 100644 index 000000000..50bcbd82f --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/402040002.txt @@ -0,0 +1,13 @@ +- [CardDAV] vCard LABELs are not generated anymore - now there's only the structured address +- [CardDAV] better support for read-only address books (make contacts "really" read-only as good as possible) +- [CalDAV] handle a rare exception when a time zone is known to Android but not to ical4j +- [UI] use Material switches for preferences +- [UI] use switches instead of checkboxes in accounts so that it is more understandable what should be synchronized +- [UI] add monochrome/themed icon +- [UI] added some pre-set base URLs +- [UI] updated Manual URL (the manual is now automatically updated by Github Actions after editing it) +- [jtx Board] remove filesize restriction for attachments +- improved compatibility (especially HUAWEI to display DAVx5 calendars there again) +- fix a bug that caused the account view to be empty after renaming an account +- fix a crash when accounts vanish somehow +- new languages (thanks to our translators!) -- GitLab From 57a77bd5f57d4c5ff0bd54ee4bf273fec5aab216 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Tue, 25 Oct 2022 12:38:39 +0200 Subject: [PATCH 29/49] Actually update vcard4android (better read-only contacts support) --- .../resource/contactrow/GroupMembershipBuilderTest.kt | 4 ++-- .../resource/contactrow/UnknownPropertiesBuilderTest.kt | 4 ++-- .../resource/contactrow/GroupMembershipBuilder.kt | 8 ++++---- .../resource/contactrow/UnknownPropertiesBuilder.kt | 8 ++++---- vcard4android | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt b/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt index e1c58b930..d23720df6 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt +++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt @@ -54,7 +54,7 @@ class GroupMembershipBuilderTest { val contact = Contact().apply { categories += "TEST GROUP" } - GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsCategories).build().also { result -> + GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsCategories, false).build().also { result -> assertEquals(1, result.size) assertEquals(GroupMembership.CONTENT_ITEM_TYPE, result[0].values[GroupMembership.MIMETYPE]) assertEquals(addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP"), result[0].values[GroupMembership.GROUP_ROW_ID]) @@ -66,7 +66,7 @@ class GroupMembershipBuilderTest { val contact = Contact().apply { categories += "TEST GROUP" } - GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsVCards).build().also { result -> + GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsVCards, false).build().also { result -> // group membership is constructed during post-processing assertEquals(0, result.size) } diff --git a/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilderTest.kt b/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilderTest.kt index 8b1461467..6178a88b7 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilderTest.kt +++ b/app/src/androidTest/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilderTest.kt @@ -13,7 +13,7 @@ class UnknownPropertiesBuilderTest { @Test fun testUnknownProperties_None() { - UnknownPropertiesBuilder(Uri.EMPTY, null, Contact()).build().also { result -> + UnknownPropertiesBuilder(Uri.EMPTY, null, Contact(), false).build().also { result -> assertEquals(0, result.size) } } @@ -22,7 +22,7 @@ class UnknownPropertiesBuilderTest { fun testUnknownProperties_Properties() { UnknownPropertiesBuilder(Uri.EMPTY, null, Contact().apply { unknownProperties = "X-TEST:12345" - }).build().also { result -> + }, false).build().also { result -> assertEquals(1, result.size) assertEquals(UnknownProperties.CONTENT_ITEM_TYPE, result[0].values[UnknownProperties.MIMETYPE]) assertEquals("X-TEST:12345", result[0].values[UnknownProperties.UNKNOWN_PROPERTIES]) diff --git a/app/src/main/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilder.kt b/app/src/main/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilder.kt index c09235217..84426a0c0 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilder.kt +++ b/app/src/main/java/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilder.kt @@ -13,8 +13,8 @@ import at.bitfire.vcard4android.GroupMethod import at.bitfire.vcard4android.contactrow.DataRowBuilder import java.util.* -class GroupMembershipBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact, val addressBook: LocalAddressBook) - : DataRowBuilder(Factory.MIME_TYPE, dataRowUri, rawContactId, contact) { +class GroupMembershipBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact, val addressBook: LocalAddressBook, readOnly: Boolean) + : DataRowBuilder(Factory.MIME_TYPE, dataRowUri, rawContactId, contact, readOnly) { override fun build(): List { val result = LinkedList() @@ -36,8 +36,8 @@ class GroupMembershipBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Cont const val MIME_TYPE = GroupMembership.CONTENT_ITEM_TYPE } override fun mimeType() = MIME_TYPE - override fun newInstance(dataRowUri: Uri, rawContactId: Long?, contact: Contact) = - GroupMembershipBuilder(dataRowUri, rawContactId, contact, addressBook) + override fun newInstance(dataRowUri: Uri, rawContactId: Long?, contact: Contact, readOnly: Boolean) = + GroupMembershipBuilder(dataRowUri, rawContactId, contact, addressBook, readOnly) } } \ No newline at end of file diff --git a/app/src/main/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilder.kt b/app/src/main/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilder.kt index 6209e53ba..ec5df5681 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilder.kt +++ b/app/src/main/java/at/bitfire/davdroid/resource/contactrow/UnknownPropertiesBuilder.kt @@ -10,8 +10,8 @@ import at.bitfire.vcard4android.Contact import at.bitfire.vcard4android.contactrow.DataRowBuilder import java.util.* -class UnknownPropertiesBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact) - : DataRowBuilder(Factory.mimeType(), dataRowUri, rawContactId, contact) { +class UnknownPropertiesBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Contact, readOnly: Boolean) + : DataRowBuilder(Factory.mimeType(), dataRowUri, rawContactId, contact, readOnly) { override fun build(): List { val result = LinkedList() @@ -24,8 +24,8 @@ class UnknownPropertiesBuilder(dataRowUri: Uri, rawContactId: Long?, contact: Co object Factory: DataRowBuilder.Factory { override fun mimeType() = UnknownProperties.CONTENT_ITEM_TYPE - override fun newInstance(dataRowUri: Uri, rawContactId: Long?, contact: Contact) = - UnknownPropertiesBuilder(dataRowUri, rawContactId, contact) + override fun newInstance(dataRowUri: Uri, rawContactId: Long?, contact: Contact, readOnly: Boolean) = + UnknownPropertiesBuilder(dataRowUri, rawContactId, contact, readOnly) } } \ No newline at end of file diff --git a/vcard4android b/vcard4android index 581eac411..7fbec18c2 160000 --- a/vcard4android +++ b/vcard4android @@ -1 +1 @@ -Subproject commit 581eac4117634bf59eba14b69acb8bb1cce95d2a +Subproject commit 7fbec18c28cf242225126f36aa858e007b28efac -- GitLab From 796eddb9750f810ca1a72760652277293adb23f3 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Fri, 28 Oct 2022 13:05:28 +0200 Subject: [PATCH 30/49] Update dav4jvm, Kotlin --- app/build.gradle | 2 +- .../at/bitfire/davdroid/syncadapter/TestSyncManager.kt | 6 +++--- .../bitfire/davdroid/syncadapter/CalendarSyncManager.kt | 4 ++-- .../bitfire/davdroid/syncadapter/ContactsSyncManager.kt | 4 ++-- .../at/bitfire/davdroid/syncadapter/JtxSyncManager.kt | 4 ++-- .../java/at/bitfire/davdroid/syncadapter/SyncManager.kt | 8 ++++---- .../at/bitfire/davdroid/syncadapter/TasksSyncManager.kt | 4 ++-- build.gradle | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c2f6e70a1..887b45be8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -115,7 +115,7 @@ dependencies { implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.fragment:fragment-ktx:1.5.3' + implementation 'androidx.fragment:fragment-ktx:1.5.4' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.paging:paging-runtime-ktx:3.1.1' diff --git a/app/src/androidTestOse/java/at/bitfire/davdroid/syncadapter/TestSyncManager.kt b/app/src/androidTestOse/java/at/bitfire/davdroid/syncadapter/TestSyncManager.kt index 6e664bed1..0c146b63b 100644 --- a/app/src/androidTestOse/java/at/bitfire/davdroid/syncadapter/TestSyncManager.kt +++ b/app/src/androidTestOse/java/at/bitfire/davdroid/syncadapter/TestSyncManager.kt @@ -9,7 +9,7 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import at.bitfire.dav4jvm.DavCollection -import at.bitfire.dav4jvm.DavResponseCallback +import at.bitfire.dav4jvm.MultiResponseCallback import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.property.GetCTag import at.bitfire.davdroid.DavUtils @@ -67,12 +67,12 @@ class TestSyncManager( var listAllRemoteResult = emptyList>() var didListAllRemote = false - override fun listAllRemote(callback: DavResponseCallback) { + override fun listAllRemote(callback: MultiResponseCallback) { if (didListAllRemote) throw IllegalStateException("listAllRemote() must not be called twice") didListAllRemote = true for (result in listAllRemoteResult) - callback(result.first, result.second) + callback.onResponse(result.first, result.second) } var assertDownloadRemote = emptyMap() diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.kt index c00239c76..a94340163 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.kt @@ -9,7 +9,7 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import at.bitfire.dav4jvm.DavCalendar -import at.bitfire.dav4jvm.DavResponseCallback +import at.bitfire.dav4jvm.MultiResponseCallback import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.exception.DavException import at.bitfire.dav4jvm.property.* @@ -101,7 +101,7 @@ class CalendarSyncManager( os.toByteArray().toRequestBody(DavCalendar.MIME_ICALENDAR_UTF8) } - override fun listAllRemote(callback: DavResponseCallback) { + override fun listAllRemote(callback: MultiResponseCallback) { // calculate time range limits var limitStart: Date? = null accountSettings.getTimeRangePastDays()?.let { pastDays -> diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt index 82e84f788..4df44fc90 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.kt @@ -12,7 +12,7 @@ import android.content.SyncResult import android.os.Build import android.os.Bundle import at.bitfire.dav4jvm.DavAddressBook -import at.bitfire.dav4jvm.DavResponseCallback +import at.bitfire.dav4jvm.MultiResponseCallback import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.exception.DavException import at.bitfire.dav4jvm.property.* @@ -252,7 +252,7 @@ class ContactsSyncManager( return@localExceptionContext(os.toByteArray().toRequestBody(mimeType)) } - override fun listAllRemote(callback: DavResponseCallback) = + override fun listAllRemote(callback: MultiResponseCallback) = remoteExceptionContext { it.propfind(1, ResourceType.NAME, GetETag.NAME, callback = callback) } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncManager.kt index 5ecdc496a..f02b1f5fe 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncManager.kt @@ -9,7 +9,7 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import at.bitfire.dav4jvm.DavCalendar -import at.bitfire.dav4jvm.DavResponseCallback +import at.bitfire.dav4jvm.MultiResponseCallback import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.exception.DavException import at.bitfire.dav4jvm.property.* @@ -76,7 +76,7 @@ class JtxSyncManager( override fun syncAlgorithm() = SyncAlgorithm.PROPFIND_REPORT - override fun listAllRemote(callback: DavResponseCallback) { + override fun listAllRemote(callback: MultiResponseCallback) { remoteExceptionContext { remote -> if (localCollection.supportsVTODO) { Logger.log.info("Querying tasks") diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt index 41c07d4c4..6616f262a 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt @@ -520,7 +520,7 @@ abstract class SyncManager, out CollectionType: L * * @param listRemote function to list remote resources (for instance, all since a certain sync-token) */ - protected open fun syncRemote(listRemote: (DavResponseCallback) -> Unit) { + protected open fun syncRemote(listRemote: (MultiResponseCallback) -> Unit) { // thread-safe sync stats val nInserted = AtomicInteger() val nUpdated = AtomicInteger() @@ -611,9 +611,9 @@ abstract class SyncManager, out CollectionType: L } } - protected abstract fun listAllRemote(callback: DavResponseCallback) + protected abstract fun listAllRemote(callback: MultiResponseCallback) - protected open fun listRemoteChanges(syncState: SyncState?, callback: DavResponseCallback): Pair { + protected open fun listRemoteChanges(syncState: SyncState?, callback: MultiResponseCallback): Pair { var furtherResults = false val report = davCollection.reportChanges( @@ -625,7 +625,7 @@ abstract class SyncManager, out CollectionType: L furtherResults = response.status?.code == 507 Response.HrefRelation.MEMBER -> - callback(response, relation) + callback.onResponse(response, relation) else -> Logger.log.fine("Unexpected sync-collection response: $response") diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.kt index d1dbc363e..1d0fcdc4d 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.kt @@ -9,7 +9,7 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import at.bitfire.dav4jvm.DavCalendar -import at.bitfire.dav4jvm.DavResponseCallback +import at.bitfire.dav4jvm.MultiResponseCallback import at.bitfire.dav4jvm.Response import at.bitfire.dav4jvm.exception.DavException import at.bitfire.dav4jvm.property.* @@ -83,7 +83,7 @@ class TasksSyncManager( os.toByteArray().toRequestBody(DavCalendar.MIME_ICALENDAR_UTF8) } - override fun listAllRemote(callback: DavResponseCallback) { + override fun listAllRemote(callback: MultiResponseCallback) { remoteExceptionContext { remote -> Logger.log.info("Querying tasks") remote.calendarQuery("VTODO", null, null, callback) diff --git a/build.gradle b/build.gradle index 394805e25..1b5e97672 100644 --- a/build.gradle +++ b/build.gradle @@ -10,9 +10,9 @@ buildscript { ext.versions = [ aboutLibraries: '8.9.4', appIntro: '6.2.0', - dav4jvm: 'c61e4b0c80a5a8de1df99b4997445bb323d3ea3d', + dav4jvm: '2.2', hilt: '2.44', - kotlin: '1.7.10', + kotlin: '1.7.20', okhttp: '4.10.0', // latest Apache Commons versions that don't require Java 8 (Android 7) commonsCollections: '4.2', -- GitLab From 43ae3fcd1f48e5b2087e8c7210b1f4b4c0926460 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Sat, 29 Oct 2022 16:40:09 +0200 Subject: [PATCH 31/49] Update libraries --- cert4android | 2 +- ical4android | 2 +- vcard4android | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cert4android b/cert4android index eb47c00cb..2c41f8657 160000 --- a/cert4android +++ b/cert4android @@ -1 +1 @@ -Subproject commit eb47c00cb05fe5d27e8640444cc60aa7c271b47a +Subproject commit 2c41f865731c02c41e540fe735b43b371cc65926 diff --git a/ical4android b/ical4android index bbabc7187..c2ba11612 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit bbabc7187d7dcb738115592d33846e7b4fd01c17 +Subproject commit c2ba1161292c8f8d5d9b23c9e96b07002cfb666d diff --git a/vcard4android b/vcard4android index 7fbec18c2..c419d7cad 160000 --- a/vcard4android +++ b/vcard4android @@ -1 +1 @@ -Subproject commit 7fbec18c28cf242225126f36aa858e007b28efac +Subproject commit c419d7cad2789bd9e1571d12f31b4807a676ca3d -- GitLab From 8915a3c10381aa130e529b9cc0b733977037c3f2 Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Tue, 1 Nov 2022 12:49:06 +0100 Subject: [PATCH 32/49] android 13 compatibility (bitfireAT/davx5#155) * check for notify permission before notifying * [WIP] add notification permission request * Revert "check for notify permission before notifying" This reverts commit ed8e046d73163bef5684622bd877f08b9ee781c6. * add notification permission request * [WIP] add notifications disabled card in accounts view * add notifications disabled card in accounts view * reorder permissions * use dp instead of mm for image max height in permissions view * stop using array to bundle notification permissions * Use new permissions contract for PermissionsFragment Co-authored-by: Ricki Hirner --- app/build.gradle | 2 +- .../at/bitfire/davdroid/PermissionUtils.kt | 8 +- .../davdroid/ui/AccountListFragment.kt | 20 +++ .../davdroid/ui/PermissionsFragment.kt | 38 +++-- .../res/drawable/ic_notifications_off.xml | 5 + app/src/main/res/layout/account_list.xml | 35 +++- .../main/res/layout/activity_permissions.xml | 149 +++++++++++------- app/src/main/res/values-h480dp/dimen.xml | 2 +- app/src/main/res/values/dimen.xml | 2 +- app/src/main/res/values/strings.xml | 6 + 10 files changed, 188 insertions(+), 79 deletions(-) create mode 100644 app/src/main/res/drawable/ic_notifications_off.xml diff --git a/app/build.gradle b/app/build.gradle index 887b45be8..0a0159922 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,7 +22,7 @@ android { setProperty "archivesBaseName", "davx5-ose-" + getVersionName() minSdkVersion 21 // Android 5 - targetSdkVersion 32 // Android 12v2 + targetSdkVersion 33 // Android 13 buildConfigField "String", "userAgent", "\"DAVx5\"" diff --git a/app/src/main/java/at/bitfire/davdroid/PermissionUtils.kt b/app/src/main/java/at/bitfire/davdroid/PermissionUtils.kt index 44529956d..cc1df6689 100644 --- a/app/src/main/java/at/bitfire/davdroid/PermissionUtils.kt +++ b/app/src/main/java/at/bitfire/davdroid/PermissionUtils.kt @@ -23,12 +23,12 @@ import at.bitfire.davdroid.ui.PermissionsActivity object PermissionUtils { val CONTACT_PERMISSIONS = arrayOf( - Manifest.permission.READ_CONTACTS, - Manifest.permission.WRITE_CONTACTS + Manifest.permission.READ_CONTACTS, + Manifest.permission.WRITE_CONTACTS ) val CALENDAR_PERMISSIONS = arrayOf( - Manifest.permission.READ_CALENDAR, - Manifest.permission.WRITE_CALENDAR + Manifest.permission.READ_CALENDAR, + Manifest.permission.WRITE_CALENDAR ) val WIFI_SSID_PERMISSIONS = diff --git a/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt index a1fe1f1ae..c7e105645 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt @@ -4,12 +4,14 @@ package at.bitfire.davdroid.ui +import android.Manifest import android.accounts.Account import android.accounts.AccountManager import android.accounts.OnAccountsUpdateListener import android.app.Activity import android.app.Application import android.content.* +import android.content.pm.PackageManager import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities @@ -18,6 +20,8 @@ import android.os.Build import android.os.Bundle import android.provider.Settings import android.view.* +import androidx.core.content.ContextCompat +import androidx.core.content.PackageManagerCompat import androidx.core.content.getSystemService import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels @@ -29,6 +33,7 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.DavUtils.SyncStatus +import at.bitfire.davdroid.PermissionUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.StorageLowReceiver import at.bitfire.davdroid.databinding.AccountListBinding @@ -57,6 +62,10 @@ class AccountListFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding.allowNotifications.setOnClickListener { + startActivity(Intent(requireActivity(), PermissionsActivity::class.java)) + } + model.networkAvailable.observe(viewLifecycleOwner) { networkAvailable -> binding.noNetworkInfo.visibility = if (networkAvailable) View.GONE else View.VISIBLE } @@ -103,11 +112,22 @@ class AccountListFragment: Fragment() { } } + override fun onResume() { + super.onResume() + checkPermissions() + } + override fun onDestroyView() { super.onDestroyView() _binding = null } + fun checkPermissions() { + if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) + binding.noNotificationsInfo.visibility = View.GONE + else + binding.noNotificationsInfo.visibility = View.VISIBLE + } class AccountAdapter( val activity: Activity diff --git a/app/src/main/java/at/bitfire/davdroid/ui/PermissionsFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/PermissionsFragment.kt index 9a914b7ec..77de939f8 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/PermissionsFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/PermissionsFragment.kt @@ -4,9 +4,11 @@ package at.bitfire.davdroid.ui +import android.Manifest import android.app.Application import android.content.Context import android.content.Intent +import android.content.pm.PackageManager import android.net.Uri import android.os.Build import android.os.Bundle @@ -14,7 +16,9 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.MainThread +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.AndroidViewModel @@ -42,6 +46,10 @@ class PermissionsFragment: Fragment() { binding.text.text = getString(R.string.permissions_text, getString(R.string.app_name)) + val requestPermission = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { + model.checkPermissions() + } + model.needAutoResetPermission.observe(viewLifecycleOwner, { keepPermissions -> if (keepPermissions == true && model.haveAutoResetPermission.value == false) { Toast.makeText(requireActivity(), R.string.permissions_autoreset_instruction, Toast.LENGTH_LONG).show() @@ -50,34 +58,38 @@ class PermissionsFragment: Fragment() { }) model.needContactsPermissions.observe(viewLifecycleOwner, { needContacts -> if (needContacts && model.haveContactsPermissions.value == false) - requestPermissions(CONTACT_PERMISSIONS, 0) + requestPermission.launch(CONTACT_PERMISSIONS) }) model.needCalendarPermissions.observe(viewLifecycleOwner, { needCalendars -> if (needCalendars && model.haveCalendarPermissions.value == false) - requestPermissions(CALENDAR_PERMISSIONS, 0) + requestPermission.launch(CALENDAR_PERMISSIONS) + }) + model.needNotificationPermissions.observe(viewLifecycleOwner, { needNotifications -> + if (needNotifications && model.haveNotificationPermissions.value == false) + requestPermission.launch(arrayOf(Manifest.permission.POST_NOTIFICATIONS)) }) model.needOpenTasksPermissions.observe(viewLifecycleOwner, { needOpenTasks -> if (needOpenTasks == true && model.haveOpenTasksPermissions.value == false) - requestPermissions(TaskProvider.PERMISSIONS_OPENTASKS, 0) + requestPermission.launch(TaskProvider.PERMISSIONS_OPENTASKS) }) model.needTasksOrgPermissions.observe(viewLifecycleOwner, { needTasksOrg -> if (needTasksOrg == true && model.haveTasksOrgPermissions.value == false) - requestPermissions(TaskProvider.PERMISSIONS_TASKS_ORG, 0) + requestPermission.launch(TaskProvider.PERMISSIONS_TASKS_ORG) }) model.needJtxPermissions.observe(viewLifecycleOwner, { needJtx -> if (needJtx == true && model.haveJtxPermissions.value == false) - requestPermissions(TaskProvider.PERMISSIONS_JTX, 0) + requestPermission.launch(TaskProvider.PERMISSIONS_JTX) }) model.needAllPermissions.observe(viewLifecycleOwner, { needAll -> if (needAll && model.haveAllPermissions.value == false) { - val all = mutableSetOf(*CONTACT_PERMISSIONS, *CALENDAR_PERMISSIONS) + val all = mutableSetOf(*CONTACT_PERMISSIONS, *CALENDAR_PERMISSIONS, Manifest.permission.POST_NOTIFICATIONS) if (model.haveOpenTasksPermissions.value != null) all.addAll(TaskProvider.PERMISSIONS_OPENTASKS) if (model.haveTasksOrgPermissions.value != null) all.addAll(TaskProvider.PERMISSIONS_TASKS_ORG) if (model.haveJtxPermissions.value != null) all.addAll(TaskProvider.PERMISSIONS_JTX) - requestPermissions(all.toTypedArray(), 0) + requestPermission.launch(all.toTypedArray()) } }) @@ -93,11 +105,6 @@ class PermissionsFragment: Fragment() { model.checkPermissions() } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - model.checkPermissions() - } - class Model(app: Application): AndroidViewModel(app) { @@ -108,6 +115,8 @@ class PermissionsFragment: Fragment() { val needContactsPermissions = MutableLiveData() val haveCalendarPermissions = MutableLiveData() val needCalendarPermissions = MutableLiveData() + val haveNotificationPermissions = MutableLiveData() + val needNotificationPermissions = MutableLiveData() val haveOpenTasksPermissions = MutableLiveData() val needOpenTasksPermissions = MutableLiveData() @@ -153,6 +162,10 @@ class PermissionsFragment: Fragment() { haveCalendarPermissions.value = calendarPermissions needCalendarPermissions.value = calendarPermissions + val notificationPermissions = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + haveNotificationPermissions.value = notificationPermissions + needNotificationPermissions.value = notificationPermissions + // OpenTasks val openTasksAvailable = pm.resolveContentProvider(ProviderName.OpenTasks.authority, 0) != null var openTasksPermissions: Boolean? = null @@ -190,6 +203,7 @@ class PermissionsFragment: Fragment() { // "all permissions" switch val allPermissions = contactPermissions && calendarPermissions && + notificationPermissions && (!openTasksAvailable || openTasksPermissions == true) && (!tasksOrgAvailable || tasksOrgPermissions == true) && (!jtxAvailable || jtxPermissions == true) diff --git a/app/src/main/res/drawable/ic_notifications_off.xml b/app/src/main/res/drawable/ic_notifications_off.xml new file mode 100644 index 000000000..daa24d19b --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_off.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/account_list.xml b/app/src/main/res/layout/account_list.xml index 18078361a..dfc7d94ed 100644 --- a/app/src/main/res/layout/account_list.xml +++ b/app/src/main/res/layout/account_list.xml @@ -5,6 +5,37 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"> + + + + + +