diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt
index e8d47ea9..b8c1bb04 100644
--- a/buildSrc/src/main/kotlin/Config.kt
+++ b/buildSrc/src/main/kotlin/Config.kt
@@ -22,7 +22,7 @@ object Config {
const val minSdk = 23
const val targetSdk = 33
const val testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- const val versionName = "1.0.3"
+ const val versionName = "1.0.4"
const val archivesBaseName = "ProtonDrive-$versionName"
val resourceConfigurations = listOf("en")
}
diff --git a/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt b/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt
index ac78b4ae..772dda93 100644
--- a/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt
+++ b/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt
@@ -24,4 +24,4 @@ fun requireField(value: Boolean, lazyMessage: () -> Any) {
val message = lazyMessage()
throw InvalidFieldException(message.toString())
}
-}
\ No newline at end of file
+}
diff --git a/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt b/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt
index 7508b0ee..660f26aa 100644
--- a/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt
+++ b/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt
@@ -21,12 +21,15 @@ package me.proton.core.drive.drivelink.crypto.domain.usecase
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope
+import me.proton.core.drive.base.domain.log.LogTag
+import me.proton.core.drive.base.domain.log.logId
import me.proton.core.drive.base.domain.provider.ConfigurationProvider
import me.proton.core.drive.cryptobase.domain.usecase.UnlockKey
import me.proton.core.drive.drivelink.domain.entity.DriveLink
import me.proton.core.drive.key.domain.extension.keyHolder
import me.proton.core.drive.key.domain.usecase.GetLinkParentKey
import me.proton.core.drive.link.domain.entity.LinkId
+import me.proton.core.util.kotlin.CoreLogger
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@@ -46,7 +49,14 @@ class DecryptDriveLinks @Inject constructor(
val deferred = links.chunkedInto(configurationProvider.decryptionInParallel).map { driveLinks ->
async {
driveLinks.forEach { link ->
- decryptedLinks[link.id] = decryptDriveLink(unlockedKey, link).getOrNull()
+ decryptedLinks[link.id] = decryptDriveLink(unlockedKey, link)
+ .onFailure { error ->
+ CoreLogger.e(
+ LogTag.ENCRYPTION,
+ error,
+ "There was an error decrypting drive link: ${link.id.id.logId()}"
+ )
+ }.getOrNull()
}
}
}
diff --git a/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt b/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt
index d5bf576a..a6eb593a 100644
--- a/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt
+++ b/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt
@@ -20,8 +20,11 @@ package me.proton.core.drive.drivelink.domain.usecase
import me.proton.core.drive.base.domain.entity.CryptoProperty
import me.proton.core.drive.base.domain.entity.TimestampS
import me.proton.core.drive.base.domain.formatter.DateTimeFormatter
+import me.proton.core.drive.base.domain.log.LogTag
+import me.proton.core.drive.base.domain.log.logId
import me.proton.core.drive.drivelink.domain.entity.DriveLink
import me.proton.core.drive.file.base.domain.extension.toXAttr
+import me.proton.core.util.kotlin.CoreLogger
import javax.inject.Inject
class GetLastModified @Inject constructor(
@@ -30,7 +33,18 @@ class GetLastModified @Inject constructor(
operator fun invoke(driveLink: DriveLink): TimestampS {
if (driveLink.cryptoXAttr !is CryptoProperty.Decrypted) return driveLink.lastModified
val xAttrString = driveLink.cryptoXAttr.value ?: return driveLink.lastModified
- return dateTimeFormatter.parseFromIso8601String(iso8601 = xAttrString.toXAttr().common.modificationTime)
- .getOrNull() ?: driveLink.lastModified
+ xAttrString.toXAttr().onSuccess { xAttr ->
+ return dateTimeFormatter.parseFromIso8601String(iso8601 = xAttr.common.modificationTime)
+ .getOrNull() ?: driveLink.lastModified
+ }.onFailure { error ->
+ CoreLogger.d(
+ LogTag.ENCRYPTION,
+ error,
+ "There was an error parsing xAttr of drive link: ${driveLink.id.id.logId()}"
+ )
+ }
+ return driveLink.lastModified
+
+
}
}
diff --git a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt
deleted file mode 100644
index b0b43020..00000000
--- a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2022-2023 Proton AG.
- * This file is part of Proton Core.
- *
- * Proton Core is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Proton Core is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Proton Core. If not, see .
- */
-package me.proton.core.drive.file.base.domain.extension
-
-import kotlinx.serialization.decodeFromString
-import kotlinx.serialization.json.Json
-import me.proton.core.drive.file.base.domain.entity.XAttr
-
-fun String.toXAttr() = Json.decodeFromString(this)
diff --git a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt
index 946d5b01..a447e6ae 100644
--- a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt
+++ b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt
@@ -17,7 +17,19 @@
*/
package me.proton.core.drive.file.base.domain.extension
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import me.proton.core.drive.file.base.domain.entity.XAttr
-fun XAttr.asJson(): String = Json.encodeToString(XAttr.serializer(), this)
+private val json = Json {
+ ignoreUnknownKeys = true
+}
+
+fun String.toXAttr(): Result = try {
+ Result.success(json.decodeFromString(this))
+} catch (e: SerializationException) {
+ Result.failure(e)
+}
+
+fun XAttr.asJson(): String = json.encodeToString(XAttr.serializer(), this)
diff --git a/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt b/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt
new file mode 100644
index 00000000..1e002571
--- /dev/null
+++ b/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 Proton AG.
+ * This file is part of Proton Core.
+ *
+ * Proton Core is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Proton Core is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Proton Core. If not, see .
+ */
+
+package me.proton.core.drive.file.base.domain.extension
+
+import me.proton.core.drive.file.base.domain.entity.XAttr
+import org.intellij.lang.annotations.Language
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class XAttrKtTest {
+
+ @Language("json")
+ val json =
+ """{"Common": {"ModificationTime": "ModificationTime", "unknown_key": null}}"""
+
+ @Test
+ fun deserialization() {
+ assertEquals(
+ Result.success(
+ XAttr(
+ common = XAttr.Common(
+ modificationTime = "ModificationTime"
+ )
+ )
+ ), json.toXAttr()
+ )
+ }
+
+ @Test
+ fun serialization() {
+ val xAttr = XAttr(common = XAttr.Common(modificationTime = "modificationTime"))
+ assertEquals(xAttr, xAttr.asJson().toXAttr().getOrNull())
+ }
+
+ @Test
+ fun `fails with bad input`() {
+ assertTrue("bad input".toXAttr().isFailure)
+ }
+}
\ No newline at end of file
diff --git a/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt b/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt
index dc8c57e0..3ed32ef4 100644
--- a/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt
+++ b/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt
@@ -65,4 +65,4 @@ fun PreviewEmpty(
)
}
}
-}
\ No newline at end of file
+}
diff --git a/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt b/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt
index f76bde25..3a7a4c71 100644
--- a/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt
+++ b/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with Proton Core. If not, see .
*/
-
package me.proton.core.drive.files.preview.presentation.component
import org.junit.Test
@@ -56,4 +55,4 @@ class TextPreviewTest {
assertEquals(listOf("first line", "", "second line"), content)
}
-}
\ No newline at end of file
+}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 8f79040c..1f044bfe 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -29,7 +29,7 @@ androidx-work = "2.7.1"
# Coil
coil = "1.4.0"
# Core
-core = "9.9.1"
+core = "9.9.3"
# Dagger
dagger = "2.44.2"
# Gradle