Compare commits

...

9 Commits
v1.8 ... v1.8.1

Author SHA1 Message Date
Ricki Hirner
830f2764f0 Assign UID/file name for empty contact even when creating in read-only address book (so that it can be deleted later) 2017-09-25 14:40:34 +02:00
Ricki Hirner
fe176f6d3c cert4android: fetch translations from Transifex 2017-09-25 12:08:11 +02:00
Ricki Hirner
cf309eb803 Fetch translations from Transifex 2017-09-25 12:07:34 +02:00
Ricki Hirner
2997190027 Version bump to 1.8.1 2017-09-25 11:56:48 +02:00
Ricki Hirner
1e4fe9fc32 Optimize read-only contact notifications 2017-09-25 11:56:10 +02:00
Ricki Hirner
8b5a2c02b3 Version bump to 1.8.1-beta1 2017-09-23 21:25:07 +02:00
Ricki Hirner
20d82f5c70 Fetch translations from Transifex 2017-09-23 21:23:37 +02:00
Ricki Hirner
1301a8398b Notify on read-only address books
* notify when a read-only address book is selected for synchronization
* notify when local changes have been discarded during sync
2017-09-23 21:10:25 +02:00
Ricki Hirner
f1fb01ee62 Initial implementation of read-only address books 2017-09-21 23:57:01 +02:00
30 changed files with 279 additions and 87 deletions

View File

