diff --git a/apps/chanora_flutter/ios/Flutter/Debug.xcconfig b/apps/chanora_flutter/ios/Flutter/Debug.xcconfig index 6111d9e..ad5ee4e 100644 --- a/apps/chanora_flutter/ios/Flutter/Debug.xcconfig +++ b/apps/chanora_flutter/ios/Flutter/Debug.xcconfig @@ -1,6 +1,9 @@ #include? "Pods/Target Support Files/Pods-Chanora/Pods-Chanora.debug.xcconfig" #include "Generated.xcconfig" -// Mirror Release.xcconfig (see explanation there). -OTHER_LDFLAGS = $(inherited) -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_create -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_destroy -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_reset -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_process -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_last_error -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_free_string +// Mirror Release.xcconfig (see explanation there). `-u` is the load-bearing +// flag: without it the linker drops Swift @_cdecl symbols (no Swift caller) +// before `-exported_symbol` can re-export them, and the verify_silero_exports +// build phase fails the build. +OTHER_LDFLAGS = $(inherited) -Xlinker -u -Xlinker _chanora_silero_vad_create -Xlinker -u -Xlinker _chanora_silero_vad_destroy -Xlinker -u -Xlinker _chanora_silero_vad_reset -Xlinker -u -Xlinker _chanora_silero_vad_process -Xlinker -u -Xlinker _chanora_silero_vad_last_error -Xlinker -u -Xlinker _chanora_silero_vad_free_string -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_create -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_destroy -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_reset -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_process -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_last_error -Xlinker -exported_symbol -Xlinker _chanora_silero_vad_free_string STRIP_STYLE = non-global diff --git a/apps/chanora_flutter/ios/Runner/Info.plist b/apps/chanora_flutter/ios/Runner/Info.plist index 5364474..3c9f03c 100644 --- a/apps/chanora_flutter/ios/Runner/Info.plist +++ b/apps/chanora_flutter/ios/Runner/Info.plist @@ -25,7 +25,7 @@ CFBundleVersion $(FLUTTER_BUILD_NUMBER) ITSAppUsesNonExemptEncryption - + LSRequiresIPhoneOS LSSupportsOpeningDocumentsInPlace diff --git a/apps/chanora_flutter/lib/src/rust/api.dart b/apps/chanora_flutter/lib/src/rust/api.dart index c743d12..d6f759d 100644 --- a/apps/chanora_flutter/lib/src/rust/api.dart +++ b/apps/chanora_flutter/lib/src/rust/api.dart @@ -226,40 +226,28 @@ String exportDiagnostics() => RustLib.instance.api.crateApiExportDiagnostics(); Future initStorage({required String dir}) => RustLib.instance.api.crateApiInitStorage(dir: dir); -/// Wire the blob cache to a platform-private cache directory. -Future initCache({required String dir}) { - final api = RustLib.instance.api as dynamic; - try { - return api.crateApiInitCache(dir: dir) as Future; - } on NoSuchMethodError { - return Future.value(); - } -} +/// Configure the bridge blob cache root. +Future initCache({required String dir}) => + RustLib.instance.api.crateApiInitCache(dir: dir); -/// Return an avatar from cache when present; otherwise download it. -Future?> downloadAvatar({ +/// Resolve avatar bytes through the bridge. +Future downloadAvatar({ required String avatarHash, required String clientUid, -}) { - final api = RustLib.instance.api as dynamic; - try { - return api.crateApiDownloadAvatar( - avatarHash: avatarHash, - clientUid: clientUid, - ) as Future?>; - } on NoSuchMethodError { - return Future.value(); - } -} +}) => RustLib.instance.api.crateApiDownloadAvatar( + avatarHash: avatarHash, + clientUid: clientUid, +); -Future?> downloadIcon({required BigInt iconId}) { - final api = RustLib.instance.api as dynamic; - try { - return api.crateApiDownloadIcon(iconId: iconId) as Future?>; - } on NoSuchMethodError { - return Future.value(); - } -} +/// Resolve icon bytes through the bridge. +Future downloadIcon({required BigInt iconId}) => + RustLib.instance.api.crateApiDownloadIcon(iconId: iconId); + +/// Purge cached protocol-owned assets. +Future clearFileCache() => RustLib.instance.api.crateApiClearFileCache(); + +/// Report the configured file-cache size. +Future fileCacheSize() => RustLib.instance.api.crateApiFileCacheSize(); /// List persisted bookmarks. Future> listBookmarks() => diff --git a/apps/chanora_flutter/lib/src/rust/frb_generated.dart b/apps/chanora_flutter/lib/src/rust/frb_generated.dart index eeb9886..62160f5 100644 --- a/apps/chanora_flutter/lib/src/rust/frb_generated.dart +++ b/apps/chanora_flutter/lib/src/rust/frb_generated.dart @@ -67,7 +67,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -20394775; + int get rustContentHash => 635684021; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -87,6 +87,8 @@ abstract class RustLibApi extends BaseApi { Future crateApiBridgeInit(); + Future crateApiClearFileCache(); + Future crateApiClientProfile({required BigInt clientId}); Future crateApiConnect({ @@ -99,12 +101,21 @@ abstract class RustLibApi extends BaseApi { Future crateApiDisconnect(); + Future crateApiDownloadAvatar({ + required String avatarHash, + required String clientUid, + }); + + Future crateApiDownloadIcon({required BigInt iconId}); + Future crateApiEnableAudioDebugWavDump({required bool enabled}); Stream crateApiEventsStream(); String crateApiExportDiagnostics(); + Future crateApiFileCacheSize(); + Future crateApiGetAudioProcessingConfig(); Future crateApiGetPttBinding(); @@ -121,6 +132,8 @@ abstract class RustLibApi extends BaseApi { void crateApiHandleRouteChange({required BridgeAudioRoute route}); + Future crateApiInitCache({required String dir}); + Future crateApiInitStorage({required String dir}); Stream crateApiInputLevelStream(); @@ -320,6 +333,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiBridgeInitConstMeta => const TaskConstMeta(debugName: "bridge_init", argNames: []); + @override + Future crateApiClearFileCache() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 5, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_bridge_error, + ), + constMeta: kCrateApiClearFileCacheConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiClearFileCacheConstMeta => + const TaskConstMeta(debugName: "clear_file_cache", argNames: []); + @override Future crateApiClientProfile({ required BigInt clientId, @@ -332,7 +372,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 5, + funcId: 6, port: port_, ); }, @@ -366,7 +406,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 6, + funcId: 7, port: port_, ); }, @@ -396,7 +436,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 7, + funcId: 8, port: port_, ); }, @@ -423,7 +463,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 8, + funcId: 9, port: port_, ); }, @@ -441,6 +481,68 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiDisconnectConstMeta => const TaskConstMeta(debugName: "disconnect", argNames: []); + @override + Future crateApiDownloadAvatar({ + required String avatarHash, + required String clientUid, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(avatarHash, serializer); + sse_encode_String(clientUid, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 10, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, + decodeErrorData: sse_decode_bridge_error, + ), + constMeta: kCrateApiDownloadAvatarConstMeta, + argValues: [avatarHash, clientUid], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDownloadAvatarConstMeta => const TaskConstMeta( + debugName: "download_avatar", + argNames: ["avatarHash", "clientUid"], + ); + + @override + Future crateApiDownloadIcon({required BigInt iconId}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_64(iconId, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 11, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, + decodeErrorData: sse_decode_bridge_error, + ), + constMeta: kCrateApiDownloadIconConstMeta, + argValues: [iconId], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDownloadIconConstMeta => + const TaskConstMeta(debugName: "download_icon", argNames: ["iconId"]); + @override Future crateApiEnableAudioDebugWavDump({required bool enabled}) { return handler.executeNormal( @@ -451,7 +553,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 9, + funcId: 12, port: port_, ); }, @@ -484,7 +586,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 10, + funcId: 13, port: port_, ); }, @@ -510,7 +612,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -526,6 +628,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiExportDiagnosticsConstMeta => const TaskConstMeta(debugName: "export_diagnostics", argNames: []); + @override + Future crateApiFileCacheSize() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 15, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_64, + decodeErrorData: sse_decode_bridge_error, + ), + constMeta: kCrateApiFileCacheSizeConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiFileCacheSizeConstMeta => + const TaskConstMeta(debugName: "file_cache_size", argNames: []); + @override Future crateApiGetAudioProcessingConfig() { return handler.executeNormal( @@ -535,7 +664,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 12, + funcId: 16, port: port_, ); }, @@ -565,7 +694,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 13, + funcId: 17, port: port_, ); }, @@ -592,7 +721,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 14, + funcId: 18, port: port_, ); }, @@ -619,7 +748,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 15, + funcId: 19, port: port_, ); }, @@ -643,7 +772,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -666,7 +795,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(shouldResume, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -692,7 +821,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(routeClass, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -718,7 +847,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bridge_audio_route(route, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -736,6 +865,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["route"], ); + @override + Future crateApiInitCache({required String dir}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dir, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 24, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_bridge_error, + ), + constMeta: kCrateApiInitCacheConstMeta, + argValues: [dir], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiInitCacheConstMeta => + const TaskConstMeta(debugName: "init_cache", argNames: ["dir"]); + @override Future crateApiInitStorage({required String dir}) { return handler.executeNormal( @@ -746,7 +903,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 20, + funcId: 25, port: port_, ); }, @@ -776,7 +933,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 21, + funcId: 26, port: port_, ); }, @@ -805,7 +962,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 22, + funcId: 27, port: port_, ); }, @@ -832,7 +989,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 23, + funcId: 28, port: port_, ); }, @@ -859,7 +1016,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 24, + funcId: 29, port: port_, ); }, @@ -883,7 +1040,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -913,7 +1070,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 26, + funcId: 31, port: port_, ); }, @@ -943,7 +1100,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 27, + funcId: 32, port: port_, ); }, @@ -970,7 +1127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 28, + funcId: 33, port: port_, ); }, @@ -995,7 +1152,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(state, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1028,7 +1185,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 30, + funcId: 35, port: port_, ); }, @@ -1055,7 +1212,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bridge_audio_route(route, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1089,7 +1246,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 32, + funcId: 37, port: port_, ); }, @@ -1124,7 +1281,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 33, + funcId: 38, port: port_, ); }, @@ -1154,7 +1311,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 34, + funcId: 39, port: port_, ); }, @@ -1182,7 +1339,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 35, + funcId: 40, port: port_, ); }, @@ -1210,7 +1367,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 36, + funcId: 41, port: port_, ); }, @@ -1240,7 +1397,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 37, + funcId: 42, port: port_, ); }, @@ -1268,7 +1425,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bridge_network_state(state, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1294,7 +1451,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 39, + funcId: 44, port: port_, ); }, @@ -1322,7 +1479,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 40, + funcId: 45, port: port_, ); }, @@ -1350,7 +1507,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 41, + funcId: 46, port: port_, ); }, @@ -1378,7 +1535,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 42, + funcId: 47, port: port_, ); }, @@ -1410,7 +1567,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 43, + funcId: 48, port: port_, ); }, @@ -1440,7 +1597,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 44, + funcId: 49, port: port_, ); }, @@ -1468,7 +1625,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 45, + funcId: 50, port: port_, ); }, @@ -1496,7 +1653,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 46, + funcId: 51, port: port_, ); }, @@ -1523,7 +1680,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 47, + funcId: 52, port: port_, ); }, @@ -1551,7 +1708,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 48, + funcId: 53, port: port_, ); }, @@ -1583,7 +1740,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 49, + funcId: 54, port: port_, ); }, @@ -1612,7 +1769,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 50, + funcId: 55, port: port_, ); }, @@ -2290,6 +2447,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_u_64(raw); } + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_list_prim_u_8_strict(raw); + } + @protected PermissionStateKind dco_decode_permission_state_kind(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3249,6 +3412,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_list_prim_u_8_strict(deserializer)); + } else { + return null; + } + } + @protected PermissionStateKind sse_decode_permission_state_kind( SseDeserializer deserializer, @@ -4096,6 +4270,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_list_prim_u_8_strict(self, serializer); + } + } + @protected void sse_encode_permission_state_kind( PermissionStateKind self, diff --git a/apps/chanora_flutter/lib/src/rust/frb_generated.io.dart b/apps/chanora_flutter/lib/src/rust/frb_generated.io.dart index d6cad6c..f5280a7 100644 --- a/apps/chanora_flutter/lib/src/rust/frb_generated.io.dart +++ b/apps/chanora_flutter/lib/src/rust/frb_generated.io.dart @@ -201,6 +201,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw); + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw); + @protected PermissionStateKind dco_decode_permission_state_kind(dynamic raw); @@ -444,6 +447,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer); + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer); + @protected PermissionStateKind sse_decode_permission_state_kind( SseDeserializer deserializer, @@ -746,6 +752,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer); + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ); + @protected void sse_encode_permission_state_kind( PermissionStateKind self, diff --git a/apps/chanora_flutter/lib/src/rust/frb_generated.web.dart b/apps/chanora_flutter/lib/src/rust/frb_generated.web.dart index 5d9c328..77ba056 100644 --- a/apps/chanora_flutter/lib/src/rust/frb_generated.web.dart +++ b/apps/chanora_flutter/lib/src/rust/frb_generated.web.dart @@ -203,6 +203,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected BigInt? dco_decode_opt_box_autoadd_u_64(dynamic raw); + @protected + Uint8List? dco_decode_opt_list_prim_u_8_strict(dynamic raw); + @protected PermissionStateKind dco_decode_permission_state_kind(dynamic raw); @@ -446,6 +449,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected BigInt? sse_decode_opt_box_autoadd_u_64(SseDeserializer deserializer); + @protected + Uint8List? sse_decode_opt_list_prim_u_8_strict(SseDeserializer deserializer); + @protected PermissionStateKind sse_decode_permission_state_kind( SseDeserializer deserializer, @@ -748,6 +754,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_u_64(BigInt? self, SseSerializer serializer); + @protected + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, + SseSerializer serializer, + ); + @protected void sse_encode_permission_state_kind( PermissionStateKind self, diff --git a/apps/chanora_flutter/scripts/verify_silero_exports.sh b/apps/chanora_flutter/scripts/verify_silero_exports.sh index a1ce2d5..2351e71 100755 --- a/apps/chanora_flutter/scripts/verify_silero_exports.sh +++ b/apps/chanora_flutter/scripts/verify_silero_exports.sh @@ -31,6 +31,18 @@ if [ ! -f "${BINARY}" ]; then exit 1 fi +# Flutter Debug builds split user code into a sibling `.debug.dylib` +# alongside a tiny launcher executable; the @_cdecl symbols live in the +# dylib. Release/Profile builds put everything in the main executable. +# Prefer the dylib when both exist so the check verifies the slice that +# actually carries the symbols. +EXECUTABLE_DIR=$(dirname "${BINARY}") +EXECUTABLE_NAME=$(basename "${BINARY}") +DEBUG_DYLIB="${EXECUTABLE_DIR}/${EXECUTABLE_NAME}.debug.dylib" +if [ -f "${DEBUG_DYLIB}" ]; then + BINARY="${DEBUG_DYLIB}" +fi + REQUIRED_SYMBOLS=" _chanora_silero_vad_create _chanora_silero_vad_destroy diff --git a/crates/chanora_bridge/src/frb_generated.rs b/crates/chanora_bridge/src/frb_generated.rs index efb1d87..a9cc692 100644 --- a/crates/chanora_bridge/src/frb_generated.rs +++ b/crates/chanora_bridge/src/frb_generated.rs @@ -38,7 +38,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -20394775; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 635684021; // Section: executor @@ -186,6 +186,41 @@ fn wire__crate__api__bridge_init_impl( }, ) } +fn wire__crate__api__clear_file_cache_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "clear_file_cache", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, crate::BridgeError>( + (move || async move { + let output_ok = crate::api::clear_file_cache().await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__client_profile_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -332,6 +367,80 @@ fn wire__crate__api__disconnect_impl( }, ) } +fn wire__crate__api__download_avatar_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "download_avatar", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_avatar_hash = ::sse_decode(&mut deserializer); + let api_client_uid = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, crate::BridgeError>( + (move || async move { + let output_ok = + crate::api::download_avatar(api_avatar_hash, api_client_uid).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__download_icon_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "download_icon", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_icon_id = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, crate::BridgeError>( + (move || async move { + let output_ok = crate::api::download_icon(api_icon_id).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__enable_audio_debug_wav_dump_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -434,6 +543,41 @@ fn wire__crate__api__export_diagnostics_impl( }, ) } +fn wire__crate__api__file_cache_size_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "file_cache_size", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, crate::BridgeError>( + (move || async move { + let output_ok = crate::api::file_cache_size().await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__get_audio_processing_config_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -702,6 +846,42 @@ fn wire__crate__api__handle_route_change_impl( }, ) } +fn wire__crate__api__init_cache_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "init_cache", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_dir = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, crate::BridgeError>( + (move || async move { + let output_ok = crate::api::init_cache(api_dir).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__init_storage_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -2763,6 +2943,17 @@ impl SseDecode for Option { } } +impl SseDecode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>::sse_decode(deserializer)); + } else { + return None; + } + } +} + impl SseDecode for crate::api::PermissionStateKind { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -2816,45 +3007,50 @@ fn pde_ffi_dispatcher_primary_impl( 2 => wire__crate__api__audio_processing_stats_impl(port, ptr, rust_vec_len, data_len), 3 => wire__crate__api__audio_stats_impl(port, ptr, rust_vec_len, data_len), 4 => wire__crate__api__bridge_init_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__api__client_profile_impl(port, ptr, rust_vec_len, data_len), - 6 => wire__crate__api__connect_impl(port, ptr, rust_vec_len, data_len), - 7 => wire__crate__api__delete_bookmark_impl(port, ptr, rust_vec_len, data_len), - 8 => wire__crate__api__disconnect_impl(port, ptr, rust_vec_len, data_len), - 9 => wire__crate__api__enable_audio_debug_wav_dump_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__api__events_stream_impl(port, ptr, rust_vec_len, data_len), - 12 => wire__crate__api__get_audio_processing_config_impl(port, ptr, rust_vec_len, data_len), - 13 => wire__crate__api__get_ptt_binding_impl(port, ptr, rust_vec_len, data_len), - 14 => wire__crate__api__get_release_tail_ms_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__get_transmit_mode_impl(port, ptr, rust_vec_len, data_len), - 20 => wire__crate__api__init_storage_impl(port, ptr, rust_vec_len, data_len), - 21 => wire__crate__api__input_level_stream_impl(port, ptr, rust_vec_len, data_len), - 22 => wire__crate__api__is_connected_impl(port, ptr, rust_vec_len, data_len), - 23 => wire__crate__api__list_audio_devices_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__list_bookmarks_impl(port, ptr, rust_vec_len, data_len), - 26 => wire__crate__api__move_to_channel_impl(port, ptr, rust_vec_len, data_len), - 27 => wire__crate__api__prefetch_server_impl(port, ptr, rust_vec_len, data_len), - 28 => wire__crate__api__ptt_descriptor_impl(port, ptr, rust_vec_len, data_len), - 30 => wire__crate__api__send_chat_message_impl(port, ptr, rust_vec_len, data_len), - 32 => wire__crate__api__set_audio_processing_config_impl(port, ptr, rust_vec_len, data_len), - 33 => wire__crate__api__set_client_volume_impl(port, ptr, rust_vec_len, data_len), - 34 => wire__crate__api__set_hard_mute_impl(port, ptr, rust_vec_len, data_len), - 35 => wire__crate__api__set_input_device_impl(port, ptr, rust_vec_len, data_len), - 36 => wire__crate__api__set_input_muted_impl(port, ptr, rust_vec_len, data_len), - 37 => { + 5 => wire__crate__api__clear_file_cache_impl(port, ptr, rust_vec_len, data_len), + 6 => wire__crate__api__client_profile_impl(port, ptr, rust_vec_len, data_len), + 7 => wire__crate__api__connect_impl(port, ptr, rust_vec_len, data_len), + 8 => wire__crate__api__delete_bookmark_impl(port, ptr, rust_vec_len, data_len), + 9 => wire__crate__api__disconnect_impl(port, ptr, rust_vec_len, data_len), + 10 => wire__crate__api__download_avatar_impl(port, ptr, rust_vec_len, data_len), + 11 => wire__crate__api__download_icon_impl(port, ptr, rust_vec_len, data_len), + 12 => wire__crate__api__enable_audio_debug_wav_dump_impl(port, ptr, rust_vec_len, data_len), + 13 => wire__crate__api__events_stream_impl(port, ptr, rust_vec_len, data_len), + 15 => wire__crate__api__file_cache_size_impl(port, ptr, rust_vec_len, data_len), + 16 => wire__crate__api__get_audio_processing_config_impl(port, ptr, rust_vec_len, data_len), + 17 => wire__crate__api__get_ptt_binding_impl(port, ptr, rust_vec_len, data_len), + 18 => wire__crate__api__get_release_tail_ms_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__get_transmit_mode_impl(port, ptr, rust_vec_len, data_len), + 24 => wire__crate__api__init_cache_impl(port, ptr, rust_vec_len, data_len), + 25 => wire__crate__api__init_storage_impl(port, ptr, rust_vec_len, data_len), + 26 => wire__crate__api__input_level_stream_impl(port, ptr, rust_vec_len, data_len), + 27 => wire__crate__api__is_connected_impl(port, ptr, rust_vec_len, data_len), + 28 => wire__crate__api__list_audio_devices_impl(port, ptr, rust_vec_len, data_len), + 29 => wire__crate__api__list_bookmarks_impl(port, ptr, rust_vec_len, data_len), + 31 => wire__crate__api__move_to_channel_impl(port, ptr, rust_vec_len, data_len), + 32 => wire__crate__api__prefetch_server_impl(port, ptr, rust_vec_len, data_len), + 33 => wire__crate__api__ptt_descriptor_impl(port, ptr, rust_vec_len, data_len), + 35 => wire__crate__api__send_chat_message_impl(port, ptr, rust_vec_len, data_len), + 37 => wire__crate__api__set_audio_processing_config_impl(port, ptr, rust_vec_len, data_len), + 38 => wire__crate__api__set_client_volume_impl(port, ptr, rust_vec_len, data_len), + 39 => wire__crate__api__set_hard_mute_impl(port, ptr, rust_vec_len, data_len), + 40 => wire__crate__api__set_input_device_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__set_input_muted_impl(port, ptr, rust_vec_len, data_len), + 42 => { wire__crate__api__set_ios_voice_processing_mode_impl(port, ptr, rust_vec_len, data_len) } - 39 => wire__crate__api__set_output_device_impl(port, ptr, rust_vec_len, data_len), - 40 => wire__crate__api__set_output_gain_impl(port, ptr, rust_vec_len, data_len), - 41 => wire__crate__api__set_output_muted_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__set_ptt_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__crate__api__set_ptt_binding_impl(port, ptr, rust_vec_len, data_len), - 44 => wire__crate__api__set_release_tail_ms_impl(port, ptr, rust_vec_len, data_len), - 45 => wire__crate__api__set_transmit_mode_impl(port, ptr, rust_vec_len, data_len), - 46 => wire__crate__api__set_vad_model_path_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__snapshot_impl(port, ptr, rust_vec_len, data_len), - 48 => wire__crate__api__update_bookmark_impl(port, ptr, rust_vec_len, data_len), - 49 => wire__crate__api__voice_join_impl(port, ptr, rust_vec_len, data_len), - 50 => wire__crate__api__voice_leave_impl(port, ptr, rust_vec_len, data_len), + 44 => wire__crate__api__set_output_device_impl(port, ptr, rust_vec_len, data_len), + 45 => wire__crate__api__set_output_gain_impl(port, ptr, rust_vec_len, data_len), + 46 => wire__crate__api__set_output_muted_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__set_ptt_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__set_ptt_binding_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__crate__api__set_release_tail_ms_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__set_transmit_mode_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__set_vad_model_path_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__snapshot_impl(port, ptr, rust_vec_len, data_len), + 53 => wire__crate__api__update_bookmark_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__voice_join_impl(port, ptr, rust_vec_len, data_len), + 55 => wire__crate__api__voice_leave_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -2867,19 +3063,19 @@ fn pde_ffi_dispatcher_sync_impl( ) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 11 => wire__crate__api__export_diagnostics_impl(ptr, rust_vec_len, data_len), - 16 => wire__crate__api__handle_interruption_began_impl(ptr, rust_vec_len, data_len), - 17 => wire__crate__api__handle_interruption_ended_impl(ptr, rust_vec_len, data_len), - 18 => wire__crate__api__handle_media_services_reset_with_route_impl( + 14 => wire__crate__api__export_diagnostics_impl(ptr, rust_vec_len, data_len), + 20 => wire__crate__api__handle_interruption_began_impl(ptr, rust_vec_len, data_len), + 21 => wire__crate__api__handle_interruption_ended_impl(ptr, rust_vec_len, data_len), + 22 => wire__crate__api__handle_media_services_reset_with_route_impl( ptr, rust_vec_len, data_len, ), - 19 => wire__crate__api__handle_route_change_impl(ptr, rust_vec_len, data_len), - 25 => wire__crate__api__log_file_path_str_impl(ptr, rust_vec_len, data_len), - 29 => wire__crate__api__record_lifecycle_event_impl(ptr, rust_vec_len, data_len), - 31 => wire__crate__api__set_audio_output_route_impl(ptr, rust_vec_len, data_len), - 38 => wire__crate__api__set_network_state_impl(ptr, rust_vec_len, data_len), + 23 => wire__crate__api__handle_route_change_impl(ptr, rust_vec_len, data_len), + 30 => wire__crate__api__log_file_path_str_impl(ptr, rust_vec_len, data_len), + 34 => wire__crate__api__record_lifecycle_event_impl(ptr, rust_vec_len, data_len), + 36 => wire__crate__api__set_audio_output_route_impl(ptr, rust_vec_len, data_len), + 43 => wire__crate__api__set_network_state_impl(ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -4556,6 +4752,16 @@ impl SseEncode for Option { } } +impl SseEncode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >::sse_encode(value, serializer); + } + } +} + impl SseEncode for crate::api::PermissionStateKind { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {