diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/repository/DavHomeSetRepositoryTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/repository/DavHomeSetRepositoryTest.kt index 1af05be25..a39177f37 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/repository/DavHomeSetRepositoryTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/repository/DavHomeSetRepositoryTest.kt @@ -41,17 +41,17 @@ class DavHomeSetRepositoryTest { val entry1 = HomeSet(id=0, serviceId=serviceId, personal=true, url="https://example.com/1".toHttpUrl()) val insertId1 = repository.insertOrUpdateByUrl(entry1) assertEquals(1L, insertId1) - assertEquals(entry1.apply { id = 1L }, repository.getById(1L)) + assertEquals(entry1.copy(id = 1L), repository.getById(1L)) val updatedEntry1 = HomeSet(id=0, serviceId=serviceId, personal=true, url="https://example.com/1".toHttpUrl(), displayName="Updated Entry") val updateId1 = repository.insertOrUpdateByUrl(updatedEntry1) assertEquals(1L, updateId1) - assertEquals(updatedEntry1.apply { id = 1L }, repository.getById(1L)) + assertEquals(updatedEntry1.copy(id = 1L), repository.getById(1L)) val entry2 = HomeSet(id=0, serviceId=serviceId, personal=true, url= "https://example.com/2".toHttpUrl()) val insertId2 = repository.insertOrUpdateByUrl(entry2) assertEquals(2L, insertId2) - assertEquals(entry2.apply { id = 2L }, repository.getById(2L)) + assertEquals(entry2.copy(id = 2L), repository.getById(2L)) } @Test diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt index 1fbc0269f..9aa1b4693 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt @@ -54,24 +54,24 @@ annotation class CollectionType ) data class Collection( @PrimaryKey(autoGenerate = true) - var id: Long = 0, + val id: Long = 0, /** * Service, which this collection belongs to. Services are unique, so a [Collection] is uniquely * identifiable via its [serviceId] and [url]. */ - var serviceId: Long = 0, + val serviceId: Long = 0, /** * A home set this collection belongs to. Multiple homesets are not supported. * If *null* the collection is considered homeless. */ - var homeSetId: Long? = null, + val homeSetId: Long? = null, /** * Principal who is owner of this collection. */ - var ownerId: Long? = null, + val ownerId: Long? = null, /** * Type of service. CalDAV or CardDAV @@ -82,68 +82,68 @@ data class Collection( /** * Address where this collection lives - with trailing slash */ - var url: HttpUrl, + val url: HttpUrl, /** * Whether we have the permission to change contents of the collection on the server. * Even if this flag is set, there may still be other reasons why a collection is effectively read-only. */ - var privWriteContent: Boolean = true, + val privWriteContent: Boolean = true, /** * Whether we have the permission to delete the collection on the server */ - var privUnbind: Boolean = true, + val privUnbind: Boolean = true, /** * Whether the user has manually set the "force read-only" flag. * Even if this flag is not set, there may still be other reasons why a collection is effectively read-only. */ - var forceReadOnly: Boolean = false, + val forceReadOnly: Boolean = false, /** * Human-readable name of the collection */ - var displayName: String? = null, + val displayName: String? = null, /** * Human-readable description of the collection */ - var description: String? = null, + val description: String? = null, // CalDAV only - var color: Int? = null, + val color: Int? = null, /** default timezone (only timezone ID, like `Europe/Vienna`) */ - var timezoneId: String? = null, + val timezoneId: String? = null, /** whether the collection supports VEVENT; in case of calendars: null means true */ - var supportsVEVENT: Boolean? = null, + val supportsVEVENT: Boolean? = null, /** whether the collection supports VTODO; in case of calendars: null means true */ - var supportsVTODO: Boolean? = null, + val supportsVTODO: Boolean? = null, /** whether the collection supports VJOURNAL; in case of calendars: null means true */ - var supportsVJOURNAL: Boolean? = null, + val supportsVJOURNAL: Boolean? = null, /** Webcal subscription source URL */ - var source: HttpUrl? = null, + val source: HttpUrl? = null, /** whether this collection has been selected for synchronization */ - var sync: Boolean = false, + val sync: Boolean = false, /** WebDAV-Push topic */ - var pushTopic: String? = null, + val pushTopic: String? = null, /** WebDAV-Push: whether this collection supports the Web Push Transport */ @ColumnInfo(defaultValue = "0") - var supportsWebPush: Boolean = false, + val supportsWebPush: Boolean = false, /** WebDAV-Push subscription URL */ - var pushSubscription: String? = null, + val pushSubscription: String? = null, /** when the [pushSubscription] expires (timestamp, used to determine whether we need to re-subscribe) */ - var pushSubscriptionExpires: Long? = null, + val pushSubscriptionExpires: Long? = null, /** when the [pushSubscription] was created/updated (timestamp) */ - var pushSubscriptionCreated: Long? = null + val pushSubscriptionCreated: Long? = null ) { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/HomeSet.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/HomeSet.kt index 12b2e3cbd..9f32a3388 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/HomeSet.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/HomeSet.kt @@ -22,20 +22,20 @@ import okhttp3.HttpUrl ) data class HomeSet( @PrimaryKey(autoGenerate = true) - var id: Long, + val id: Long, - var serviceId: Long, + val serviceId: Long, /** * Whether this homeset belongs to the [Service.principal] given by [serviceId]. */ - var personal: Boolean, + val personal: Boolean, - var url: HttpUrl, + val url: HttpUrl, - var privBind: Boolean = true, + val privBind: Boolean = true, - var displayName: String? = null + val displayName: String? = null ) { fun title() = displayName ?: url.lastSegment diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/Principal.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/Principal.kt index cb69ce621..358a6f01a 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/Principal.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/Principal.kt @@ -26,11 +26,11 @@ import okhttp3.HttpUrl ) data class Principal( @PrimaryKey(autoGenerate = true) - var id: Long = 0, - var serviceId: Long, + val id: Long = 0, + val serviceId: Long, /** URL of the principal, always without trailing slash */ - var url: HttpUrl, - var displayName: String? = null + val url: HttpUrl, + val displayName: String? = null ) { companion object { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt index 66837d951..7093e1b2e 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt @@ -26,14 +26,14 @@ annotation class ServiceType ]) data class Service( @PrimaryKey(autoGenerate = true) - var id: Long, + val id: Long, - var accountName: String, + val accountName: String, @ServiceType - var type: String, + val type: String, - var principal: HttpUrl? + val principal: HttpUrl? ) { companion object { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/SyncStats.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/SyncStats.kt index 9d4fa20c8..acb3d8acd 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/SyncStats.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/SyncStats.kt @@ -24,5 +24,5 @@ data class SyncStats( val collectionId: Long, val authority: String, - var lastSync: Long + val lastSync: Long ) \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt index e0d5e45b8..c8b3ab55f 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt @@ -35,30 +35,30 @@ import java.time.Instant data class WebDavDocument( @PrimaryKey(autoGenerate = true) - var id: Long = 0, + val id: Long = 0, /** refers to the [WebDavMount] the document belongs to */ val mountId: Long, /** refers to parent document (*null* when this document is a root document) */ - var parentId: Long?, + val parentId: Long?, /** file name (without any slashes) */ - var name: String, - var isDirectory: Boolean = false, + val name: String, + val isDirectory: Boolean = false, - var displayName: String? = null, - var mimeType: MediaType? = null, - var eTag: String? = null, - var lastModified: Long? = null, - var size: Long? = null, + val displayName: String? = null, + val mimeType: MediaType? = null, + val eTag: String? = null, + val lastModified: Long? = null, + val size: Long? = null, - var mayBind: Boolean? = null, - var mayUnbind: Boolean? = null, - var mayWriteContent: Boolean? = null, + val mayBind: Boolean? = null, + val mayUnbind: Boolean? = null, + val mayWriteContent: Boolean? = null, - var quotaAvailable: Long? = null, - var quotaUsed: Long? = null + val quotaAvailable: Long? = null, + val quotaUsed: Long? = null ) { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocumentDao.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocumentDao.kt index 83fd831b3..dc0c237f9 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocumentDao.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocumentDao.kt @@ -77,8 +77,7 @@ interface WebDavDocumentDao { displayName = mount.name ) val id = insertOrReplace(newDoc) - newDoc.id = id - return newDoc + return newDoc.copy(id = id) } } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavMount.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavMount.kt index 05e6c96d9..c05888b9c 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavMount.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/WebDavMount.kt @@ -11,13 +11,13 @@ import okhttp3.HttpUrl @Entity(tableName = "webdav_mount") data class WebDavMount( @PrimaryKey(autoGenerate = true) - var id: Long = 0, + val id: Long = 0, /** display name of the WebDAV mount */ - var name: String, + val name: String, /** URL of the WebDAV service, including trailing slash */ - var url: HttpUrl + val url: HttpUrl // credentials are stored using CredentialsStore diff --git a/app/src/main/kotlin/at/bitfire/davdroid/repository/AccountRepository.kt b/app/src/main/kotlin/at/bitfire/davdroid/repository/AccountRepository.kt index 95b574fce..ac39d67c8 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/repository/AccountRepository.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/repository/AccountRepository.kt @@ -258,8 +258,7 @@ class AccountRepository @Inject constructor( // insert collections for (collection in info.collections.values) { - collection.serviceId = serviceId - collectionRepository.insertOrUpdateByUrl(collection) + collectionRepository.insertOrUpdateByUrl(collection.copy(serviceId = serviceId)) } return serviceId diff --git a/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt b/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt index d056b174c..0b2f490f7 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt @@ -55,8 +55,8 @@ import javax.inject.Inject */ class DavCollectionRepository @Inject constructor( private val accountSettingsFactory: AccountSettings.Factory, - @ApplicationContext val context: Context, - db: AppDatabase, + @ApplicationContext private val context: Context, + private val db: AppDatabase, defaultListeners: Lazy>, private val serviceRepository: DavServiceRepository ) { @@ -68,8 +68,7 @@ class DavCollectionRepository @Inject constructor( /** * Whether there are any collections that are registered for push. */ - suspend fun anyPushCapable() = - dao.anyPushCapable() + suspend fun anyPushCapable() = dao.anyPushCapable() /** * Creates address book collection on server and locally @@ -217,20 +216,28 @@ class DavCollectionRepository @Inject constructor( dao.getPushRegisteredAndNotSyncable() /** - * Inserts or updates the collection. On update it will not update flag values ([Collection.sync], - * [Collection.forceReadOnly]), but use the values of the already existing collection. + * Inserts or updates the collection. + * + * On update, it will _not_ update the flags + * - [Collection.sync] and + * - [Collection.forceReadOnly], + * but use the values of the already existing collection. * * @param newCollection Collection to be inserted or updated */ fun insertOrUpdateByUrlAndRememberFlags(newCollection: Collection) { - // remember locally set flags - dao.getByServiceAndUrl(newCollection.serviceId, newCollection.url.toString())?.let { oldCollection -> - newCollection.sync = oldCollection.sync - newCollection.forceReadOnly = oldCollection.forceReadOnly + db.runInTransaction { + // remember locally set flags + val oldCollection = dao.getByServiceAndUrl(newCollection.serviceId, newCollection.url.toString()) + val newCollectionWithFlags = + if (oldCollection != null) + newCollection.copy(sync = oldCollection.sync, forceReadOnly = oldCollection.forceReadOnly) + else + newCollection + + // commit new collection to database + insertOrUpdateByUrl(newCollectionWithFlags) } - - // commit to database - insertOrUpdateByUrl(newCollection) } /** diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt index 3c7a8629c..ec06c4731 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt @@ -39,22 +39,28 @@ class LocalCalendarStore @Inject constructor( val account = Account(service.accountName, context.getString(R.string.account_type)) // If the collection doesn't have a color, use a default color. - if (fromCollection.color != null) - fromCollection.color = Constants.DAVDROID_GREEN_RGBA - - val values = valuesFromCollectionInfo(fromCollection, withColor = true) - - // ACCOUNT_NAME and ACCOUNT_TYPE are required (see docs)! If it's missing, other apps will crash. - values.put(Calendars.ACCOUNT_NAME, account.name) - values.put(Calendars.ACCOUNT_TYPE, account.type) - - // Email address for scheduling. Used by the calendar provider to determine whether the - // user is ORGANIZER/ATTENDEE for a certain event. - values.put(Calendars.OWNER_ACCOUNT, account.name) - - // flag as visible & syncable at creation, might be changed by user at any time - values.put(Calendars.VISIBLE, 1) - values.put(Calendars.SYNC_EVENTS, 1) + val collectionWithColor = + if (fromCollection.color != null) + fromCollection + else + fromCollection.copy(color = Constants.DAVDROID_GREEN_RGBA) + + val values = valuesFromCollectionInfo( + info = collectionWithColor, + withColor = true + ).apply { + // ACCOUNT_NAME and ACCOUNT_TYPE are required (see docs)! If it's missing, other apps will crash. + put(Calendars.ACCOUNT_NAME, account.name) + put(Calendars.ACCOUNT_TYPE, account.type) + + // Email address for scheduling. Used by the calendar provider to determine whether the + // user is ORGANIZER/ATTENDEE for a certain event. + put(Calendars.OWNER_ACCOUNT, account.name) + + // flag as visible & syncable at creation, might be changed by user at any time + put(Calendars.VISIBLE, 1) + put(Calendars.SYNC_EVENTS, 1) + } logger.log(Level.INFO, "Adding local calendar", values) val uri = AndroidCalendar.create(account, provider, values) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalJtxCollectionStore.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalJtxCollectionStore.kt index 3deecf075..194fc1122 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalJtxCollectionStore.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalJtxCollectionStore.kt @@ -35,13 +35,21 @@ class LocalJtxCollectionStore @Inject constructor( private val serviceDao = db.serviceDao() override fun create(provider: ContentProviderClient, fromCollection: Collection): LocalJtxCollection? { - // If the collection doesn't have a color, use a default color. - if (fromCollection.color != null) - fromCollection.color = Constants.DAVDROID_GREEN_RGBA - val service = serviceDao.get(fromCollection.serviceId) ?: throw IllegalArgumentException("Couldn't fetch DB service from collection") val account = Account(service.accountName, context.getString(R.string.account_type)) - val values = valuesFromCollection(fromCollection, account = account, withColor = true) + + // If the collection doesn't have a color, use a default color. + val collectionWithColor = + if (fromCollection.color != null) + fromCollection + else + fromCollection.copy(color = Constants.DAVDROID_GREEN_RGBA) + + val values = valuesFromCollection( + info = collectionWithColor, + account = account, + withColor = true + ) val uri = JtxCollection.create(account, provider, values) return LocalJtxCollection(account, provider, ContentUris.parseId(uri)) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalTaskListStore.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalTaskListStore.kt index 20cf7b83a..72a67bc3d 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalTaskListStore.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalTaskListStore.kt @@ -54,15 +54,21 @@ class LocalTaskListStore @AssistedInject constructor( return DmfsTaskList.findByID(account, provider, providerName, LocalTaskList.Factory, ContentUris.parseId(uri)) } - private fun create(account: Account, provider: ContentProviderClient, providerName: TaskProvider.ProviderName, info: Collection): Uri { + private fun create(account: Account, provider: ContentProviderClient, providerName: TaskProvider.ProviderName, fromCollection: Collection): Uri { // If the collection doesn't have a color, use a default color. - if (info.color != null) - info.color = Constants.DAVDROID_GREEN_RGBA - - val values = valuesFromCollectionInfo(info, withColor = true) - values.put(TaskLists.OWNER, account.name) - values.put(TaskLists.SYNC_ENABLED, 1) - values.put(TaskLists.VISIBLE, 1) + val collectionWithColor = if (fromCollection.color != null) + fromCollection + else + fromCollection.copy(color = Constants.DAVDROID_GREEN_RGBA) + + val values = valuesFromCollectionInfo( + info = collectionWithColor, + withColor = true + ).apply { + put(TaskLists.OWNER, account.name) + put(TaskLists.SYNC_ENABLED, 1) + put(TaskLists.VISIBLE, 1) + } return DmfsTaskList.Companion.create(account, provider, providerName, values) } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/CollectionListRefresher.kt b/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/CollectionListRefresher.kt index 68f817062..ca70c0092 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/CollectionListRefresher.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/CollectionListRefresher.kt @@ -41,8 +41,8 @@ import java.util.logging.Logger * Logic for refreshing the list of collections and home-sets and related information. */ class CollectionListRefresher @AssistedInject constructor( - @Assisted val service: Service, - @Assisted val httpClient: OkHttpClient, + @Assisted private val service: Service, + @Assisted private val httpClient: OkHttpClient, private val db: AppDatabase, private val collectionRepository: DavCollectionRepository, private val homeSetRepository: DavHomeSetRepository, @@ -191,29 +191,24 @@ class CollectionListRefresher @AssistedInject constructor( if (!response.isSuccess()) return@propfind - if (relation == Response.HrefRelation.SELF) { - // this response is about the homeset itself - localHomeset.displayName = response[DisplayName::class.java]?.displayName - localHomeset.privBind = response[CurrentUserPrivilegeSet::class.java]?.mayBind ?: true - homeSetRepository.insertOrUpdateByUrl(localHomeset) - } + if (relation == Response.HrefRelation.SELF) + // this response is about the home set itself + homeSetRepository.insertOrUpdateByUrl(localHomeset.copy( + displayName = response[DisplayName::class.java]?.displayName, + privBind = response[CurrentUserPrivilegeSet::class.java]?.mayBind != false + )) // in any case, check whether the response is about a usable collection - val collection = Collection.fromDavResponse(response) ?: return@propfind - - collection.serviceId = service.id - collection.homeSetId = localHomeset.id - collection.sync = shouldPreselect(collection, homesets.values) - - // .. and save the principal url (collection owner) - response[Owner::class.java]?.href - ?.let { response.href.resolve(it) } - ?.let { principalUrl -> - val principal = Principal.fromServiceAndUrl(service, principalUrl) - val id = db.principalDao().insertOrUpdate(service.id, principal) - collection.ownerId = id - } - + var collection = Collection.fromDavResponse(response) ?: return@propfind + collection = collection.copy( + serviceId = service.id, + homeSetId = localHomeset.id, + sync = shouldPreselect(collection, homesets.values), + ownerId = response[Owner::class.java]?.href // save the principal id (collection owner) + ?.let { response.href.resolve(it) } + ?.let { principalUrl -> Principal.fromServiceAndUrl(service, principalUrl) } + ?.let { principal -> db.principalDao().insertOrUpdate(service.id, principal) } + ) logger.log(Level.FINE, "Found collection", collection) // save or update collection if usable (ignore it otherwise) @@ -230,10 +225,10 @@ class CollectionListRefresher @AssistedInject constructor( } // Mark leftover (not rediscovered) collections from queue as homeless (remove association) - for ((_, homelessCollection) in localHomesetCollections) { - homelessCollection.homeSetId = null - collectionRepository.insertOrUpdateByUrlAndRememberFlags(homelessCollection) - } + for ((_, homelessCollection) in localHomesetCollections) + collectionRepository.insertOrUpdateByUrlAndRememberFlags( + homelessCollection.copy(homeSetId = null) + ) } } @@ -256,18 +251,13 @@ class CollectionListRefresher @AssistedInject constructor( Collection.fromDavResponse(response)?.let { collection -> if (!isUsableCollection(collection)) return@let - collection.serviceId = localCollection.serviceId // use same service ID as previous entry - - // .. and save the principal url (collection owner) - response[Owner::class.java]?.href - ?.let { response.href.resolve(it) } - ?.let { principalUrl -> - val principal = Principal.fromServiceAndUrl(service, principalUrl) - val principalId = db.principalDao().insertOrUpdate(service.id, principal) - collection.ownerId = principalId - } - - collectionRepository.insertOrUpdateByUrlAndRememberFlags(collection) + collectionRepository.insertOrUpdateByUrlAndRememberFlags(collection.copy( + serviceId = localCollection.serviceId, // use same service ID as previous entry + ownerId = response[Owner::class.java]?.href // save the principal id (collection owner) + ?.let { response.href.resolve(it) } + ?.let { principalUrl -> Principal.fromServiceAndUrl(service, principalUrl) } + ?.let { principal -> db.principalDao().insertOrUpdate(service.id, principal) } + )) } ?: collectionRepository.delete(localCollection) } } catch (e: HttpException) { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt b/app/src/main/kotlin/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt index a757d5ffd..ea562d338 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/webdav/DavDocumentsProvider.kt @@ -420,8 +420,7 @@ class DavDocumentsProvider: DocumentsProvider() { // successfully moved } - doc.parentId = dstParent.id - documentDao.update(doc) + documentDao.update(doc.copy(parentId = dstParent.id)) actor.notifyFolderChanged(sourceParentDocumentId) actor.notifyFolderChanged(targetParentDocumentId) @@ -449,8 +448,7 @@ class DavDocumentsProvider: DocumentsProvider() { dav.move(newLocation, false) { // successfully renamed } - doc.name = newName - documentDao.update(doc) + documentDao.update(doc.copy(name = newName)) actor.notifyFolderChanged(doc.parentId) return doc.id.toString() @@ -531,9 +529,7 @@ class DavDocumentsProvider: DocumentsProvider() { val now = System.currentTimeMillis() if (!readAccess /* write access */) { // write access, update file size - doc.size = transferred - doc.lastModified = now - documentDao.update(doc) + documentDao.update(doc.copy(size = transferred, lastModified = now)) } actor.notifyFolderChanged(doc.parentId) @@ -671,32 +667,25 @@ class DavDocumentsProvider: DocumentsProvider() { } } - response[ResourceType::class.java]?.types?.let { types -> - resource.isDirectory = types.contains(ResourceType.COLLECTION) - } - - resource.displayName = response[DisplayName::class.java]?.displayName - resource.mimeType = response[GetContentType::class.java]?.type - response[GetETag::class.java]?.let { getETag -> - if (!getETag.weak) - resource.eTag = resource.eTag - } - resource.lastModified = response[GetLastModified::class.java]?.lastModified?.toEpochMilli() - resource.size = response[GetContentLength::class.java]?.contentLength - - val privs = response[CurrentUserPrivilegeSet::class.java] - resource.mayBind = privs?.mayBind - resource.mayUnbind = privs?.mayUnbind - resource.mayWriteContent = privs?.mayWriteContent - - resource.quotaAvailable = response[QuotaAvailableBytes::class.java]?.quotaAvailableBytes - resource.quotaUsed = response[QuotaUsedBytes::class.java]?.quotaUsedBytes + val updatedResource = resource.copy( + isDirectory = response[ResourceType::class.java]?.types?.contains(ResourceType.COLLECTION) ?: resource.isDirectory, + displayName = response[DisplayName::class.java]?.displayName, + mimeType = response[GetContentType::class.java]?.type, + eTag = response[GetETag::class.java]?.takeIf { !it.weak }?.let { resource.eTag }, + lastModified = response[GetLastModified::class.java]?.lastModified?.toEpochMilli(), + size = response[GetContentLength::class.java]?.contentLength, + mayBind = response[CurrentUserPrivilegeSet::class.java]?.mayBind, + mayUnbind = response[CurrentUserPrivilegeSet::class.java]?.mayUnbind, + mayWriteContent = response[CurrentUserPrivilegeSet::class.java]?.mayWriteContent, + quotaAvailable = response[QuotaAvailableBytes::class.java]?.quotaAvailableBytes, + quotaUsed = response[QuotaUsedBytes::class.java]?.quotaUsedBytes, + ) if (resource == parent) - documentDao.update(resource) + documentDao.update(updatedResource) else { - documentDao.insertOrUpdate(resource) - newChildrenList[resource.name] = resource + documentDao.insertOrUpdate(updatedResource) + newChildrenList[resource.name] = updatedResource } // remove resource from known child nodes, because not found on server