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> { + Ok( + self + .inner + .get(universal_id) + .await? + .fts_get(&index_name, &doc_id) + .await?, + ) + } + + pub async fn fts_search( + &self, + universal_id: String, + index_name: String, + query: String, + ) -> Result> { + Ok( + self + .inner + .get(universal_id) + .await? + .fts_search(&index_name, &query) + .await? + .into_iter() + .map(Into::into) + .collect(), + ) + } + + pub async fn fts_get_matches( + &self, + universal_id: String, + index_name: String, + doc_id: String, + query: String, + ) -> Result> { + Ok( + self + .inner + .get(universal_id) + .await? + .fts_get_matches(&index_name, &doc_id, &query) + .await? + .into_iter() + .map(Into::into) + .collect(), + ) + } + + pub async fn fts_flush_index(&self, universal_id: String) -> Result<()> { + self.inner.get(universal_id).await?.flush_index().await?; + Ok(()) + } + + pub async fn fts_index_version(&self) -> Result { + Ok(affine_nbstore::storage::SqliteDocStorage::index_version()) + } }