@@ -18,7 +18,7 @@ android {
applicationId "at.bitfire.davdroid"
resValue "string", "packageID", applicationId
versionCode 170
versionCode 172
buildConfigField "long", "buildTime", System.currentTimeMillis() + "L"
minSdkVersion 16
@@ -30,19 +30,19 @@ android {
productFlavors {
standard {
versionName "1.8"
versionName "1.8.1"
buildConfigField "boolean", "customCerts", "true"
}
gplay {
versionName "1.8-gplay"
versionName "1.8.1-gplay"
buildConfigField "boolean", "customCerts", "true"
}
icloud {
applicationId "at.bitfire.cloudsync"
resValue "string", "packageID", applicationId
versionName "1.8-cloud"
versionName "1.8.1-cloud"
buildConfigField "at.bitfire.vcard4android.GroupMethod", "settingContactGroupMethod", "at.bitfire.vcard4android.GroupMethod.GROUP_VCARDS"
}
soldupe {
@@ -50,7 +50,7 @@ android {
resValue "string", "packageID", applicationId
minSdkVersion 21
versionName "1.8-soldupe"
versionName "1.8.1-soldupe"
buildConfigField "boolean", "customCerts", "true"
buildConfigField "at.bitfire.vcard4android.GroupMethod", "settingContactGroupMethod", "at.bitfire.vcard4android.GroupMethod.CATEGORIES"
}

View File

@@ -17,6 +17,6 @@
<!--AccountSettingsActivity-->
<!--collection management-->
<!--ExceptionInfoFragment-->
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<!--cert4android-->
</resources>

View File

@@ -187,7 +187,7 @@
<string name="exception_httpexception">Došlo k HTTP chybě.</string>
<string name="exception_ioexception">Došlo k I/O chybě.</string>
<string name="exception_show_details">Zobrazit detaily</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Ladící informace</string>
<string name="sync_error_permissions">DAVdroid oprávnění</string>
<string name="sync_error_permissions_text">Vyžadována dodatečná oprávnění</string>

View File

@@ -190,7 +190,7 @@
<string name="exception_httpexception">Der er opstået en HTTP-fejl.</string>
<string name="exception_ioexception">Der er opstået en I/O-fejl.</string>
<string name="exception_show_details">Vis detaljer</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Debug-info</string>
<string name="sync_error_permissions">DAVdroid-rettigheder</string>
<string name="sync_error_permissions_text">Yderligere adgang påkrævet</string>

View File

@@ -186,7 +186,7 @@
<string name="exception_httpexception">Ha ocurrido un error HTTP.</string>
<string name="exception_ioexception">Ha ocurrido un error I/O.</string>
<string name="exception_show_details">Mostrar detalles</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Información de depuración</string>
<string name="sync_error_permissions">Permisos de DAVdroid</string>
<string name="sync_error_permissions_text">Permisos adicionales requeridos</string>

View File

@@ -217,7 +217,7 @@ Si vous constatez des dysfonctionnements, faites nous un retour.</string>
<string name="exception_httpexception">Une erreur HTTP est survenue.</string>
<string name="exception_ioexception">Une erreur I/O est survenue.</string>
<string name="exception_show_details">Voir détails</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Infos de débogage</string>
<string name="sync_error_permissions">Autorisations DAVdroid</string>
<string name="sync_error_permissions_text">Autorisations supplémentaires demandées</string>

View File

@@ -8,11 +8,14 @@
<string name="manage_accounts">Fiókok kezelése</string>
<string name="please_wait">Kérjük, várjon ...</string>
<string name="send">Küldés</string>
<string name="homepage_url">https://davdroid.bitfire.at/?pk_campaign=davdroid-app</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Akkumulátoroptimalizálás </string>
<string name="startup_battery_optimization_message">Az operációs rendszer a DAVdroid szinkronizálást pár nap után leállíthatja vagy visszafoghatja. Ennek elkerülésére kapcsolja ki az akkumulátoroptimalizálást.</string>
<string name="startup_battery_optimization_disable">Kikapcsolás a DAVdroid kapcsán</string>
<string name="startup_dont_show_again">Ne jelenjen meg többet</string>
<string name="startup_development_version">Technológiai előzetes</string>
<string name="startup_development_version_message">Ez a %s fejlesztői verziója. Nem biztos, hogy minden úgy fog működni, ahogy az várható lenne. A visszajelzéseket köszönettel vesszük.</string>
<string name="startup_development_version_give_feedback">Visszajelzés küldése</string>
<string name="startup_donate">A forrás nyíltságával kapcsolatos információk</string>
<string name="startup_donate_message">Örülünk, hogy használja a DAVdroidot. A DAVdroid nyílt forráskódú (GPLv3) szoftver, de a fejlesztése kemény munkát jelent, már eddig több ezer munkaórát emésztett fel, ezért kérjük, fontolja meg, hogy támogassa munkánkat.</string>
@@ -44,6 +47,8 @@
<string name="navigation_drawer_external_links">Weblapok</string>
<string name="navigation_drawer_website">Honlap</string>
<string name="navigation_drawer_faq">GYIK</string>
<string name="navigation_drawer_faq_url">https://davdroid.bitfire.at/faq/?pk_campaign=davdroid-app</string>
<string name="navigation_drawer_forums">Segítség / Fórumok</string>
<string name="navigation_drawer_donate">Támogatás</string>
<string name="account_list_empty">Üdvözöljük a DAVdroid felhasználók között!\n\nMost már felvehet CalDAV/CardDav fiókokat.</string>
<string name="accounts_global_sync_disabled">A rendszerszintű automatikus szinkronizálás ki van kapcsolva</string>
@@ -86,10 +91,15 @@
<string name="account_delete">Fiók törlése</string>
<string name="account_delete_confirmation_title">Valóban törölni akarja a fiókot?</string>
<string name="account_delete_confirmation_text">Az összes címjegyzék, naptár és feladatlista helyi példányai törölve lesznek.</string>
<string name="account_carddav">CardDAV</string>
<string name="account_caldav">CalDAV</string>
<string name="account_webcal">Webcal</string>
<string name="account_refresh_address_book_list">Címjegyzék-lista frissítése</string>
<string name="account_create_new_address_book">Új címjegyzék létrehozása</string>
<string name="account_refresh_calendar_list">Naptárlista frissítése</string>
<string name="account_create_new_calendar">Új naptár létrehozása</string>
<string name="account_no_webcal_handler_found">Nem található Webcal-képes alkalmazás</string>
<string name="account_install_icsdroid">ICSdroid telepítése</string>
<!--PermissionsActivity-->
<string name="permissions_title">DAVdroid engedélyek </string>
<string name="permissions_calendar">Naptárengedély</string>
@@ -102,6 +112,7 @@
<string name="permissions_opentasks_details">A CalDAV feladatlisták és a helyi feladatlisták szinkronizálásához a DAVdroid OpenTasks hozzáférést igényel.</string>
<string name="permissions_opentasks_request">OpenTasks engedélyek igénylése</string>
<!--AddAccountActivity-->
<string name="login_help_url">https://davdroid.bitfire.at/configuration/?pk_campaign=davdroid-app</string>
<string name="login_title">Fiók hozzáadása</string>
<string name="login_type_email">Bejelentkezés email cím segítségével</string>
<string name="login_email_address">Email cím:</string>
@@ -140,9 +151,22 @@
<string name="settings_sync_summary_periodically" tools:ignore="PluralsCandidate">Minden %d percben + az eszközön történt módosítás után</string>
<string name="settings_sync_interval_calendars">Naptárszinkronizálás sűrűsége</string>
<string name="settings_sync_interval_tasks">Feladatlisták szinkronizálásának sűrűsége</string>
<string-array name="settings_sync_interval_names">
<item>Manális</item>
<item>15 percenként</item>
<item>30 percenként</item>
<item>Óránként</item>
<item>Kétóránként</item>
<item>Négyóránként</item>
<item>Naponta</item>
</string-array>
<string name="settings_sync_wifi_only">Szinkronizálás csak WIFI-n</string>
<string name="settings_sync_wifi_only_on">Csak WIFI kapcsolat keresztül történjen szinkronizálás</string>
<string name="settings_sync_wifi_only_off">Szinkronizálás a kapcsolat típusától függetlenül</string>
<string name="settings_sync_wifi_only_ssids">WiFi SSID szűrés</string>
<string name="settings_sync_wifi_only_ssids_on">Az alábbi hálózatok használhatók: %s</string>
<string name="settings_sync_wifi_only_ssids_off">Minden hálózat használható</string>
<string name="settings_sync_wifi_only_ssids_message">A használható WiFi hálózatok nevei (SSID), vesszővel elválasztva (hagyja üresen, ha nem akar szűrést beállítani)</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">A csoportok kezelésének módja</string>
<string-array name="settings_contact_group_method_values">
@@ -164,6 +188,10 @@
<string name="settings_manage_calendar_colors">Naptárszínek kezelése</string>
<string name="settings_manage_calendar_colors_on">A naptárszíneket a DAVdroid kezeli</string>
<string name="settings_manage_calendar_colors_off">A naptárszíneket nem a DAVdroid kezeli</string>
<string name="settings_event_colors">Eseményszínek támogatása</string>
<string name="settings_event_colors_on">Eseményszínek szinkronlzálása</string>
<string name="settings_event_colors_off">Az eseményszínek szinkronizálásának elhagyása</string>
<string name="settings_event_colors_off_confirm">A szinkronizálás kikapcsolása a már szinkronizált eseményszíneket törölheti.</string>
<!--collection management-->
<string name="create_addressbook">Címjegyzék létrehozása</string>
<string name="create_addressbook_display_name_hint">Új címjegyzék</string>
@@ -190,7 +218,7 @@
<string name="exception_httpexception">HTTP hiba történt.</string>
<string name="exception_ioexception">I/O hiba történt.</string>
<string name="exception_show_details">Részletek megjelenítése</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Hibakeresési információ</string>
<string name="sync_error_permissions">DAVdroid engedélyek </string>
<string name="sync_error_permissions_text">További engedélyek szükségesek</string>

View File

@@ -205,7 +205,7 @@
<string name="exception_httpexception">Si è verificato un errore HTTP.</string>
<string name="exception_ioexception">Si è verificato un errore di I/O.</string>
<string name="exception_show_details">Mostra dettagli</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Informazioni di debug</string>
<string name="sync_error_permissions">Autorizzazioni DAVdroid</string>
<string name="sync_error_permissions_text">Autorizzazioni addizionali richieste</string>

View File

@@ -91,10 +91,16 @@
<string name="account_delete">アカウントを削除</string>
<string name="account_delete_confirmation_title">アカウントを削除してもよろしいですか?</string>
<string name="account_delete_confirmation_text">アドレス帳、カレンダー、タスクリストのローカルコピーがすべて削除されます。</string>
<string name="account_carddav">CardDAV</string>
<string name="account_caldav">CalDAV</string>
<string name="account_webcal">Webcal</string>
<string name="account_refresh_address_book_list">アドレス帳リストを更新</string>
<string name="account_create_new_address_book">新しいアドレス帳を作成</string>
<string name="account_refresh_calendar_list">カレンダーリストを更新</string>
<string name="account_create_new_calendar">新しいカレンダーを作成</string>
<string name="account_no_webcal_handler_found">Webcal に対応するアプリが見つかりません</string>
<string name="account_install_icsdroid">ICSdroid をインストール</string>
<string name="account_read_only_address_book_selected">読み取り専用のアドレス帳 ローカルの変更は破棄されます!</string>
<!--PermissionsActivity-->
<string name="permissions_title">DAVdroid アクセス許可</string>
<string name="permissions_calendar">カレンダー アクセス許可</string>
@@ -146,6 +152,15 @@
<string name="settings_sync_summary_periodically" tools:ignore="PluralsCandidate">%d 分ごと + ローカルの変更時はすぐに</string>
<string name="settings_sync_interval_calendars">カレンダー同期間隔</string>
<string name="settings_sync_interval_tasks">タスク同期間隔</string>
<string-array name="settings_sync_interval_names">
<item>手動のみ</item>
<item>15 分ごと</item>
<item>30 分ごと</item>
<item>1 時間ごと</item>
<item>2 時間ごと</item>
<item>4 時間ごと</item>
<item>1 日 1 回</item>
</string-array>
<string name="settings_sync_wifi_only">WiFi でのみ同期</string>
<string name="settings_sync_wifi_only_on">同期は WiFi 接続に制限されます</string>
<string name="settings_sync_wifi_only_off">接続の種類は考慮されません</string>
@@ -203,8 +218,12 @@
<string name="exception_httpexception">HTTP エラーが発生しました。</string>
<string name="exception_ioexception">I/O エラーが発生しました。</string>
<string name="exception_show_details">詳細を表示</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">デバッグ情報</string>
<string name="sync_contacts_read_only_address_book">読み取り専用のアドレス帳</string>
<plurals name="sync_contacts_local_contact_changes_discarded">
<item quantity="other">%d ローカル連絡先の変更が破棄されました</item>
</plurals>
<string name="sync_error_permissions">DAVdroid アクセス許可</string>
<string name="sync_error_permissions_text">追加のアクセス許可が必要です</string>
<string name="sync_error_calendar">カレンダーの同期に失敗しました (%s)</string>

View File

@@ -144,7 +144,7 @@
<string name="exception_httpexception">En HTTP-feil har inntruffet.</string>
<string name="exception_ioexception">En I/O-feil har inntruffet.</string>
<string name="exception_show_details">Vis detaljer</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Feilrettingsinfo</string>
<string name="sync_error_tasks">Gjøremålssynkronisering mislyktes (%s)</string>
<string name="sync_error_unauthorized">Brukernavn-/passord feil</string>

View File

@@ -195,7 +195,7 @@
<string name="exception_httpexception">Er is een HTTP fout opgetreden.</string>
<string name="exception_ioexception">Er is een I/O fout opgetreden.</string>
<string name="exception_show_details">Toon details</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Debug informatie</string>
<string name="sync_error_permissions">DAVdroid rechten</string>
<string name="sync_error_permissions_text">Aanvullende rechten vereist</string>

View File

@@ -199,7 +199,7 @@
<string name="exception_httpexception">Wystąpił błąd HTTP.</string>
<string name="exception_ioexception">Wystąpił błąd I/O.</string>
<string name="exception_show_details">Pokaż szczegóły</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Informacje debugowe</string>
<string name="sync_error_permissions">Uprawnienia DAVdroid</string>
<string name="sync_error_permissions_text">Wymagane dodatkowe uprawnienia</string>

View File

@@ -216,7 +216,7 @@
<string name="exception_httpexception">Ocorreu um erro de HTTP.</string>
<string name="exception_ioexception">Ocorreu um erro de leitura/gravação.</string>
<string name="exception_show_details">Mostrar detalhes</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Informações de depuração</string>
<string name="sync_error_permissions">Permissões do DAVdroid</string>
<string name="sync_error_permissions_text">É necessário permissões adicionais</string>

View File

@@ -28,6 +28,6 @@
<string name="settings_sync_interval_calendars">Intervalo de sincronização do calendário</string>
<!--collection management-->
<!--ExceptionInfoFragment-->
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<!--cert4android-->
</resources>

View File

@@ -184,7 +184,7 @@
<string name="exception_httpexception">Произошла ошибка HTTP</string>
<string name="exception_ioexception">Произошла ошибка ввода/вывода.</string>
<string name="exception_show_details">Подробнее</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Отладочная информация</string>
<string name="sync_error_permissions">Разрешения DAVdroid</string>
<string name="sync_error_permissions_text">Требуются дополнительные разрешения</string>

View File

@@ -191,7 +191,7 @@
<string name="exception_httpexception">Десила се ХТТП грешка.</string>
<string name="exception_ioexception">Десила се У/И грешка.</string>
<string name="exception_show_details">Прикажи детаље</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Подаци за исправљање грешака</string>
<string name="sync_error_permissions">ДАВдроид дозволе</string>
<string name="sync_error_permissions_text">Потребне су додатне доволе</string>

View File

@@ -158,7 +158,7 @@
<string name="exception_httpexception">Bir HTTP hatası oluştu.</string>
<string name="exception_ioexception">Bir I/O hatası oluştu.</string>
<string name="exception_show_details">Detayları göster</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Hata ayıklama bilgisi</string>
<string name="sync_error_permissions">DAVdroid izinleri</string>
<string name="sync_error_permissions_text">Ek izinler zorunludur</string>

View File

@@ -189,7 +189,7 @@
<string name="exception_httpexception">Трапилась помилка HTTP.</string>
<string name="exception_ioexception">Трапилась помилка I/O.</string>
<string name="exception_show_details">Показати подробиці</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Інформація зневадження</string>
<string name="sync_error_permissions">Дозволи DAVdroid</string>
<string name="sync_error_permissions_text">Потребує додаткові дозволи</string>

View File

@@ -14,6 +14,8 @@
<string name="startup_battery_optimization_message">系统可能会在几天后减少或停用 DAVdroid 同步。为了避免这一情况,请禁用对 DAVdroid 的电池优化。</string>
<string name="startup_battery_optimization_disable">禁用电池优化</string>
<string name="startup_dont_show_again">不再显示</string>
<string name="startup_development_version">预览版</string>
<string name="startup_development_version_message">这是 1%s 的开发版本,部分功能可能无法正常运行。欢迎您进行反馈。</string>
<string name="startup_development_version_give_feedback">反馈</string>
<string name="startup_donate">开源信息</string>
<string name="startup_donate_message">欢迎使用 DAVdroid这是一款开源软件 (GPLv3)。开发 DAVdroid 的工作花费了数千小时,请您考虑捐助我们。</string>
@@ -46,6 +48,7 @@
<string name="navigation_drawer_website">应用网站</string>
<string name="navigation_drawer_faq">常见问题</string>
<string name="navigation_drawer_faq_url">https://davdroid.bitfire.at/faq/?pk_campaign=davdroid-app</string>
<string name="navigation_drawer_forums">帮助 / 论坛</string>
<string name="navigation_drawer_donate">捐助</string>
<string name="account_list_empty">欢迎使用 DAVdroid\n\n现在你可以增加 CalDAV/CardDAV 账户。</string>
<string name="accounts_global_sync_disabled">系统全局自动同步已禁用</string>
@@ -88,10 +91,15 @@
<string name="account_delete">删除账户</string>
<string name="account_delete_confirmation_title">真的要删除账户吗?</string>
<string name="account_delete_confirmation_text">所有通讯录、日历和任务列表的本机存储将被删除。</string>
<string name="account_carddav">CardDAV</string>
<string name="account_caldav">CalDAV</string>
<string name="account_webcal">Webcal</string>
<string name="account_refresh_address_book_list">刷新通讯录列表</string>
<string name="account_create_new_address_book">创建通讯录</string>
<string name="account_refresh_calendar_list">刷新日历列表</string>
<string name="account_create_new_calendar">创建日历</string>
<string name="account_no_webcal_handler_found">找不到支持 Webcal 的应用</string>
<string name="account_install_icsdroid">安装 ICSdroid</string>
<!--PermissionsActivity-->
<string name="permissions_title">DAVdroid 权限</string>
<string name="permissions_calendar">日历权限</string>
@@ -143,9 +151,22 @@
<string name="settings_sync_summary_periodically" tools:ignore="PluralsCandidate">每 %d 分钟或本地修改后</string>
<string name="settings_sync_interval_calendars">日历自动同步间隔</string>
<string name="settings_sync_interval_tasks">任务自动同步间隔</string>
<string-array name="settings_sync_interval_names">
<item>手动同步</item>
<item>每 15 分钟</item>
<item>每 30 分钟</item>
<item>每小时</item>
<item>每 2 小时</item>
<item>每 4 小时</item>
<item>每天一次</item>
</string-array>
<string name="settings_sync_wifi_only">只在 WiFi 下同步</string>
<string name="settings_sync_wifi_only_on">同步只在 WiFi 连接下进行</string>
<string name="settings_sync_wifi_only_off">同步不受数据连接类型限制</string>
<string name="settings_sync_wifi_only_ssids">WiFi SSID 限制</string>
<string name="settings_sync_wifi_only_ssids_on">只使用 %s 网络同步</string>
<string name="settings_sync_wifi_only_ssids_off">任意 WiFi 网络均可同步</string>
<string name="settings_sync_wifi_only_ssids_message">请用半角逗号分隔允许同步的 WiFi 网络名SSID留空则允许任意网络</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">联系人分组方式</string>
<string-array name="settings_contact_group_method_values">
@@ -166,6 +187,10 @@
<string name="settings_manage_calendar_colors">管理日历颜色</string>
<string name="settings_manage_calendar_colors_on">日历颜色由 DAVdroid 设置</string>
<string name="settings_manage_calendar_colors_off">日历颜色不由 DAVdroid 设置</string>
<string name="settings_event_colors">事件日历颜色支持</string>
<string name="settings_event_colors_on">同步日历事件颜色</string>
<string name="settings_event_colors_off">不同步日历事件颜色</string>
<string name="settings_event_colors_off_confirm">关闭事件颜色功能将删除已同步的日历颜色。</string>
<!--collection management-->
<string name="create_addressbook">创建通讯录</string>
<string name="create_addressbook_display_name_hint">我的通讯录</string>
@@ -192,7 +217,7 @@
<string name="exception_httpexception">出现 HTTP 错误</string>
<string name="exception_ioexception">出现 I/O 错误</string>
<string name="exception_show_details">显示详情</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">调试信息</string>
<string name="sync_error_permissions">DAVdroid 权限</string>
<string name="sync_error_permissions_text">需要额外权限</string>

View File

@@ -191,7 +191,7 @@
<string name="exception_httpexception">HTTP 發生錯誤</string>
<string name="exception_ioexception">讀寫錯誤</string>
<string name="exception_show_details">顯示細節</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">除錯訊息</string>
<string name="sync_error_permissions">DAVdroid 權限</string>
<string name="sync_error_permissions_text">需要額外的權限</string>

View File

@@ -39,6 +39,7 @@ class LocalAddressBook(
val USER_DATA_MAIN_ACCOUNT_TYPE = "real_account_type"
val USER_DATA_MAIN_ACCOUNT_NAME = "real_account_name"
val USER_DATA_URL = "url"
val USER_DATA_READ_ONLY = "read_only"
val USER_DATA_CTAG = "ctag"
@JvmStatic
@@ -125,6 +126,9 @@ class LocalAddressBook(
account = future.result
}
Constants.log.info("Address book read-only? = ${info.readOnly}")
setReadOnly(info.readOnly)
// make sure it will still be synchronized when contacts are updated
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true)
}
@@ -334,24 +338,22 @@ class LocalAddressBook(
}
@Throws(ContactsStorageException::class)
fun getURL(): String {
val accountManager = AccountManager.get(context)
return accountManager.getUserData(account, USER_DATA_URL) ?: throw ContactsStorageException("Address book has no URL")
}
fun getURL() =
AccountManager.get(context).getUserData(account, USER_DATA_URL) ?: throw ContactsStorageException("Address book has no URL")
fun setURL(url: String) {
val accountManager = AccountManager.get(context)
accountManager.setUserData(account, USER_DATA_URL, url)
}
fun setURL(url: String) =
AccountManager.get(context).setUserData(account, USER_DATA_URL, url)
override fun getCTag(): String? {
val accountManager = AccountManager.get(context)
return accountManager.getUserData(account, USER_DATA_CTAG)
}
fun getReadOnly() =
AccountManager.get(context).getUserData(account, USER_DATA_READ_ONLY) != null
override fun setCTag(cTag: String?) {
val accountManager = AccountManager.get(context)
accountManager.setUserData(account, USER_DATA_CTAG, cTag)
}
fun setReadOnly(readOnly: Boolean) =
AccountManager.get(context).setUserData(account, USER_DATA_READ_ONLY, if (readOnly) "1" else null)
override fun getCTag(): String? =
AccountManager.get(context).getUserData(account, USER_DATA_CTAG)
override fun setCTag(cTag: String?) =
AccountManager.get(context).setUserData(account, USER_DATA_CTAG, cTag)
}

View File

@@ -46,6 +46,17 @@ class LocalContact: AndroidContact, LocalResource {
super(addressBook, contact, fileName, eTag)
@Throws(ContactsStorageException::class)
fun resetDeleted() {
val values = ContentValues(1)
values.put(ContactsContract.RawContacts.DELETED, 0)
try {
addressBook.provider!!.update(rawContactSyncURI(), values, null, null)
} catch(e: RemoteException) {
throw ContactsStorageException("Couldn't clear deleted flag", e)
}
}
@Throws(ContactsStorageException::class)
fun resetDirty() {
val values = ContentValues(1)

View File

@@ -117,6 +117,19 @@ class LocalGroup: AndroidGroup, LocalResource {
super(addressBook, contact, fileName, eTag)
@Throws(ContactsStorageException::class)
fun resetDeleted() {
val uri = ContentUris.withAppendedId(addressBook.syncAdapterURI(ContactsContract.Groups.CONTENT_URI), requireNotNull(id))
val values = ContentValues(1)
values.put(ContactsContract.Groups.DELETED, 0)
try {
addressBook.provider!!.update(uri, values, null, null)
} catch(e: RemoteException) {
throw ContactsStorageException("Couldn't clear deleted flag", e)
}
}
@Throws(ContactsStorageException::class)
override fun clearDirty(eTag: String?) {
val id = requireNotNull(id)

View File

@@ -15,14 +15,13 @@ import android.os.Bundle
import android.os.RemoteException
import android.provider.ContactsContract
import android.provider.ContactsContract.Groups
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationManagerCompat
import at.bitfire.dav4android.DavAddressBook
import at.bitfire.dav4android.DavResource
import at.bitfire.dav4android.exception.DavException
import at.bitfire.dav4android.property.*
import at.bitfire.davdroid.AccountSettings
import at.bitfire.davdroid.Constants
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.R
import at.bitfire.davdroid.*
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.resource.LocalContact
@@ -84,10 +83,13 @@ class ContactsSyncManager(
authority: String,
syncResult: SyncResult,
val provider: ContentProviderClient,
val localAddressBook: LocalAddressBook
private val localAddressBook: LocalAddressBook
): SyncManager(context, account, settings, extras, authority, syncResult, "addressBook") {
val MAX_MULTIGET = 10
private val MAX_MULTIGET = 10
private var readOnly = false
var numDiscarded = 0
private var hasVCard4 = false
private lateinit var groupMethod: GroupMethod
@@ -122,6 +124,8 @@ class ContactsSyncManager(
collectionURL = HttpUrl.parse(localAddressBook.getURL()) ?: return false
davCollection = DavAddressBook(httpClient.okHttpClient, collectionURL)
readOnly = localAddressBook.getReadOnly()
return true
}
@@ -139,50 +143,105 @@ class ContactsSyncManager(
localAddressBook.includeGroups = groupMethod == GroupMethod.GROUP_VCARDS
}
override fun processLocallyDeleted() {
if (readOnly) {
for (group in localAddressBook.getDeletedGroups()) {
Logger.log.warning("Restoring locally deleted group (read-only address book!)")
group.resetDeleted()
numDiscarded++
}
for (contact in localAddressBook.getDeletedContacts()) {
Logger.log.warning("Restoring locally deleted contact (read-only address book!)")
contact.resetDeleted()
numDiscarded++
}
if (numDiscarded > 0)
notifyDiscardedChange()
} else
// mirror deletions to remote collection (DELETE)
super.processLocallyDeleted()
}
override fun prepareDirty() {
// generate UID/file name for newly created contacts
super.prepareDirty()
if (groupMethod == GroupMethod.CATEGORIES) {
/* groups memberships are represented as contact CATEGORIES */
// groups with DELETED=1: set all members to dirty, then remove group
for (group in localAddressBook.getDeletedGroups()) {
Logger.log.fine("Finally removing group $group")
// useless because Android deletes group memberships as soon as a group is set to DELETED:
// group.markMembersDirty()
group.delete()
}
// groups with DIRTY=1: mark all memberships as dirty, then clean DIRTY flag of group
if (readOnly) {
for (group in localAddressBook.getDirtyGroups()) {
Logger.log.fine("Marking members of modified group $group as dirty")
group.markMembersDirty()
Logger.log.warning("Resetting locally modified group to ETag=null (read-only address book!)")
group.clearDirty(null)
numDiscarded++
}
} else {
/* groups as separate VCards: there are group contacts and individual contacts */
// mark groups with changed members as dirty
val batch = BatchOperation(localAddressBook.provider!!)
for (contact in localAddressBook.getDirtyContacts())
try {
Logger.log.fine("Looking for changed group memberships of contact ${contact.fileName}")
val cachedGroups = contact.getCachedGroupMemberships()
val currentGroups = contact.getGroupMemberships()
for (groupID in cachedGroups disjunct currentGroups) {
Logger.log.fine("Marking group as dirty: $groupID")
batch.enqueue(BatchOperation.Operation(
ContentProviderOperation.newUpdate(localAddressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, groupID)))
.withValue(Groups.DIRTY, 1)
.withYieldAllowed(true)
))
}
} catch(e: FileNotFoundException) {
for (contact in localAddressBook.getDirtyContacts()) {
Logger.log.warning("Resetting locally modified contact to ETag=null (read-only address book!)")
contact.clearDirty(null)
numDiscarded++
}
if (numDiscarded > 0)
notifyDiscardedChange()
} else {
if (groupMethod == GroupMethod.CATEGORIES) {
/* groups memberships are represented as contact CATEGORIES */
// groups with DELETED=1: set all members to dirty, then remove group
for (group in localAddressBook.getDeletedGroups()) {
Logger.log.fine("Finally removing group $group")
// useless because Android deletes group memberships as soon as a group is set to DELETED:
// group.markMembersDirty()
group.delete()
}
batch.commit()
// groups with DIRTY=1: mark all memberships as dirty, then clean DIRTY flag of group
for (group in localAddressBook.getDirtyGroups()) {
Logger.log.fine("Marking members of modified group $group as dirty")
group.markMembersDirty()
group.clearDirty(null)
}
} else {
/* groups as separate VCards: there are group contacts and individual contacts */
// mark groups with changed members as dirty
val batch = BatchOperation(localAddressBook.provider!!)
for (contact in localAddressBook.getDirtyContacts())
try {
Logger.log.fine("Looking for changed group memberships of contact ${contact.fileName}")
val cachedGroups = contact.getCachedGroupMemberships()
val currentGroups = contact.getGroupMemberships()
for (groupID in cachedGroups disjunct currentGroups) {
Logger.log.fine("Marking group as dirty: $groupID")
batch.enqueue(BatchOperation.Operation(
ContentProviderOperation.newUpdate(localAddressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, groupID)))
.withValue(Groups.DIRTY, 1)
.withYieldAllowed(true)
))
}
} catch(e: FileNotFoundException) {
}
batch.commit()
}
}
}
private fun notifyDiscardedChange() {
val notification = NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_delete_light)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(context.getString(R.string.sync_contacts_read_only_address_book))
.setContentText(context.resources.getQuantityString(R.plurals.sync_contacts_local_contact_changes_discarded, numDiscarded, numDiscarded))
.setSubText(account.name)
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setLocalOnly(true)
.setAutoCancel(true)
.build()
NotificationManagerCompat.from(context).notify("discarded_${account.name}", 0, notification)
}
override fun prepareUpload(resource: LocalResource): RequestBody {
val contact: Contact
if (resource is LocalContact) {

View File

@@ -252,7 +252,7 @@ abstract class SyncManager(
* Process locally deleted entries (DELETE them on the server as well).
* Checks Thread.interrupted() before each request to allow quick sync cancellation.
*/
protected fun processLocallyDeleted() {
protected open fun processLocallyDeleted() {
// Remove locally deleted entries from server (if they have a name, i.e. if they were uploaded before),
// but only if they don't have changed on the server. Then finally remove them from the local address book.
val localList = localCollection.getDeleted()

View File

@@ -71,7 +71,7 @@ class AccountActivity: AppCompatActivity(), Toolbar.OnMenuItemClickListener, Pop
}
lateinit var account: Account
var accountInfo: AccountInfo? = null
private var accountInfo: AccountInfo? = null
override fun onCreate(savedInstanceState: Bundle?) {
@@ -202,10 +202,13 @@ class AccountActivity: AppCompatActivity(), Toolbar.OnMenuItemClickListener, Pop
db.setTransactionSuccessful()
db.endTransaction()
info.selected = nowChecked
adapter.notifyDataSetChanged()
}
info.selected = nowChecked
adapter.notifyDataSetChanged()
if (nowChecked && info.type == CollectionInfo.Type.ADDRESS_BOOK && info.readOnly)
Snackbar.make(parent, R.string.account_read_only_address_book_selected, Snackbar.LENGTH_LONG).show()
}
private val onItemLongClickListener = AdapterView.OnItemLongClickListener { parent, view, position, _ ->

View File

@@ -0,0 +1,17 @@
<!--
~ Copyright © Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@@ -89,12 +89,16 @@
<string name="account_delete">Konto löschen</string>
<string name="account_delete_confirmation_title">Konto wirklich löschen?</string>
<string name="account_delete_confirmation_text">Alle Adressbücher, Kalender und Aufgabenlisten werden vom Gerät (nicht am Server) gelöscht.</string>
<string name="account_carddav">CardDAV</string>
<string name="account_caldav">CalDAV</string>
<string name="account_webcal">Webcal</string>
<string name="account_refresh_address_book_list">Adressbücher neu erkennen</string>
<string name="account_create_new_address_book">Neues Adressbuch erstellen</string>
<string name="account_refresh_calendar_list">Kalender neu erkennen</string>
<string name="account_create_new_calendar">Neuen Kalender erstellen</string>
<string name="account_no_webcal_handler_found">Keine Webcal-App gefunden</string>
<string name="account_install_icsdroid">ICSdroid installieren</string>
<string name="account_read_only_address_book_selected">Schreibgeschütztes Adressbuch lokale Änderungen werden verworfen!</string>
<!--PermissionsActivity-->
<string name="permissions_title">DAVdroid-Berechtigungen</string>
<string name="permissions_calendar">Kalender-Zugriff</string>
@@ -212,8 +216,13 @@
<string name="exception_httpexception">Ein HTTP-Fehler ist aufgetreten.</string>
<string name="exception_ioexception">Ein E/A-Fehler ist aufgetreten.</string>
<string name="exception_show_details">Details anzeigen</string>
<!--sync errors and DebugInfoActivity-->
<!--sync adapters and DebugInfoActivity-->
<string name="debug_info_title">Informationen zur Fehlersuche</string>
<string name="sync_contacts_read_only_address_book">Schreibgeschütztes Adressbuch</string>
<plurals name="sync_contacts_local_contact_changes_discarded">
<item quantity="one">Lokale Kontakt-Änderung verworfen</item>
<item quantity="other">%d lokale Kontakt-Änderungen verworfen</item>
</plurals>
<string name="sync_error_permissions">DAVdroid-Berechtigungen</string>
<string name="sync_error_permissions_text">Zusätzliche Berechtigungen benötigt</string>
<string name="sync_error_calendar">Kalender-Synchronisierung fehlgeschlagen (%s)</string>

View File

@@ -120,6 +120,7 @@
<string name="account_create_new_calendar">Create new calendar</string>
<string name="account_no_webcal_handler_found">No Webcal-capable app found</string>
<string name="account_install_icsdroid">Install ICSdroid</string>
<string name="account_read_only_address_book_selected">Read-only address book local changes will be discarded!</string>
<!-- PermissionsActivity -->
<string name="permissions_title">DAVdroid permissions</string>
@@ -254,9 +255,14 @@
<string name="exception_ioexception">An I/O error has occurred.</string>
<string name="exception_show_details">Show details</string>
<!-- sync errors and DebugInfoActivity -->
<!-- sync adapters and DebugInfoActivity -->
<string name="authority_log_provider">at.bitfire.davdroid.log</string>
<string name="debug_info_title">Debug info</string>
<string name="sync_contacts_read_only_address_book">Read-only address book</string>
<plurals name="sync_contacts_local_contact_changes_discarded">
<item quantity="one">Local contact change discarded</item>
<item quantity="other">%d local contact changes discarded</item>
</plurals>
<string name="sync_error_permissions">DAVdroid permissions</string>
<string name="sync_error_permissions_text">Additional permissions required</string>
<string name="sync_error_calendar">Calendar synchronization failed (%s)</string>