From 20a80015c0513824df96eb55169b4ba20456891b Mon Sep 17 00:00:00 2001
From: DarkSky <25152247+darkskygit@users.noreply.github.com>
Date: Sun, 28 Dec 2025 21:34:39 +0800
Subject: [PATCH] feat: integrate native indexer for mobile (#14174)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Added full-text search functionality to mobile apps (Android and iOS),
enabling document indexing and search capabilities.
* Enhanced blob upload support with new GraphQL mutations for creating,
completing, and managing file uploads.
* **Improvements**
* iOS and Android now use SQLite storage backend for improved indexing
performance, aligning with desktop experience.
✏️ Tip: You can customize this high-level summary in your review
settings.
---
.../app/affine/pro/plugin/NbStorePlugin.kt | 117 +++
.../affine_mobile_native.kt | 374 ++++++++++
.../src/plugins/nbstore/definitions.ts | 8 +-
.../apps/android/src/plugins/nbstore/index.ts | 8 +-
.../xcshareddata/swiftpm/Package.resolved | 25 +-
.../App/Plugins/NBStore/NBStorePlugin.swift | 173 +++++
.../App/App/uniffi/affine_mobile_native.swift | 692 ++++++++++++++++++
.../App/App/uniffi/affine_mobile_nativeFFI.h | 88 +++
.../AbortBlobUploadMutation.graphql.swift | 48 ++
.../CompleteBlobUploadMutation.graphql.swift | 53 ++
.../CreateBlobUploadMutation.graphql.swift | 103 +++
...GetBlobUploadPartUrlMutation.graphql.swift | 73 ++
.../Enums/BlobUploadMethod.graphql.swift | 11 +
.../BlobUploadPartInput.graphql.swift | 32 +
.../Objects/BlobUploadInit.graphql.swift | 12 +
.../Objects/BlobUploadPart.graphql.swift | 12 +
.../Objects/BlobUploadedPart.graphql.swift | 12 +
.../Schema/SchemaMetadata.graphql.swift | 3 +
packages/frontend/apps/ios/App/Podfile.lock | 12 +-
.../ios/src/plugins/nbstore/definitions.ts | 8 +-
.../apps/ios/src/plugins/nbstore/index.ts | 8 +-
.../modules/workspace-engine/impls/cloud.ts | 7 +-
.../modules/workspace-engine/impls/local.ts | 7 +-
packages/frontend/mobile-native/src/lib.rs | 146 +++-
24 files changed, 1993 insertions(+), 39 deletions(-)
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/AbortBlobUploadMutation.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CompleteBlobUploadMutation.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CreateBlobUploadMutation.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/GetBlobUploadPartUrlMutation.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Enums/BlobUploadMethod.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/InputObjects/BlobUploadPartInput.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadInit.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadPart.graphql.swift
create mode 100644 packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadedPart.graphql.swift
diff --git a/packages/frontend/apps/android/App/app/src/main/java/app/affine/pro/plugin/NbStorePlugin.kt b/packages/frontend/apps/android/App/app/src/main/java/app/affine/pro/plugin/NbStorePlugin.kt
index be0a5107ab..8e206d17f4 100644
--- a/packages/frontend/apps/android/App/app/src/main/java/app/affine/pro/plugin/NbStorePlugin.kt
+++ b/packages/frontend/apps/android/App/app/src/main/java/app/affine/pro/plugin/NbStorePlugin.kt
@@ -618,4 +618,121 @@ class NbStorePlugin : Plugin() {
}
}
}
+
+ @PluginMethod
+ fun ftsAddDocument(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ val indexName = call.getStringEnsure("indexName")
+ val docId = call.getStringEnsure("docId")
+ val text = call.getStringEnsure("text")
+ val index = call.getBoolean("index")
+ ?: throw IllegalArgumentException("index is required")
+ docStoragePool.ftsAddDocument(id, indexName, docId, text, index)
+ call.resolve()
+ } catch (e: Exception) {
+ call.reject("Failed to add document to fts: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsDeleteDocument(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ val indexName = call.getStringEnsure("indexName")
+ val docId = call.getStringEnsure("docId")
+ docStoragePool.ftsDeleteDocument(id, indexName, docId)
+ call.resolve()
+ } catch (e: Exception) {
+ call.reject("Failed to delete document from fts: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsSearch(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ val indexName = call.getStringEnsure("indexName")
+ val query = call.getStringEnsure("query")
+ val results = docStoragePool.ftsSearch(id, indexName, query)
+ val mapped = results.map {
+ JSObject()
+ .put("id", it.id)
+ .put("score", it.score)
+ .put("terms", JSArray(it.terms))
+ }
+ call.resolve(
+ JSObject().put("results", JSArray(mapped))
+ )
+ } catch (e: Exception) {
+ call.reject("Failed to search fts: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsGetDocument(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ val indexName = call.getStringEnsure("indexName")
+ val docId = call.getStringEnsure("docId")
+ val text = docStoragePool.ftsGetDocument(id, indexName, docId)
+ call.resolve(JSObject().put("text", text))
+ } catch (e: Exception) {
+ call.reject("Failed to get fts document: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsGetMatches(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ val indexName = call.getStringEnsure("indexName")
+ val docId = call.getStringEnsure("docId")
+ val query = call.getStringEnsure("query")
+ val matches = docStoragePool.ftsGetMatches(id, indexName, docId, query)
+ val mapped = matches.map {
+ JSObject()
+ .put("start", it.start.toInt())
+ .put("end", it.end.toInt())
+ }
+ call.resolve(JSObject().put("matches", JSArray(mapped)))
+ } catch (e: Exception) {
+ call.reject("Failed to get fts matches: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsFlushIndex(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val id = call.getStringEnsure("id")
+ docStoragePool.ftsFlushIndex(id)
+ call.resolve()
+ } catch (e: Exception) {
+ call.reject("Failed to flush fts index: ${e.message}", null, e)
+ }
+ }
+ }
+
+ @PluginMethod
+ fun ftsIndexVersion(call: PluginCall) {
+ launch(Dispatchers.IO) {
+ try {
+ val version = docStoragePool.ftsIndexVersion()
+ call.resolve(JSObject().put("indexVersion", version))
+ } catch (e: Exception) {
+ call.reject("Failed to get fts index version: ${e.message}", null, e)
+ }
+ }
+ }
}
diff --git a/packages/frontend/apps/android/App/app/src/main/java/uniffi/affine_mobile_native/affine_mobile_native.kt b/packages/frontend/apps/android/App/app/src/main/java/uniffi/affine_mobile_native/affine_mobile_native.kt
index 7e7d67a9f0..902212ceef 100644
--- a/packages/frontend/apps/android/App/app/src/main/java/uniffi/affine_mobile_native/affine_mobile_native.kt
+++ b/packages/frontend/apps/android/App/app/src/main/java/uniffi/affine_mobile_native/affine_mobile_native.kt
@@ -768,6 +768,20 @@ internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -814,6 +828,20 @@ fun uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc(
): Short
fun uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect(
): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_add_document(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_delete_document(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_flush_index(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_document(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_matches(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_index_version(
+): Short
+fun uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_search(
+): Short
fun uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob(
): Short
fun uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob_uploaded_at(
@@ -925,6 +953,20 @@ fun uniffi_affine_mobile_native_fn_method_docstoragepool_delete_doc(`ptr`: Point
): Long
fun uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,
): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_add_document(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`indexName`: RustBuffer.ByValue,`docId`: RustBuffer.ByValue,`text`: RustBuffer.ByValue,`index`: Byte,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_delete_document(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`indexName`: RustBuffer.ByValue,`docId`: RustBuffer.ByValue,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_flush_index(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_document(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`indexName`: RustBuffer.ByValue,`docId`: RustBuffer.ByValue,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_matches(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`indexName`: RustBuffer.ByValue,`docId`: RustBuffer.ByValue,`query`: RustBuffer.ByValue,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_index_version(`ptr`: Pointer,
+): Long
+fun uniffi_affine_mobile_native_fn_method_docstoragepool_fts_search(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`indexName`: RustBuffer.ByValue,`query`: RustBuffer.ByValue,
+): Long
fun uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`key`: RustBuffer.ByValue,
): Long
fun uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob_uploaded_at(`ptr`: Pointer,`universalId`: RustBuffer.ByValue,`peer`: RustBuffer.ByValue,`blobId`: RustBuffer.ByValue,
@@ -1125,6 +1167,27 @@ private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) {
if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect() != 20410.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_add_document() != 37651.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_delete_document() != 47292.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_flush_index() != 9921.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_document() != 45953.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_matches() != 35972.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_index_version() != 44498.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
+ if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_search() != 28341.toShort()) {
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
+ }
if (lib.uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob() != 56927.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
@@ -1423,6 +1486,29 @@ public object FfiConverterLong: FfiConverter {
}
}
+/**
+ * @suppress
+ */
+public object FfiConverterDouble: FfiConverter {
+ override fun lift(value: Double): Double {
+ return value
+ }
+
+ override fun read(buf: ByteBuffer): Double {
+ return buf.getDouble()
+ }
+
+ override fun lower(value: Double): Double {
+ return value
+ }
+
+ override fun allocationSize(value: Double) = 8UL
+
+ override fun write(value: Double, buf: ByteBuffer) {
+ buf.putDouble(value)
+ }
+}
+
/**
* @suppress
*/
@@ -1619,6 +1705,20 @@ public interface DocStoragePoolInterface {
suspend fun `disconnect`(`universalId`: kotlin.String)
+ suspend fun `ftsAddDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String, `text`: kotlin.String, `index`: kotlin.Boolean)
+
+ suspend fun `ftsDeleteDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String)
+
+ suspend fun `ftsFlushIndex`(`universalId`: kotlin.String)
+
+ suspend fun `ftsGetDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String): kotlin.String?
+
+ suspend fun `ftsGetMatches`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String, `query`: kotlin.String): List
+
+ suspend fun `ftsIndexVersion`(): kotlin.UInt
+
+ suspend fun `ftsSearch`(`universalId`: kotlin.String, `indexName`: kotlin.String, `query`: kotlin.String): List
+
suspend fun `getBlob`(`universalId`: kotlin.String, `key`: kotlin.String): Blob?
suspend fun `getBlobUploadedAt`(`universalId`: kotlin.String, `peer`: kotlin.String, `blobId`: kotlin.String): kotlin.Long?
@@ -1885,6 +1985,156 @@ open class DocStoragePool: Disposable, AutoCloseable, DocStoragePoolInterface
}
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsAddDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String, `text`: kotlin.String, `index`: kotlin.Boolean) {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_add_document(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),FfiConverterString.lower(`indexName`),FfiConverterString.lower(`docId`),FfiConverterString.lower(`text`),FfiConverterBoolean.lower(`index`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_void(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_void(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_void(future) },
+ // lift function
+ { Unit },
+
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsDeleteDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String) {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_delete_document(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),FfiConverterString.lower(`indexName`),FfiConverterString.lower(`docId`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_void(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_void(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_void(future) },
+ // lift function
+ { Unit },
+
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsFlushIndex`(`universalId`: kotlin.String) {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_flush_index(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_void(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_void(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_void(future) },
+ // lift function
+ { Unit },
+
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsGetDocument`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String) : kotlin.String? {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_document(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),FfiConverterString.lower(`indexName`),FfiConverterString.lower(`docId`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_rust_buffer(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_rust_buffer(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_rust_buffer(future) },
+ // lift function
+ { FfiConverterOptionalString.lift(it) },
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsGetMatches`(`universalId`: kotlin.String, `indexName`: kotlin.String, `docId`: kotlin.String, `query`: kotlin.String) : List {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_matches(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),FfiConverterString.lower(`indexName`),FfiConverterString.lower(`docId`),FfiConverterString.lower(`query`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_rust_buffer(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_rust_buffer(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_rust_buffer(future) },
+ // lift function
+ { FfiConverterSequenceTypeMatchRange.lift(it) },
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsIndexVersion`() : kotlin.UInt {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_index_version(
+ thisPtr,
+
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_u32(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_u32(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_u32(future) },
+ // lift function
+ { FfiConverterUInt.lift(it) },
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
+ @Throws(UniffiException::class)
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun `ftsSearch`(`universalId`: kotlin.String, `indexName`: kotlin.String, `query`: kotlin.String) : List {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ UniffiLib.INSTANCE.uniffi_affine_mobile_native_fn_method_docstoragepool_fts_search(
+ thisPtr,
+ FfiConverterString.lower(`universalId`),FfiConverterString.lower(`indexName`),FfiConverterString.lower(`query`),
+ )
+ },
+ { future, callback, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_poll_rust_buffer(future, callback, continuation) },
+ { future, continuation -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_complete_rust_buffer(future, continuation) },
+ { future -> UniffiLib.INSTANCE.ffi_affine_mobile_native_rust_future_free_rust_buffer(future) },
+ // lift function
+ { FfiConverterSequenceTypeSearchHit.lift(it) },
+ // Error FFI converter
+ UniffiException.ErrorHandler,
+ )
+ }
+
+
@Throws(UniffiException::class)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
override suspend fun `getBlob`(`universalId`: kotlin.String, `key`: kotlin.String) : Blob? {
@@ -2696,6 +2946,74 @@ public object FfiConverterTypeListedBlob: FfiConverterRustBuffer {
+data class MatchRange (
+ var `start`: kotlin.UInt,
+ var `end`: kotlin.UInt
+) {
+
+ companion object
+}
+
+/**
+ * @suppress
+ */
+public object FfiConverterTypeMatchRange: FfiConverterRustBuffer {
+ override fun read(buf: ByteBuffer): MatchRange {
+ return MatchRange(
+ FfiConverterUInt.read(buf),
+ FfiConverterUInt.read(buf),
+ )
+ }
+
+ override fun allocationSize(value: MatchRange) = (
+ FfiConverterUInt.allocationSize(value.`start`) +
+ FfiConverterUInt.allocationSize(value.`end`)
+ )
+
+ override fun write(value: MatchRange, buf: ByteBuffer) {
+ FfiConverterUInt.write(value.`start`, buf)
+ FfiConverterUInt.write(value.`end`, buf)
+ }
+}
+
+
+
+data class SearchHit (
+ var `id`: kotlin.String,
+ var `score`: kotlin.Double,
+ var `terms`: List
+) {
+
+ companion object
+}
+
+/**
+ * @suppress
+ */
+public object FfiConverterTypeSearchHit: FfiConverterRustBuffer {
+ override fun read(buf: ByteBuffer): SearchHit {
+ return SearchHit(
+ FfiConverterString.read(buf),
+ FfiConverterDouble.read(buf),
+ FfiConverterSequenceString.read(buf),
+ )
+ }
+
+ override fun allocationSize(value: SearchHit) = (
+ FfiConverterString.allocationSize(value.`id`) +
+ FfiConverterDouble.allocationSize(value.`score`) +
+ FfiConverterSequenceString.allocationSize(value.`terms`)
+ )
+
+ override fun write(value: SearchHit, buf: ByteBuffer) {
+ FfiConverterString.write(value.`id`, buf)
+ FfiConverterDouble.write(value.`score`, buf)
+ FfiConverterSequenceString.write(value.`terms`, buf)
+ }
+}
+
+
+
data class SetBlob (
var `key`: kotlin.String,
var `data`: kotlin.String,
@@ -3188,6 +3506,62 @@ public object FfiConverterSequenceTypeListedBlob: FfiConverterRustBuffer> {
+ override fun read(buf: ByteBuffer): List {
+ val len = buf.getInt()
+ return List(len) {
+ FfiConverterTypeMatchRange.read(buf)
+ }
+ }
+
+ override fun allocationSize(value: List): ULong {
+ val sizeForLength = 4UL
+ val sizeForItems = value.map { FfiConverterTypeMatchRange.allocationSize(it) }.sum()
+ return sizeForLength + sizeForItems
+ }
+
+ override fun write(value: List, buf: ByteBuffer) {
+ buf.putInt(value.size)
+ value.iterator().forEach {
+ FfiConverterTypeMatchRange.write(it, buf)
+ }
+ }
+}
+
+
+
+
+/**
+ * @suppress
+ */
+public object FfiConverterSequenceTypeSearchHit: FfiConverterRustBuffer> {
+ override fun read(buf: ByteBuffer): List {
+ val len = buf.getInt()
+ return List(len) {
+ FfiConverterTypeSearchHit.read(buf)
+ }
+ }
+
+ override fun allocationSize(value: List): ULong {
+ val sizeForLength = 4UL
+ val sizeForItems = value.map { FfiConverterTypeSearchHit.allocationSize(it) }.sum()
+ return sizeForLength + sizeForItems
+ }
+
+ override fun write(value: List, buf: ByteBuffer) {
+ buf.putInt(value.size)
+ value.iterator().forEach {
+ FfiConverterTypeSearchHit.write(it, buf)
+ }
+ }
+}
+
+
+
+
diff --git a/packages/frontend/apps/android/src/plugins/nbstore/definitions.ts b/packages/frontend/apps/android/src/plugins/nbstore/definitions.ts
index 6f1faecce1..0c92f18c7b 100644
--- a/packages/frontend/apps/android/src/plugins/nbstore/definitions.ts
+++ b/packages/frontend/apps/android/src/plugins/nbstore/definitions.ts
@@ -171,7 +171,9 @@ export interface NbStorePlugin {
id: string;
indexName: string;
query: string;
- }) => Promise<{ id: string; score: number; terms: Array }[]>;
+ }) => Promise<{
+ results: { id: string; score: number; terms: Array }[];
+ }>;
ftsGetDocument: (options: {
id: string;
indexName: string;
@@ -182,7 +184,7 @@ export interface NbStorePlugin {
indexName: string;
docId: string;
query: string;
- }) => Promise>;
+ }) => Promise<{ matches: Array<{ start: number; end: number }> }>;
ftsFlushIndex: (options: { id: string }) => Promise;
- ftsIndexVersion: () => Promise;
+ ftsIndexVersion: () => Promise<{ indexVersion: number }>;
}
diff --git a/packages/frontend/apps/android/src/plugins/nbstore/index.ts b/packages/frontend/apps/android/src/plugins/nbstore/index.ts
index e19a2b1059..ee0d298a6a 100644
--- a/packages/frontend/apps/android/src/plugins/nbstore/index.ts
+++ b/packages/frontend/apps/android/src/plugins/nbstore/index.ts
@@ -370,11 +370,12 @@ export const NbStoreNativeDBApis: NativeDBApis = {
indexName: string,
query: string
): Promise<{ id: string; score: number; terms: Array }[]> {
- return await NbStore.ftsSearch({
+ const { results } = await NbStore.ftsSearch({
id,
indexName,
query,
});
+ return results ?? [];
},
ftsGetDocument: async function (
id: string,
@@ -394,12 +395,13 @@ export const NbStoreNativeDBApis: NativeDBApis = {
docId: string,
query: string
): Promise<{ start: number; end: number }[]> {
- return await NbStore.ftsGetMatches({
+ const { matches } = await NbStore.ftsGetMatches({
id,
indexName,
docId,
query,
});
+ return matches ?? [];
},
ftsFlushIndex: async function (id: string): Promise {
await NbStore.ftsFlushIndex({
@@ -407,6 +409,6 @@ export const NbStoreNativeDBApis: NativeDBApis = {
});
},
ftsIndexVersion: function (): Promise {
- return NbStore.ftsIndexVersion();
+ return NbStore.ftsIndexVersion().then(res => res.indexVersion);
},
};
diff --git a/packages/frontend/apps/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved b/packages/frontend/apps/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved
index a08907f526..e14ed8d571 100644
--- a/packages/frontend/apps/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/packages/frontend/apps/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Lakr233/ListViewKit",
"state" : {
- "revision" : "a4372d7f90c846d834c1f1575d1af0050d70fa0f",
- "version" : "1.1.6"
+ "revision" : "5dea05a52a6c2c7bb013a5925c517d6e32940605",
+ "version" : "1.1.8"
}
},
{
@@ -41,8 +41,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Lakr233/MarkdownView",
"state" : {
- "revision" : "c052f57768436212c91e4369d76181c38eaa3ba3",
- "version" : "3.4.2"
+ "revision" : "20fa808889944921e8da3a1c8317e8a557db373e",
+ "version" : "3.4.7"
+ }
+ },
+ {
+ "identity" : "msdisplaylink",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/Lakr233/MSDisplayLink",
+ "state" : {
+ "revision" : "ebf5823cb5fc1326639d9a05bc06d16bbe82989f",
+ "version" : "2.0.8"
}
},
{
@@ -77,8 +86,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Lakr233/SpringInterpolation",
"state" : {
- "revision" : "f9ae95ece5d6b7cdceafd4381f1d5f0f9494e5d2",
- "version" : "1.3.1"
+ "revision" : "cdb556516daa9b43c16aae9436dd39e19ff930fd",
+ "version" : "1.4.0"
}
},
{
@@ -95,8 +104,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
- "revision" : "8c0c0a8b49e080e54e5e328cc552821ff07cd341",
- "version" : "1.2.1"
+ "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
+ "version" : "1.3.0"
}
},
{
diff --git a/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift b/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift
index 96a81ca51f..141d80a542 100644
--- a/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift
+++ b/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift
@@ -36,6 +36,14 @@ public class NbStorePlugin: CAPPlugin, CAPBridgedPlugin {
CAPPluginMethod(name: "clearClocks", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "getBlobUploadedAt", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "setBlobUploadedAt", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "crawlDocData", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsAddDocument", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsDeleteDocument", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsSearch", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsGetDocument", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsGetMatches", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsFlushIndex", returnType: CAPPluginReturnPromise),
+ CAPPluginMethod(name: "ftsIndexVersion", returnType: CAPPluginReturnPromise),
]
@objc func connect(_ call: CAPPluginCall) {
@@ -546,4 +554,169 @@ public class NbStorePlugin: CAPPlugin, CAPBridgedPlugin {
}
}
}
+
+ @objc func crawlDocData(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let docId = try call.getStringEnsure("docId")
+ let result = try await docStoragePool.crawlDocData(universalId: id, docId: docId)
+ let blocks = result.blocks.map {
+ [
+ "blockId": $0.blockId,
+ "flavour": $0.flavour,
+ "content": $0.content as Any,
+ "blob": $0.blob as Any,
+ "refDocId": $0.refDocId as Any,
+ "refInfo": $0.refInfo as Any,
+ "parentFlavour": $0.parentFlavour as Any,
+ "parentBlockId": $0.parentBlockId as Any,
+ "additional": $0.additional as Any,
+ ]
+ }
+ call.resolve([
+ "title": result.title,
+ "summary": result.summary,
+ "blocks": blocks,
+ ])
+ } catch {
+ call.reject("Failed to crawl doc data, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsAddDocument(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let indexName = try call.getStringEnsure("indexName")
+ let docId = try call.getStringEnsure("docId")
+ let text = try call.getStringEnsure("text")
+ guard let index = call.getBool("index") else {
+ call.reject("index is required", nil, nil)
+ return
+ }
+ try await docStoragePool.ftsAddDocument(
+ universalId: id,
+ indexName: indexName,
+ docId: docId,
+ text: text,
+ index: index
+ )
+ call.resolve()
+ } catch {
+ call.reject("Failed to add document to fts, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsDeleteDocument(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let indexName = try call.getStringEnsure("indexName")
+ let docId = try call.getStringEnsure("docId")
+ try await docStoragePool.ftsDeleteDocument(
+ universalId: id,
+ indexName: indexName,
+ docId: docId
+ )
+ call.resolve()
+ } catch {
+ call.reject("Failed to delete document from fts, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsSearch(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let indexName = try call.getStringEnsure("indexName")
+ let query = try call.getStringEnsure("query")
+ let results = try await docStoragePool.ftsSearch(
+ universalId: id,
+ indexName: indexName,
+ query: query
+ )
+ let mapped = results.map {
+ [
+ "id": $0.id,
+ "score": $0.score,
+ "terms": $0.terms,
+ ] as [String: Any]
+ }
+ call.resolve(["results": mapped])
+ } catch {
+ call.reject("Failed to search fts, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsGetDocument(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let indexName = try call.getStringEnsure("indexName")
+ let docId = try call.getStringEnsure("docId")
+ let text = try await docStoragePool.ftsGetDocument(
+ universalId: id,
+ indexName: indexName,
+ docId: docId
+ )
+ call.resolve(["text": text as Any])
+ } catch {
+ call.reject("Failed to get fts document, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsGetMatches(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ let indexName = try call.getStringEnsure("indexName")
+ let docId = try call.getStringEnsure("docId")
+ let query = try call.getStringEnsure("query")
+ let matches = try await docStoragePool.ftsGetMatches(
+ universalId: id,
+ indexName: indexName,
+ docId: docId,
+ query: query
+ )
+ let mapped = matches.map {
+ [
+ "start": $0.start,
+ "end": $0.end,
+ ]
+ }
+ call.resolve(["matches": mapped])
+ } catch {
+ call.reject("Failed to get fts matches, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsFlushIndex(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let id = try call.getStringEnsure("id")
+ try await docStoragePool.ftsFlushIndex(universalId: id)
+ call.resolve()
+ } catch {
+ call.reject("Failed to flush fts index, \(error)", nil, error)
+ }
+ }
+ }
+
+ @objc func ftsIndexVersion(_ call: CAPPluginCall) {
+ Task {
+ do {
+ let version = try await docStoragePool.ftsIndexVersion()
+ call.resolve(["indexVersion": version])
+ } catch {
+ call.reject("Failed to get fts index version, \(error)", nil, error)
+ }
+ }
+ }
}
diff --git a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift
index 9e015b0b59..590b1be0f6 100644
--- a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift
+++ b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift
@@ -429,6 +429,22 @@ fileprivate struct FfiConverterInt64: FfiConverterPrimitive {
}
}
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterDouble: FfiConverterPrimitive {
+ typealias FfiType = Double
+ typealias SwiftType = Double
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double {
+ return try lift(readDouble(&buf))
+ }
+
+ public static func write(_ value: Double, into buf: inout [UInt8]) {
+ writeDouble(&buf, lower(value))
+ }
+}
+
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@@ -506,12 +522,28 @@ public protocol DocStoragePoolProtocol: AnyObject, Sendable {
*/
func connect(universalId: String, path: String) async throws
+ func crawlDocData(universalId: String, docId: String) async throws -> CrawlResult
+
func deleteBlob(universalId: String, key: String, permanently: Bool) async throws
func deleteDoc(universalId: String, docId: String) async throws
func disconnect(universalId: String) async throws
+ func ftsAddDocument(universalId: String, indexName: String, docId: String, text: String, index: Bool) async throws
+
+ func ftsDeleteDocument(universalId: String, indexName: String, docId: String) async throws
+
+ func ftsFlushIndex(universalId: String) async throws
+
+ func ftsGetDocument(universalId: String, indexName: String, docId: String) async throws -> String?
+
+ func ftsGetMatches(universalId: String, indexName: String, docId: String, query: String) async throws -> [MatchRange]
+
+ func ftsIndexVersion() async throws -> UInt32
+
+ func ftsSearch(universalId: String, indexName: String, query: String) async throws -> [SearchHit]
+
func getBlob(universalId: String, key: String) async throws -> Blob?
func getBlobUploadedAt(universalId: String, peer: String, blobId: String) async throws -> Int64?
@@ -648,6 +680,23 @@ open func connect(universalId: String, path: String)async throws {
)
}
+open func crawlDocData(universalId: String, docId: String)async throws -> CrawlResult {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_crawl_doc_data(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(docId)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer,
+ liftFunc: FfiConverterTypeCrawlResult_lift,
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
open func deleteBlob(universalId: String, key: String, permanently: Bool)async throws {
return
try await uniffiRustCallAsync(
@@ -699,6 +748,125 @@ open func disconnect(universalId: String)async throws {
)
}
+open func ftsAddDocument(universalId: String, indexName: String, docId: String, text: String, index: Bool)async throws {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_add_document(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(indexName),FfiConverterString.lower(docId),FfiConverterString.lower(text),FfiConverterBool.lower(index)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_void,
+ liftFunc: { $0 },
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsDeleteDocument(universalId: String, indexName: String, docId: String)async throws {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_delete_document(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(indexName),FfiConverterString.lower(docId)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_void,
+ liftFunc: { $0 },
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsFlushIndex(universalId: String)async throws {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_flush_index(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_void,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_void,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_void,
+ liftFunc: { $0 },
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsGetDocument(universalId: String, indexName: String, docId: String)async throws -> String? {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_document(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(indexName),FfiConverterString.lower(docId)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer,
+ liftFunc: FfiConverterOptionString.lift,
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsGetMatches(universalId: String, indexName: String, docId: String, query: String)async throws -> [MatchRange] {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_matches(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(indexName),FfiConverterString.lower(docId),FfiConverterString.lower(query)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer,
+ liftFunc: FfiConverterSequenceTypeMatchRange.lift,
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsIndexVersion()async throws -> UInt32 {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_index_version(
+ self.uniffiClonePointer()
+
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_u32,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_u32,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_u32,
+ liftFunc: FfiConverterUInt32.lift,
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
+open func ftsSearch(universalId: String, indexName: String, query: String)async throws -> [SearchHit] {
+ return
+ try await uniffiRustCallAsync(
+ rustFutureFunc: {
+ uniffi_affine_mobile_native_fn_method_docstoragepool_fts_search(
+ self.uniffiClonePointer(),
+ FfiConverterString.lower(universalId),FfiConverterString.lower(indexName),FfiConverterString.lower(query)
+ )
+ },
+ pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer,
+ completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer,
+ freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer,
+ liftFunc: FfiConverterSequenceTypeSearchHit.lift,
+ errorHandler: FfiConverterTypeUniffiError_lift
+ )
+}
+
open func getBlob(universalId: String, key: String)async throws -> Blob? {
return
try await uniffiRustCallAsync(
@@ -1240,6 +1408,210 @@ public func FfiConverterTypeBlob_lower(_ value: Blob) -> RustBuffer {
}
+public struct BlockInfo {
+ public var blockId: String
+ public var flavour: String
+ public var content: [String]?
+ public var blob: [String]?
+ public var refDocId: [String]?
+ public var refInfo: [String]?
+ public var parentFlavour: String?
+ public var parentBlockId: String?
+ public var additional: String?
+
+ // Default memberwise initializers are never public by default, so we
+ // declare one manually.
+ public init(blockId: String, flavour: String, content: [String]?, blob: [String]?, refDocId: [String]?, refInfo: [String]?, parentFlavour: String?, parentBlockId: String?, additional: String?) {
+ self.blockId = blockId
+ self.flavour = flavour
+ self.content = content
+ self.blob = blob
+ self.refDocId = refDocId
+ self.refInfo = refInfo
+ self.parentFlavour = parentFlavour
+ self.parentBlockId = parentBlockId
+ self.additional = additional
+ }
+}
+
+#if compiler(>=6)
+extension BlockInfo: Sendable {}
+#endif
+
+
+extension BlockInfo: Equatable, Hashable {
+ public static func ==(lhs: BlockInfo, rhs: BlockInfo) -> Bool {
+ if lhs.blockId != rhs.blockId {
+ return false
+ }
+ if lhs.flavour != rhs.flavour {
+ return false
+ }
+ if lhs.content != rhs.content {
+ return false
+ }
+ if lhs.blob != rhs.blob {
+ return false
+ }
+ if lhs.refDocId != rhs.refDocId {
+ return false
+ }
+ if lhs.refInfo != rhs.refInfo {
+ return false
+ }
+ if lhs.parentFlavour != rhs.parentFlavour {
+ return false
+ }
+ if lhs.parentBlockId != rhs.parentBlockId {
+ return false
+ }
+ if lhs.additional != rhs.additional {
+ return false
+ }
+ return true
+ }
+
+ public func hash(into hasher: inout Hasher) {
+ hasher.combine(blockId)
+ hasher.combine(flavour)
+ hasher.combine(content)
+ hasher.combine(blob)
+ hasher.combine(refDocId)
+ hasher.combine(refInfo)
+ hasher.combine(parentFlavour)
+ hasher.combine(parentBlockId)
+ hasher.combine(additional)
+ }
+}
+
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public struct FfiConverterTypeBlockInfo: FfiConverterRustBuffer {
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> BlockInfo {
+ return
+ try BlockInfo(
+ blockId: FfiConverterString.read(from: &buf),
+ flavour: FfiConverterString.read(from: &buf),
+ content: FfiConverterOptionSequenceString.read(from: &buf),
+ blob: FfiConverterOptionSequenceString.read(from: &buf),
+ refDocId: FfiConverterOptionSequenceString.read(from: &buf),
+ refInfo: FfiConverterOptionSequenceString.read(from: &buf),
+ parentFlavour: FfiConverterOptionString.read(from: &buf),
+ parentBlockId: FfiConverterOptionString.read(from: &buf),
+ additional: FfiConverterOptionString.read(from: &buf)
+ )
+ }
+
+ public static func write(_ value: BlockInfo, into buf: inout [UInt8]) {
+ FfiConverterString.write(value.blockId, into: &buf)
+ FfiConverterString.write(value.flavour, into: &buf)
+ FfiConverterOptionSequenceString.write(value.content, into: &buf)
+ FfiConverterOptionSequenceString.write(value.blob, into: &buf)
+ FfiConverterOptionSequenceString.write(value.refDocId, into: &buf)
+ FfiConverterOptionSequenceString.write(value.refInfo, into: &buf)
+ FfiConverterOptionString.write(value.parentFlavour, into: &buf)
+ FfiConverterOptionString.write(value.parentBlockId, into: &buf)
+ FfiConverterOptionString.write(value.additional, into: &buf)
+ }
+}
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeBlockInfo_lift(_ buf: RustBuffer) throws -> BlockInfo {
+ return try FfiConverterTypeBlockInfo.lift(buf)
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeBlockInfo_lower(_ value: BlockInfo) -> RustBuffer {
+ return FfiConverterTypeBlockInfo.lower(value)
+}
+
+
+public struct CrawlResult {
+ public var blocks: [BlockInfo]
+ public var title: String
+ public var summary: String
+
+ // Default memberwise initializers are never public by default, so we
+ // declare one manually.
+ public init(blocks: [BlockInfo], title: String, summary: String) {
+ self.blocks = blocks
+ self.title = title
+ self.summary = summary
+ }
+}
+
+#if compiler(>=6)
+extension CrawlResult: Sendable {}
+#endif
+
+
+extension CrawlResult: Equatable, Hashable {
+ public static func ==(lhs: CrawlResult, rhs: CrawlResult) -> Bool {
+ if lhs.blocks != rhs.blocks {
+ return false
+ }
+ if lhs.title != rhs.title {
+ return false
+ }
+ if lhs.summary != rhs.summary {
+ return false
+ }
+ return true
+ }
+
+ public func hash(into hasher: inout Hasher) {
+ hasher.combine(blocks)
+ hasher.combine(title)
+ hasher.combine(summary)
+ }
+}
+
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public struct FfiConverterTypeCrawlResult: FfiConverterRustBuffer {
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> CrawlResult {
+ return
+ try CrawlResult(
+ blocks: FfiConverterSequenceTypeBlockInfo.read(from: &buf),
+ title: FfiConverterString.read(from: &buf),
+ summary: FfiConverterString.read(from: &buf)
+ )
+ }
+
+ public static func write(_ value: CrawlResult, into buf: inout [UInt8]) {
+ FfiConverterSequenceTypeBlockInfo.write(value.blocks, into: &buf)
+ FfiConverterString.write(value.title, into: &buf)
+ FfiConverterString.write(value.summary, into: &buf)
+ }
+}
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeCrawlResult_lift(_ buf: RustBuffer) throws -> CrawlResult {
+ return try FfiConverterTypeCrawlResult.lift(buf)
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeCrawlResult_lower(_ value: CrawlResult) -> RustBuffer {
+ return FfiConverterTypeCrawlResult.lower(value)
+}
+
+
public struct DocClock {
public var docId: String
public var timestamp: Int64
@@ -1552,6 +1924,154 @@ public func FfiConverterTypeListedBlob_lower(_ value: ListedBlob) -> RustBuffer
}
+public struct MatchRange {
+ public var start: UInt32
+ public var end: UInt32
+
+ // Default memberwise initializers are never public by default, so we
+ // declare one manually.
+ public init(start: UInt32, end: UInt32) {
+ self.start = start
+ self.end = end
+ }
+}
+
+#if compiler(>=6)
+extension MatchRange: Sendable {}
+#endif
+
+
+extension MatchRange: Equatable, Hashable {
+ public static func ==(lhs: MatchRange, rhs: MatchRange) -> Bool {
+ if lhs.start != rhs.start {
+ return false
+ }
+ if lhs.end != rhs.end {
+ return false
+ }
+ return true
+ }
+
+ public func hash(into hasher: inout Hasher) {
+ hasher.combine(start)
+ hasher.combine(end)
+ }
+}
+
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public struct FfiConverterTypeMatchRange: FfiConverterRustBuffer {
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MatchRange {
+ return
+ try MatchRange(
+ start: FfiConverterUInt32.read(from: &buf),
+ end: FfiConverterUInt32.read(from: &buf)
+ )
+ }
+
+ public static func write(_ value: MatchRange, into buf: inout [UInt8]) {
+ FfiConverterUInt32.write(value.start, into: &buf)
+ FfiConverterUInt32.write(value.end, into: &buf)
+ }
+}
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeMatchRange_lift(_ buf: RustBuffer) throws -> MatchRange {
+ return try FfiConverterTypeMatchRange.lift(buf)
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeMatchRange_lower(_ value: MatchRange) -> RustBuffer {
+ return FfiConverterTypeMatchRange.lower(value)
+}
+
+
+public struct SearchHit {
+ public var id: String
+ public var score: Double
+ public var terms: [String]
+
+ // Default memberwise initializers are never public by default, so we
+ // declare one manually.
+ public init(id: String, score: Double, terms: [String]) {
+ self.id = id
+ self.score = score
+ self.terms = terms
+ }
+}
+
+#if compiler(>=6)
+extension SearchHit: Sendable {}
+#endif
+
+
+extension SearchHit: Equatable, Hashable {
+ public static func ==(lhs: SearchHit, rhs: SearchHit) -> Bool {
+ if lhs.id != rhs.id {
+ return false
+ }
+ if lhs.score != rhs.score {
+ return false
+ }
+ if lhs.terms != rhs.terms {
+ return false
+ }
+ return true
+ }
+
+ public func hash(into hasher: inout Hasher) {
+ hasher.combine(id)
+ hasher.combine(score)
+ hasher.combine(terms)
+ }
+}
+
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public struct FfiConverterTypeSearchHit: FfiConverterRustBuffer {
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SearchHit {
+ return
+ try SearchHit(
+ id: FfiConverterString.read(from: &buf),
+ score: FfiConverterDouble.read(from: &buf),
+ terms: FfiConverterSequenceString.read(from: &buf)
+ )
+ }
+
+ public static func write(_ value: SearchHit, into buf: inout [UInt8]) {
+ FfiConverterString.write(value.id, into: &buf)
+ FfiConverterDouble.write(value.score, into: &buf)
+ FfiConverterSequenceString.write(value.terms, into: &buf)
+ }
+}
+
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeSearchHit_lift(_ buf: RustBuffer) throws -> SearchHit {
+ return try FfiConverterTypeSearchHit.lift(buf)
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+public func FfiConverterTypeSearchHit_lower(_ value: SearchHit) -> RustBuffer {
+ return FfiConverterTypeSearchHit.lower(value)
+}
+
+
public struct SetBlob {
public var key: String
public var data: String
@@ -1745,6 +2265,30 @@ fileprivate struct FfiConverterOptionInt64: FfiConverterRustBuffer {
}
}
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer {
+ typealias SwiftType = String?
+
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
+ guard let value = value else {
+ writeInt(&buf, Int8(0))
+ return
+ }
+ writeInt(&buf, Int8(1))
+ FfiConverterString.write(value, into: &buf)
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
+ switch try readInt(&buf) as Int8 {
+ case 0: return nil
+ case 1: return try FfiConverterString.read(from: &buf)
+ default: throw UniffiInternalError.unexpectedOptionalTag
+ }
+ }
+}
+
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@@ -1817,6 +2361,30 @@ fileprivate struct FfiConverterOptionTypeDocRecord: FfiConverterRustBuffer {
}
}
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterOptionSequenceString: FfiConverterRustBuffer {
+ typealias SwiftType = [String]?
+
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
+ guard let value = value else {
+ writeInt(&buf, Int8(0))
+ return
+ }
+ writeInt(&buf, Int8(1))
+ FfiConverterSequenceString.write(value, into: &buf)
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
+ switch try readInt(&buf) as Int8 {
+ case 0: return nil
+ case 1: return try FfiConverterSequenceString.read(from: &buf)
+ default: throw UniffiInternalError.unexpectedOptionalTag
+ }
+ }
+}
+
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@@ -1842,6 +2410,56 @@ fileprivate struct FfiConverterSequenceInt64: FfiConverterRustBuffer {
}
}
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer {
+ typealias SwiftType = [String]
+
+ public static func write(_ value: [String], into buf: inout [UInt8]) {
+ let len = Int32(value.count)
+ writeInt(&buf, len)
+ for item in value {
+ FfiConverterString.write(item, into: &buf)
+ }
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] {
+ let len: Int32 = try readInt(&buf)
+ var seq = [String]()
+ seq.reserveCapacity(Int(len))
+ for _ in 0 ..< len {
+ seq.append(try FfiConverterString.read(from: &buf))
+ }
+ return seq
+ }
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterSequenceTypeBlockInfo: FfiConverterRustBuffer {
+ typealias SwiftType = [BlockInfo]
+
+ public static func write(_ value: [BlockInfo], into buf: inout [UInt8]) {
+ let len = Int32(value.count)
+ writeInt(&buf, len)
+ for item in value {
+ FfiConverterTypeBlockInfo.write(item, into: &buf)
+ }
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [BlockInfo] {
+ let len: Int32 = try readInt(&buf)
+ var seq = [BlockInfo]()
+ seq.reserveCapacity(Int(len))
+ for _ in 0 ..< len {
+ seq.append(try FfiConverterTypeBlockInfo.read(from: &buf))
+ }
+ return seq
+ }
+}
+
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@@ -1916,6 +2534,56 @@ fileprivate struct FfiConverterSequenceTypeListedBlob: FfiConverterRustBuffer {
return seq
}
}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterSequenceTypeMatchRange: FfiConverterRustBuffer {
+ typealias SwiftType = [MatchRange]
+
+ public static func write(_ value: [MatchRange], into buf: inout [UInt8]) {
+ let len = Int32(value.count)
+ writeInt(&buf, len)
+ for item in value {
+ FfiConverterTypeMatchRange.write(item, into: &buf)
+ }
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [MatchRange] {
+ let len: Int32 = try readInt(&buf)
+ var seq = [MatchRange]()
+ seq.reserveCapacity(Int(len))
+ for _ in 0 ..< len {
+ seq.append(try FfiConverterTypeMatchRange.read(from: &buf))
+ }
+ return seq
+ }
+}
+
+#if swift(>=5.8)
+@_documentation(visibility: private)
+#endif
+fileprivate struct FfiConverterSequenceTypeSearchHit: FfiConverterRustBuffer {
+ typealias SwiftType = [SearchHit]
+
+ public static func write(_ value: [SearchHit], into buf: inout [UInt8]) {
+ let len = Int32(value.count)
+ writeInt(&buf, len)
+ for item in value {
+ FfiConverterTypeSearchHit.write(item, into: &buf)
+ }
+ }
+
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [SearchHit] {
+ let len: Int32 = try readInt(&buf)
+ var seq = [SearchHit]()
+ seq.reserveCapacity(Int(len))
+ for _ in 0 ..< len {
+ seq.append(try FfiConverterTypeSearchHit.read(from: &buf))
+ }
+ return seq
+ }
+}
private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1
@@ -2004,6 +2672,9 @@ private let initializationResult: InitializationResult = {
if (uniffi_affine_mobile_native_checksum_method_docstoragepool_connect() != 19047) {
return InitializationResult.apiChecksumMismatch
}
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_crawl_doc_data() != 36347) {
+ return InitializationResult.apiChecksumMismatch
+ }
if (uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_blob() != 53695) {
return InitializationResult.apiChecksumMismatch
}
@@ -2013,6 +2684,27 @@ private let initializationResult: InitializationResult = {
if (uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect() != 20410) {
return InitializationResult.apiChecksumMismatch
}
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_add_document() != 37651) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_delete_document() != 47292) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_flush_index() != 9921) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_document() != 45953) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_matches() != 35972) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_index_version() != 44498) {
+ return InitializationResult.apiChecksumMismatch
+ }
+ if (uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_search() != 28341) {
+ return InitializationResult.apiChecksumMismatch
+ }
if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob() != 56927) {
return InitializationResult.apiChecksumMismatch
}
diff --git a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h
index bff076d8ad..04f5dc26d2 100644
--- a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h
+++ b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h
@@ -271,6 +271,11 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_clear_clocks(void*
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_connect(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer path
);
#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CRAWL_DOC_DATA
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_CRAWL_DOC_DATA
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_crawl_doc_data(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer doc_id
+);
+#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_DELETE_BLOB
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_DELETE_BLOB
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_delete_blob(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer key, int8_t permanently
@@ -286,6 +291,41 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_delete_doc(void*_N
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect(void*_Nonnull ptr, RustBuffer universal_id
);
#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_ADD_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_ADD_DOCUMENT
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_add_document(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer index_name, RustBuffer doc_id, RustBuffer text, int8_t index
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_DELETE_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_DELETE_DOCUMENT
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_delete_document(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer index_name, RustBuffer doc_id
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_FLUSH_INDEX
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_FLUSH_INDEX
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_flush_index(void*_Nonnull ptr, RustBuffer universal_id
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_GET_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_GET_DOCUMENT
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_document(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer index_name, RustBuffer doc_id
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_GET_MATCHES
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_GET_MATCHES
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_get_matches(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer index_name, RustBuffer doc_id, RustBuffer query
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_INDEX_VERSION
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_INDEX_VERSION
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_index_version(void*_Nonnull ptr
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_SEARCH
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_FTS_SEARCH
+uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_fts_search(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer index_name, RustBuffer query
+);
+#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_GET_BLOB
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_GET_BLOB
uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer key
@@ -714,6 +754,12 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_clear_clocks
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CONNECT
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_connect(void
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CRAWL_DOC_DATA
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CRAWL_DOC_DATA
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_crawl_doc_data(void
+
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_DELETE_BLOB
@@ -732,6 +778,48 @@ uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc(v
#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_DISCONNECT
uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect(void
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_ADD_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_ADD_DOCUMENT
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_add_document(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_DELETE_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_DELETE_DOCUMENT
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_delete_document(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_FLUSH_INDEX
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_FLUSH_INDEX
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_flush_index(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_GET_DOCUMENT
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_GET_DOCUMENT
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_document(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_GET_MATCHES
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_GET_MATCHES
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_get_matches(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_INDEX_VERSION
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_INDEX_VERSION
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_index_version(void
+
+);
+#endif
+#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_SEARCH
+#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_FTS_SEARCH
+uint16_t uniffi_affine_mobile_native_checksum_method_docstoragepool_fts_search(void
+
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_GET_BLOB
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/AbortBlobUploadMutation.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/AbortBlobUploadMutation.graphql.swift
new file mode 100644
index 0000000000..54e172d4be
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/AbortBlobUploadMutation.graphql.swift
@@ -0,0 +1,48 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+@_exported import ApolloAPI
+
+public class AbortBlobUploadMutation: GraphQLMutation {
+ public static let operationName: String = "abortBlobUpload"
+ public static let operationDocument: ApolloAPI.OperationDocument = .init(
+ definition: .init(
+ #"mutation abortBlobUpload($workspaceId: String!, $key: String!, $uploadId: String!) { abortBlobUpload(workspaceId: $workspaceId, key: $key, uploadId: $uploadId) }"#
+ ))
+
+ public var workspaceId: String
+ public var key: String
+ public var uploadId: String
+
+ public init(
+ workspaceId: String,
+ key: String,
+ uploadId: String
+ ) {
+ self.workspaceId = workspaceId
+ self.key = key
+ self.uploadId = uploadId
+ }
+
+ public var __variables: Variables? { [
+ "workspaceId": workspaceId,
+ "key": key,
+ "uploadId": uploadId
+ ] }
+
+ public struct Data: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.Mutation }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("abortBlobUpload", Bool.self, arguments: [
+ "workspaceId": .variable("workspaceId"),
+ "key": .variable("key"),
+ "uploadId": .variable("uploadId")
+ ]),
+ ] }
+
+ public var abortBlobUpload: Bool { __data["abortBlobUpload"] }
+ }
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CompleteBlobUploadMutation.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CompleteBlobUploadMutation.graphql.swift
new file mode 100644
index 0000000000..498bd8a87d
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CompleteBlobUploadMutation.graphql.swift
@@ -0,0 +1,53 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+@_exported import ApolloAPI
+
+public class CompleteBlobUploadMutation: GraphQLMutation {
+ public static let operationName: String = "completeBlobUpload"
+ public static let operationDocument: ApolloAPI.OperationDocument = .init(
+ definition: .init(
+ #"mutation completeBlobUpload($workspaceId: String!, $key: String!, $uploadId: String, $parts: [BlobUploadPartInput!]) { completeBlobUpload( workspaceId: $workspaceId key: $key uploadId: $uploadId parts: $parts ) }"#
+ ))
+
+ public var workspaceId: String
+ public var key: String
+ public var uploadId: GraphQLNullable
+ public var parts: GraphQLNullable<[BlobUploadPartInput]>
+
+ public init(
+ workspaceId: String,
+ key: String,
+ uploadId: GraphQLNullable,
+ parts: GraphQLNullable<[BlobUploadPartInput]>
+ ) {
+ self.workspaceId = workspaceId
+ self.key = key
+ self.uploadId = uploadId
+ self.parts = parts
+ }
+
+ public var __variables: Variables? { [
+ "workspaceId": workspaceId,
+ "key": key,
+ "uploadId": uploadId,
+ "parts": parts
+ ] }
+
+ public struct Data: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.Mutation }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("completeBlobUpload", String.self, arguments: [
+ "workspaceId": .variable("workspaceId"),
+ "key": .variable("key"),
+ "uploadId": .variable("uploadId"),
+ "parts": .variable("parts")
+ ]),
+ ] }
+
+ public var completeBlobUpload: String { __data["completeBlobUpload"] }
+ }
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CreateBlobUploadMutation.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CreateBlobUploadMutation.graphql.swift
new file mode 100644
index 0000000000..cf2a515616
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/CreateBlobUploadMutation.graphql.swift
@@ -0,0 +1,103 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+@_exported import ApolloAPI
+
+public class CreateBlobUploadMutation: GraphQLMutation {
+ public static let operationName: String = "createBlobUpload"
+ public static let operationDocument: ApolloAPI.OperationDocument = .init(
+ definition: .init(
+ #"mutation createBlobUpload($workspaceId: String!, $key: String!, $size: Int!, $mime: String!) { createBlobUpload(workspaceId: $workspaceId, key: $key, size: $size, mime: $mime) { __typename method blobKey alreadyUploaded uploadUrl headers expiresAt uploadId partSize uploadedParts { __typename partNumber etag } } }"#
+ ))
+
+ public var workspaceId: String
+ public var key: String
+ public var size: Int
+ public var mime: String
+
+ public init(
+ workspaceId: String,
+ key: String,
+ size: Int,
+ mime: String
+ ) {
+ self.workspaceId = workspaceId
+ self.key = key
+ self.size = size
+ self.mime = mime
+ }
+
+ public var __variables: Variables? { [
+ "workspaceId": workspaceId,
+ "key": key,
+ "size": size,
+ "mime": mime
+ ] }
+
+ public struct Data: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.Mutation }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("createBlobUpload", CreateBlobUpload.self, arguments: [
+ "workspaceId": .variable("workspaceId"),
+ "key": .variable("key"),
+ "size": .variable("size"),
+ "mime": .variable("mime")
+ ]),
+ ] }
+
+ public var createBlobUpload: CreateBlobUpload { __data["createBlobUpload"] }
+
+ /// CreateBlobUpload
+ ///
+ /// Parent Type: `BlobUploadInit`
+ public struct CreateBlobUpload: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.BlobUploadInit }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("__typename", String.self),
+ .field("method", GraphQLEnum.self),
+ .field("blobKey", String.self),
+ .field("alreadyUploaded", Bool?.self),
+ .field("uploadUrl", String?.self),
+ .field("headers", AffineGraphQL.JSONObject?.self),
+ .field("expiresAt", AffineGraphQL.DateTime?.self),
+ .field("uploadId", String?.self),
+ .field("partSize", Int?.self),
+ .field("uploadedParts", [UploadedPart]?.self),
+ ] }
+
+ public var method: GraphQLEnum { __data["method"] }
+ public var blobKey: String { __data["blobKey"] }
+ public var alreadyUploaded: Bool? { __data["alreadyUploaded"] }
+ public var uploadUrl: String? { __data["uploadUrl"] }
+ public var headers: AffineGraphQL.JSONObject? { __data["headers"] }
+ public var expiresAt: AffineGraphQL.DateTime? { __data["expiresAt"] }
+ public var uploadId: String? { __data["uploadId"] }
+ public var partSize: Int? { __data["partSize"] }
+ public var uploadedParts: [UploadedPart]? { __data["uploadedParts"] }
+
+ /// CreateBlobUpload.UploadedPart
+ ///
+ /// Parent Type: `BlobUploadedPart`
+ public struct UploadedPart: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.BlobUploadedPart }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("__typename", String.self),
+ .field("partNumber", Int.self),
+ .field("etag", String.self),
+ ] }
+
+ public var partNumber: Int { __data["partNumber"] }
+ public var etag: String { __data["etag"] }
+ }
+ }
+ }
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/GetBlobUploadPartUrlMutation.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/GetBlobUploadPartUrlMutation.graphql.swift
new file mode 100644
index 0000000000..3c98007d2c
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Operations/Mutations/GetBlobUploadPartUrlMutation.graphql.swift
@@ -0,0 +1,73 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+@_exported import ApolloAPI
+
+public class GetBlobUploadPartUrlMutation: GraphQLMutation {
+ public static let operationName: String = "getBlobUploadPartUrl"
+ public static let operationDocument: ApolloAPI.OperationDocument = .init(
+ definition: .init(
+ #"mutation getBlobUploadPartUrl($workspaceId: String!, $key: String!, $uploadId: String!, $partNumber: Int!) { getBlobUploadPartUrl( workspaceId: $workspaceId key: $key uploadId: $uploadId partNumber: $partNumber ) { __typename uploadUrl headers expiresAt } }"#
+ ))
+
+ public var workspaceId: String
+ public var key: String
+ public var uploadId: String
+ public var partNumber: Int
+
+ public init(
+ workspaceId: String,
+ key: String,
+ uploadId: String,
+ partNumber: Int
+ ) {
+ self.workspaceId = workspaceId
+ self.key = key
+ self.uploadId = uploadId
+ self.partNumber = partNumber
+ }
+
+ public var __variables: Variables? { [
+ "workspaceId": workspaceId,
+ "key": key,
+ "uploadId": uploadId,
+ "partNumber": partNumber
+ ] }
+
+ public struct Data: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.Mutation }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("getBlobUploadPartUrl", GetBlobUploadPartUrl.self, arguments: [
+ "workspaceId": .variable("workspaceId"),
+ "key": .variable("key"),
+ "uploadId": .variable("uploadId"),
+ "partNumber": .variable("partNumber")
+ ]),
+ ] }
+
+ public var getBlobUploadPartUrl: GetBlobUploadPartUrl { __data["getBlobUploadPartUrl"] }
+
+ /// GetBlobUploadPartUrl
+ ///
+ /// Parent Type: `BlobUploadPart`
+ public struct GetBlobUploadPartUrl: AffineGraphQL.SelectionSet {
+ public let __data: DataDict
+ public init(_dataDict: DataDict) { __data = _dataDict }
+
+ public static var __parentType: any ApolloAPI.ParentType { AffineGraphQL.Objects.BlobUploadPart }
+ public static var __selections: [ApolloAPI.Selection] { [
+ .field("__typename", String.self),
+ .field("uploadUrl", String.self),
+ .field("headers", AffineGraphQL.JSONObject?.self),
+ .field("expiresAt", AffineGraphQL.DateTime?.self),
+ ] }
+
+ public var uploadUrl: String { __data["uploadUrl"] }
+ public var headers: AffineGraphQL.JSONObject? { __data["headers"] }
+ public var expiresAt: AffineGraphQL.DateTime? { __data["expiresAt"] }
+ }
+ }
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Enums/BlobUploadMethod.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Enums/BlobUploadMethod.graphql.swift
new file mode 100644
index 0000000000..2e5d37aefd
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Enums/BlobUploadMethod.graphql.swift
@@ -0,0 +1,11 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+import ApolloAPI
+
+/// Blob upload method
+public enum BlobUploadMethod: String, EnumType {
+ case graphql = "GRAPHQL"
+ case multipart = "MULTIPART"
+ case presigned = "PRESIGNED"
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/InputObjects/BlobUploadPartInput.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/InputObjects/BlobUploadPartInput.graphql.swift
new file mode 100644
index 0000000000..7717ebc388
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/InputObjects/BlobUploadPartInput.graphql.swift
@@ -0,0 +1,32 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+import ApolloAPI
+
+public struct BlobUploadPartInput: InputObject {
+ public private(set) var __data: InputDict
+
+ public init(_ data: InputDict) {
+ __data = data
+ }
+
+ public init(
+ etag: String,
+ partNumber: Int
+ ) {
+ __data = InputDict([
+ "etag": etag,
+ "partNumber": partNumber
+ ])
+ }
+
+ public var etag: String {
+ get { __data["etag"] }
+ set { __data["etag"] = newValue }
+ }
+
+ public var partNumber: Int {
+ get { __data["partNumber"] }
+ set { __data["partNumber"] = newValue }
+ }
+}
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadInit.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadInit.graphql.swift
new file mode 100644
index 0000000000..71f4415d80
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadInit.graphql.swift
@@ -0,0 +1,12 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+import ApolloAPI
+
+public extension Objects {
+ static let BlobUploadInit = ApolloAPI.Object(
+ typename: "BlobUploadInit",
+ implementedInterfaces: [],
+ keyFields: nil
+ )
+}
\ No newline at end of file
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadPart.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadPart.graphql.swift
new file mode 100644
index 0000000000..47a985330e
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadPart.graphql.swift
@@ -0,0 +1,12 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+import ApolloAPI
+
+public extension Objects {
+ static let BlobUploadPart = ApolloAPI.Object(
+ typename: "BlobUploadPart",
+ implementedInterfaces: [],
+ keyFields: nil
+ )
+}
\ No newline at end of file
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadedPart.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadedPart.graphql.swift
new file mode 100644
index 0000000000..71bed0fa9f
--- /dev/null
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/Objects/BlobUploadedPart.graphql.swift
@@ -0,0 +1,12 @@
+// @generated
+// This file was automatically generated and should not be edited.
+
+import ApolloAPI
+
+public extension Objects {
+ static let BlobUploadedPart = ApolloAPI.Object(
+ typename: "BlobUploadedPart",
+ implementedInterfaces: [],
+ keyFields: nil
+ )
+}
\ No newline at end of file
diff --git a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/SchemaMetadata.graphql.swift b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/SchemaMetadata.graphql.swift
index 9c005bc4a5..acda35c0d9 100644
--- a/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/SchemaMetadata.graphql.swift
+++ b/packages/frontend/apps/ios/App/Packages/AffineGraphQL/Sources/Schema/SchemaMetadata.graphql.swift
@@ -24,6 +24,9 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata {
case "AggregateBucketObjectType": return AffineGraphQL.Objects.AggregateBucketObjectType
case "AggregateResultObjectType": return AffineGraphQL.Objects.AggregateResultObjectType
case "AppConfigValidateResult": return AffineGraphQL.Objects.AppConfigValidateResult
+ case "BlobUploadInit": return AffineGraphQL.Objects.BlobUploadInit
+ case "BlobUploadPart": return AffineGraphQL.Objects.BlobUploadPart
+ case "BlobUploadedPart": return AffineGraphQL.Objects.BlobUploadedPart
case "ChatMessage": return AffineGraphQL.Objects.ChatMessage
case "CommentChangeObjectType": return AffineGraphQL.Objects.CommentChangeObjectType
case "CommentChangeObjectTypeEdge": return AffineGraphQL.Objects.CommentChangeObjectTypeEdge
diff --git a/packages/frontend/apps/ios/App/Podfile.lock b/packages/frontend/apps/ios/App/Podfile.lock
index ef43285496..87d06e4df2 100644
--- a/packages/frontend/apps/ios/App/Podfile.lock
+++ b/packages/frontend/apps/ios/App/Podfile.lock
@@ -45,13 +45,13 @@ EXTERNAL SOURCES:
:path: "../../../../../node_modules/capacitor-plugin-app-tracking-transparency"
SPEC CHECKSUMS:
- Capacitor: 03bc7cbdde6a629a8b910a9d7d78c3cc7ed09ea7
- CapacitorApp: febecbb9582cb353aed037e18ec765141f880fe9
- CapacitorBrowser: 6299776d496e968505464884d565992faa20444a
+ Capacitor: 106e7a4205f4618d582b886a975657c61179138d
+ CapacitorApp: d63334c052278caf5d81585d80b21905c6f93f39
+ CapacitorBrowser: 081852cf532acf77b9d2953f3a88fe5b9711fb06
CapacitorCordova: 5967b9ba03915ef1d585469d6e31f31dc49be96f
- CapacitorHaptics: 1f1e17041f435d8ead9ff2a34edd592c6aa6a8d6
- CapacitorKeyboard: 09fd91dcde4f8a37313e7f11bde553ad1ed52036
- CapacitorPluginAppTrackingTransparency: 92ae9c1cfb5cf477753db9269689332a686f675a
+ CapacitorHaptics: 70e47470fa1a6bd6338cd102552e3846b7f9a1b3
+ CapacitorKeyboard: 969647d0ca2e5c737d7300088e2517aa832434e2
+ CapacitorPluginAppTrackingTransparency: 2a2792623a5a72795f2e8f9ab3f1147573732fd8
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
PODFILE CHECKSUM: 2c1e4be82121f2d9724ecf7e31dd14e165aeb082
diff --git a/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts b/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts
index 6f1faecce1..c5319bf762 100644
--- a/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts
+++ b/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts
@@ -171,7 +171,9 @@ export interface NbStorePlugin {
id: string;
indexName: string;
query: string;
- }) => Promise<{ id: string; score: number; terms: Array }[]>;
+ }) => Promise<{
+ results: { id: string; score: number; terms: Array }[];
+ }>;
ftsGetDocument: (options: {
id: string;
indexName: string;
@@ -182,7 +184,7 @@ export interface NbStorePlugin {
indexName: string;
docId: string;
query: string;
- }) => Promise>;
+ }) => Promise<{ matches: { start: number; end: number }[] }>;
ftsFlushIndex: (options: { id: string }) => Promise;
- ftsIndexVersion: () => Promise;
+ ftsIndexVersion: () => Promise<{ indexVersion: number }>;
}
diff --git a/packages/frontend/apps/ios/src/plugins/nbstore/index.ts b/packages/frontend/apps/ios/src/plugins/nbstore/index.ts
index a26115f323..6691122a61 100644
--- a/packages/frontend/apps/ios/src/plugins/nbstore/index.ts
+++ b/packages/frontend/apps/ios/src/plugins/nbstore/index.ts
@@ -374,11 +374,12 @@ export const NbStoreNativeDBApis: NativeDBApis = {
indexName: string,
query: string
): Promise<{ id: string; score: number; terms: Array }[]> {
- return await NbStore.ftsSearch({
+ const { results } = await NbStore.ftsSearch({
id,
indexName,
query,
});
+ return results ?? [];
},
ftsGetDocument: async function (
id: string,
@@ -398,12 +399,13 @@ export const NbStoreNativeDBApis: NativeDBApis = {
docId: string,
query: string
): Promise<{ start: number; end: number }[]> {
- return await NbStore.ftsGetMatches({
+ const { matches } = await NbStore.ftsGetMatches({
id,
indexName,
docId,
query,
});
+ return matches ?? [];
},
ftsFlushIndex: async function (id: string): Promise {
await NbStore.ftsFlushIndex({
@@ -411,6 +413,6 @@ export const NbStoreNativeDBApis: NativeDBApis = {
});
},
ftsIndexVersion: function (): Promise {
- return NbStore.ftsIndexVersion();
+ return NbStore.ftsIndexVersion().then(res => res.indexVersion);
},
};
diff --git a/packages/frontend/core/src/modules/workspace-engine/impls/cloud.ts b/packages/frontend/core/src/modules/workspace-engine/impls/cloud.ts
index 56672c53ce..c4f808e90f 100644
--- a/packages/frontend/core/src/modules/workspace-engine/impls/cloud.ts
+++ b/packages/frontend/core/src/modules/workspace-engine/impls/cloud.ts
@@ -132,9 +132,10 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
BUILD_CONFIG.isElectron || BUILD_CONFIG.isIOS || BUILD_CONFIG.isAndroid
? SqliteBlobSyncStorage
: IndexedDBBlobSyncStorage;
- IndexerStorageType = BUILD_CONFIG.isElectron
- ? SqliteIndexerStorage
- : IndexedDBIndexerStorage;
+ IndexerStorageType =
+ BUILD_CONFIG.isElectron || BUILD_CONFIG.isIOS || BUILD_CONFIG.isAndroid
+ ? SqliteIndexerStorage
+ : IndexedDBIndexerStorage;
async deleteWorkspace(id: string): Promise {
await this.graphqlService.gql({
diff --git a/packages/frontend/core/src/modules/workspace-engine/impls/local.ts b/packages/frontend/core/src/modules/workspace-engine/impls/local.ts
index 2f57657b6c..fa9e6f0b3e 100644
--- a/packages/frontend/core/src/modules/workspace-engine/impls/local.ts
+++ b/packages/frontend/core/src/modules/workspace-engine/impls/local.ts
@@ -109,9 +109,10 @@ class LocalWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
BUILD_CONFIG.isElectron || BUILD_CONFIG.isIOS || BUILD_CONFIG.isAndroid
? SqliteBlobSyncStorage
: IndexedDBBlobSyncStorage;
- IndexerStorageType = BUILD_CONFIG.isElectron
- ? SqliteIndexerStorage
- : IndexedDBIndexerStorage;
+ IndexerStorageType =
+ BUILD_CONFIG.isElectron || BUILD_CONFIG.isIOS || BUILD_CONFIG.isAndroid
+ ? SqliteIndexerStorage
+ : IndexedDBIndexerStorage;
async deleteWorkspace(id: string): Promise {
setLocalWorkspaceIds(ids => ids.filter(x => x !== id));
diff --git a/packages/frontend/mobile-native/src/lib.rs b/packages/frontend/mobile-native/src/lib.rs
index 7abf0fe833..437472db0b 100644
--- a/packages/frontend/mobile-native/src/lib.rs
+++ b/packages/frontend/mobile-native/src/lib.rs
@@ -1,5 +1,5 @@
use affine_common::hashcash::Stamp;
-use affine_nbstore::pool::SqliteDocStoragePool;
+use affine_nbstore::{pool::SqliteDocStoragePool, Data};
#[derive(uniffi::Error, thiserror::Error, Debug)]
pub enum UniffiError {
@@ -50,9 +50,11 @@ impl TryFrom for affine_nbstore::DocRecord {
fn try_from(record: DocRecord) -> Result {
Ok(Self {
doc_id: record.doc_id,
- bin: base64_simd::STANDARD
- .decode_to_vec(record.bin)
- .map_err(|e| UniffiError::Base64DecodingError(e.to_string()))?,
+ bin: Into::::into(
+ base64_simd::STANDARD
+ .decode_to_vec(record.bin)
+ .map_err(|e| UniffiError::Base64DecodingError(e.to_string()))?,
+ ),
timestamp: chrono::DateTime::::from_timestamp_millis(record.timestamp)
.ok_or(UniffiError::TimestampDecodingError)?
.naive_utc(),
@@ -156,9 +158,11 @@ impl TryFrom for affine_nbstore::SetBlob {
fn try_from(blob: SetBlob) -> Result {
Ok(Self {
key: blob.key,
- data: base64_simd::STANDARD
- .decode_to_vec(blob.data)
- .map_err(|e| UniffiError::Base64DecodingError(e.to_string()))?,
+ data: Into::::into(
+ base64_simd::STANDARD
+ .decode_to_vec(blob.data)
+ .map_err(|e| UniffiError::Base64DecodingError(e.to_string()))?,
+ ),
mime: blob.mime,
})
}
@@ -229,6 +233,38 @@ impl From for CrawlResult {
}
}
+#[derive(uniffi::Record)]
+pub struct SearchHit {
+ pub id: String,
+ pub score: f64,
+ pub terms: Vec,
+}
+
+impl From for SearchHit {
+ fn from(value: affine_nbstore::indexer::NativeSearchHit) -> Self {
+ Self {
+ id: value.id,
+ score: value.score,
+ terms: value.terms,
+ }
+ }
+}
+
+#[derive(uniffi::Record)]
+pub struct MatchRange {
+ pub start: u32,
+ pub end: u32,
+}
+
+impl From for MatchRange {
+ fn from(value: affine_nbstore::indexer::NativeMatch) -> Self {
+ Self {
+ start: value.start,
+ end: value.end,
+ }
+ }
+}
+
#[derive(uniffi::Object)]
pub struct DocStoragePool {
inner: SqliteDocStoragePool,
@@ -699,4 +735,100 @@ impl DocStoragePool {
.await?;
Ok(result.into())
}
+
+ pub async fn fts_add_document(
+ &self,
+ universal_id: String,
+ index_name: String,
+ doc_id: String,
+ text: String,
+ index: bool,
+ ) -> Result<()> {
+ self
+ .inner
+ .get(universal_id)
+ .await?
+ .fts_add(&index_name, &doc_id, &text, index)
+ .await?;
+ Ok(())
+ }
+
+ pub async fn fts_delete_document(
+ &self,
+ universal_id: String,
+ index_name: String,
+ doc_id: String,
+ ) -> Result<()> {
+ self
+ .inner
+ .get(universal_id)
+ .await?
+ .fts_delete(&index_name, &doc_id)
+ .await?;
+ Ok(())
+ }
+
+ pub async fn fts_get_document(
+ &self,
+ universal_id: String,
+ index_name: String,
+ doc_id: String,
+ ) -> Result