-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add initial crossplatform backup serialization [WPB-10575] #3121
feat: add initial crossplatform backup serialization [WPB-10575] #3121
Conversation
This commit introduces a new cross-platform backup module to the project with support for iOS, Web, and Android. Additionally, it enables JavaScript multiplatform support in existing `kalium/network-model` and `kalium/data` projects.
This commit introduces a new multiplatform backup feature including export and import capabilities. It adds data classes, serialization, tests, and Gradle dependencies to support cross-platform backup data handling, including proper ProtoBuf serialization.
Test Results3 309 tests 3 202 ✅ 5m 1s ⏱️ Results for commit bc8ddeb. ♻️ This comment has been updated with latest results. |
Datadog ReportBranch report: ✅ 0 Failed, 3202 Passed, 107 Skipped, 34.91s Total Time |
…latform-backup-serialization
Quality Gate passedIssues Measures |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## epic/multiplatform-backup #3121 +/- ##
============================================================
Coverage ? 54.03%
============================================================
Files ? 1246
Lines ? 36152
Branches ? 3656
============================================================
Hits ? 19534
Misses ? 15207
Partials ? 1411 Continue to review full report in Codecov by Sentry.
|
|
||
import kotlin.js.JsExport | ||
|
||
@JsExport |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JsExport
is needed so this class can be called from JS later.
expect class BackupDateTime | ||
|
||
expect fun BackupDateTime(timestampMillis: Long): BackupDateTime | ||
expect fun BackupDateTime.toLongMilliseconds(): Long |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is because JS doesn't have 64-bit Integers (Long).
So we can use Long for iOS/Android, and a custom Date wrapper for JS.
@ObjCName("add") | ||
fun addUser(user: BackupUser) { | ||
allUsers.add(user) | ||
} | ||
|
||
@ObjCName("add") | ||
fun addConversation(conversation: BackupConversation) { | ||
allConversations.add(conversation) | ||
} | ||
|
||
@ObjCName("add") | ||
fun addMessage(message: BackupMessage) { | ||
allMessages.add(message) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was planning on having add
for all three methods, only changing the parameter.
Unfortunately it doesn't work on JS, as it is not a typed language...
So at least when calling from Swift it will look like this:
backupExporter.add(user: BackupUser(...))
backupExporter.add(conversation: BackupConversation(...))
backupExporter.add(message: BackupMesage(...))
BackupMessageContent.Text(proContent.value.content) | ||
} | ||
|
||
null -> TODO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in the next PR:
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (other == null || this::class.js != other::class.js) return false | ||
|
||
other as BackupDateTime | ||
|
||
return this.toLongMilliseconds() == other.toLongMilliseconds() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason backupDateTime == backupDateTime
doesn't work on JS, so I had to do it myself like so.
|
||
@JsExport | ||
sealed class BackupMessageContent { | ||
data class Text(val text: String) : BackupMessageContent() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Text messages also contain link previews, mentions, and are possibly a reply to another message. Are we planning to include these in the first version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can expand later, like what's done in:
|
||
@OptIn(ExperimentalStdlibApi::class) | ||
@ShouldRefineInSwift // Hidden in Swift | ||
fun serialize(): ByteArray { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the method we call to produce the backup? The comment suggests it's hidden but it the POC it is visible but returns a KotlinByteArray
which I'm guessing I would create a file with and present it to the user. Though I'm concerned about the size of this data and loading it all into memory at once.
I'm wondering if it would be possible for the client to pass a URL to which the library could write the backup file to. This could allow for more memory efficienct handling of the backup data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed :)
The goal is to implement the byte-reading part in the commonMain
code, which will be used internally for all clients.
JS will only have this bytearray alternative.
Android and iOS will be able to pass paths that will stream and take paginated chunks of data in, without having to load the whole file into memory
This PR only handles initial serialization. There are more PRs incoming with:
- Expanded serialization
- Encryption/Decryption
- Creating APIs specific for dealing with files on iOS and Android
- Solidifying/tweaking the API
PR Submission Checklist for internal contributors
The PR Title
SQPIT-764
The PR Description
What's new in this PR?
Issues
This PR adds initial serialization/deserialization to the backup module.
Solutions
Using Protobuf, and a common implementation for JS and Non-JS.
The main difference between JS and Non-JS, is that:
Dependencies
Needs releases with:
Testing
Test Coverage
PR Post Merge Checklist for internal contributors
References
feat(conversation-list): Sort conversations by most emojis in the title #SQPIT-764
.