diff --git a/local_plugins/device_jieli/ios/Classes/Bridge/EventDispatcher.swift b/local_plugins/device_jieli/ios/Classes/Bridge/EventDispatcher.swift index fa55d2929..c50c656c9 100644 --- a/local_plugins/device_jieli/ios/Classes/Bridge/EventDispatcher.swift +++ b/local_plugins/device_jieli/ios/Classes/Bridge/EventDispatcher.swift @@ -4,7 +4,10 @@ import Foundation /// Native-side event subscriber. Mirrors Android `JieliEventListener`. /// Implementers receive the same `payload` dictionary that gets pushed to /// the Flutter EventChannel, so native and Dart subscribers stay symmetric. -@objc public protocol JieliEventListener: AnyObject { +/// +/// Pure-Swift protocol (not `@objc`) because the payload's `[String: Any?]` +/// cannot be bridged to Obj-C (Obj-C dictionary values can't be nullable). +protocol JieliEventListener: AnyObject { func onEvent(payload: [String: Any?]) } @@ -14,7 +17,7 @@ import Foundation /// originating queue — fits high-frequency audio frames). /// /// Mirrors Android `bridge/EventDispatcher.kt`. -public class EventDispatcher: NSObject, FlutterStreamHandler { +class EventDispatcher: NSObject, FlutterStreamHandler { private let lock = NSLock() private var sink: FlutterEventSink? @@ -22,7 +25,7 @@ public class EventDispatcher: NSObject, FlutterStreamHandler { // MARK: - FlutterStreamHandler - public func onListen( + func onListen( withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink ) -> FlutterError? { @@ -31,7 +34,7 @@ public class EventDispatcher: NSObject, FlutterStreamHandler { return nil } - public func onCancel(withArguments arguments: Any?) -> FlutterError? { + func onCancel(withArguments arguments: Any?) -> FlutterError? { lock.lock(); defer { lock.unlock() } sink = nil return nil @@ -39,14 +42,14 @@ public class EventDispatcher: NSObject, FlutterStreamHandler { // MARK: - Native listeners - public func addNativeListener(_ listener: JieliEventListener) { + func addNativeListener(_ listener: JieliEventListener) { lock.lock(); defer { lock.unlock() } if !listeners.contains(where: { $0 === listener }) { listeners.append(listener) } } - public func removeNativeListener(_ listener: JieliEventListener) { + func removeNativeListener(_ listener: JieliEventListener) { lock.lock(); defer { lock.unlock() } listeners.removeAll { $0 === listener } } @@ -57,7 +60,7 @@ public class EventDispatcher: NSObject, FlutterStreamHandler { /// /// Payload schema: identical to Android. `type` is the discriminator key /// that the Dart `Jielihome._parseEvent(...)` switches on. - public func send(_ payload: [String: Any?]) { + func send(_ payload: [String: Any?]) { let snapshot: [JieliEventListener] let sinkRef: FlutterEventSink? lock.lock() diff --git a/local_plugins/device_jieli/ios/Classes/Bridge/MethodRouter.swift b/local_plugins/device_jieli/ios/Classes/Bridge/MethodRouter.swift index 30fb4cd20..8ab3394bf 100644 --- a/local_plugins/device_jieli/ios/Classes/Bridge/MethodRouter.swift +++ b/local_plugins/device_jieli/ios/Classes/Bridge/MethodRouter.swift @@ -8,15 +8,15 @@ import UIKit /// argument keys. Where the iOS JieLi SDK does not yet have a wired /// implementation, the handler returns a `NOT_IMPLEMENTED_IOS` error so the /// Dart layer can downgrade gracefully (instead of crashing). -public class MethodRouter { +class MethodRouter { private let server: JieliHomeServer - public init(server: JieliHomeServer) { + init(server: JieliHomeServer) { self.server = server } - public func handle(call: FlutterMethodCall, result: @escaping FlutterResult) { + func handle(call: FlutterMethodCall, result: @escaping FlutterResult) { let args = call.arguments as? [String: Any] ?? [:] do { switch call.method { @@ -317,10 +317,10 @@ public class MethodRouter { /// Local plugin error wrapping that maps cleanly onto FlutterError. Used by /// feature classes when they need to surface a typed error code without /// throwing an opaque NSError. -public struct PluginError: Error { - public let code: String - public let message: String - public init(_ code: String, _ message: String) { +struct PluginError: Error { + let code: String + let message: String + init(_ code: String, _ message: String) { self.code = code self.message = message } diff --git a/local_plugins/device_jieli/ios/Classes/Core/JieliHomeServer.swift b/local_plugins/device_jieli/ios/Classes/Core/JieliHomeServer.swift index aea6c0c10..52e0ab912 100644 --- a/local_plugins/device_jieli/ios/Classes/Core/JieliHomeServer.swift +++ b/local_plugins/device_jieli/ios/Classes/Core/JieliHomeServer.swift @@ -13,14 +13,14 @@ import JL_BLEKit /// /// Initialization is idempotent — calling [initialize] twice returns /// immediately on the second call. -public class JieliHomeServer { +class JieliHomeServer { - public static let shared = JieliHomeServer() + static let shared = JieliHomeServer() private(set) public var initialized: Bool = false /// Event bus shared by Flutter EventChannel + native listeners. - public let dispatcher: EventDispatcher = EventDispatcher() + let dispatcher: EventDispatcher = EventDispatcher() // MARK: - Underlying SDK references // The JieLi iOS SDK exposes BLE plumbing via `JL_BLEMultiple` and per-device @@ -34,36 +34,36 @@ public class JieliHomeServer { /// `JLTranslationManager`. Holds the active translation sink (call /// translation / assistant / device record); modules switch sinks as they /// enter/exit modes — only one mode at a time. - public private(set) lazy var translationCoordinator: TranslationCoordinator = { + private(set) lazy var translationCoordinator: TranslationCoordinator = { TranslationCoordinator(server: self) }() // MARK: - Features (lazy-attached after initialize) - public private(set) lazy var scanFeature: ScanFeature = { + private(set) lazy var scanFeature: ScanFeature = { ScanFeature(dispatcher: dispatcher) }() - public private(set) lazy var connectFeature: ConnectFeature = { + private(set) lazy var connectFeature: ConnectFeature = { ConnectFeature(server: self) }() - public private(set) lazy var deviceInfoFeature: DeviceInfoFeature = { + private(set) lazy var deviceInfoFeature: DeviceInfoFeature = { DeviceInfoFeature(server: self) }() - public private(set) lazy var customCmdFeature: CustomCmdFeature = { + private(set) lazy var customCmdFeature: CustomCmdFeature = { CustomCmdFeature(server: self) }() - public private(set) lazy var translationFeature: TranslationFeature = { + private(set) lazy var translationFeature: TranslationFeature = { TranslationFeature(server: self) }() - public private(set) lazy var speechFeature: SpeechFeature = { + private(set) lazy var speechFeature: SpeechFeature = { SpeechFeature(server: self) }() - public private(set) lazy var otaFeature: OtaFeature = { + private(set) lazy var otaFeature: OtaFeature = { OtaFeature(server: self) }() - public private(set) lazy var deviceRecordFeature: DeviceRecordFeature = { + private(set) lazy var deviceRecordFeature: DeviceRecordFeature = { DeviceRecordFeature(server: self) }() - public private(set) lazy var assistantBridge: AssistantBridge = { + private(set) lazy var assistantBridge: AssistantBridge = { AssistantBridge(server: self) }() @@ -71,7 +71,7 @@ public class JieliHomeServer { // MARK: - Lifecycle - public func initialize( + func initialize( multiDevice: Bool, skipNoNameDev: Bool, enableLog: Bool @@ -103,7 +103,7 @@ public class JieliHomeServer { ]) } - public func shutdown() { + func shutdown() { if !initialized { return } otaFeature.cancel() deviceRecordFeature.stop() @@ -116,11 +116,11 @@ public class JieliHomeServer { // MARK: - Native event subscription helpers - public func addEventListener(_ listener: JieliEventListener) { + func addEventListener(_ listener: JieliEventListener) { dispatcher.addNativeListener(listener) } - public func removeEventListener(_ listener: JieliEventListener) { + func removeEventListener(_ listener: JieliEventListener) { dispatcher.removeNativeListener(listener) } diff --git a/local_plugins/device_jieli/ios/Classes/Feature/AssistantBridge.swift b/local_plugins/device_jieli/ios/Classes/Feature/AssistantBridge.swift index 1cd8f0c55..4e76fbc34 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/AssistantBridge.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/AssistantBridge.swift @@ -24,7 +24,7 @@ import JL_BLEKit /// re-routes through the connected A2DP earphone. iOS equivalent is /// `AVAudioEngine`/`AudioQueue`; the orchestrator can drive this directly /// or call back through `assistantPlayback` (TODO once needed). -public class AssistantBridge { +class AssistantBridge { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } @@ -36,9 +36,9 @@ public class AssistantBridge { private var sinkWrapper: AssistantSinkWrapper? #endif - public func isRunning() -> Bool { running } + func isRunning() -> Bool { running } - public func start() -> Bool { + func start() -> Bool { if running { return true } #if canImport(JL_BLEKit) guard let server = server else { return false } @@ -118,7 +118,7 @@ public class AssistantBridge { #endif } - public func stop() { + func stop() { if !running { return } running = false cleanup() @@ -128,7 +128,7 @@ public class AssistantBridge { ]) } - public func shutdown() { stop() } + func shutdown() { stop() } // MARK: - Internal diff --git a/local_plugins/device_jieli/ios/Classes/Feature/ConnectFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/ConnectFeature.swift index e36587beb..c5750ab4e 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/ConnectFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/ConnectFeature.swift @@ -12,7 +12,7 @@ import JL_BLEKit /// (0=disconnect, 1=ok, 2=connecting). RCSP-init success surfaces as a /// separate `rcspInit` event when the JieLi SDK confirms `cmdTargetFeatureResult` /// returns successfully — same flow Android publishes. -public class ConnectFeature: NSObject { +class ConnectFeature: NSObject { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } diff --git a/local_plugins/device_jieli/ios/Classes/Feature/CustomCmdFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/CustomCmdFeature.swift index 065b15dc7..b8812b562 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/CustomCmdFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/CustomCmdFeature.swift @@ -12,12 +12,12 @@ import JL_BLEKit /// argument, so we prepend the opCode byte to the payload and call that. /// The reply comes back through the result block. This matches the shape /// the Dart caller expects: a `[Int]` response. -public class CustomCmdFeature { +class CustomCmdFeature { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } - public func send( + func send( address: String, opCode: UInt8, payload: Data, diff --git a/local_plugins/device_jieli/ios/Classes/Feature/DeviceInfoFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/DeviceInfoFeature.swift index ae8ec68d8..e5f4ccd69 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/DeviceInfoFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/DeviceInfoFeature.swift @@ -10,12 +10,12 @@ import JL_BLEKit /// caller. The Android schema (`name`, `firmwareVersion`, `battery`, ...) is /// preserved; iOS-specific extras (`bleAddr`, `btAddr`, `pidvid`) are added /// for completeness — Dart consumers ignore unknown keys. -public class DeviceInfoFeature { +class DeviceInfoFeature { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } - public func snapshot(address: String) -> [String: Any?]? { + func snapshot(address: String) -> [String: Any?]? { #if canImport(JL_BLEKit) guard let entity = server?.connectFeature.currentEntity() as? JL_EntityM, entity.mUUID == address else { @@ -39,7 +39,7 @@ public class DeviceInfoFeature { #endif } - public func queryTargetInfo( + func queryTargetInfo( address: String, mask: Int, completion: @escaping ([String: Any?]?, Error?) -> Void diff --git a/local_plugins/device_jieli/ios/Classes/Feature/DeviceRecordFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/DeviceRecordFeature.swift index 8fdbf0075..572accfd2 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/DeviceRecordFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/DeviceRecordFeature.swift @@ -21,7 +21,7 @@ import JL_BLEKit /// /// Mutually exclusive with TranslationFeature — both use the shared /// `JLTranslationManager`. The MethodRouter stops the other before starting. -public class DeviceRecordFeature { +class DeviceRecordFeature { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } @@ -36,9 +36,9 @@ public class DeviceRecordFeature { private var sinkWrapper: RecordSinkWrapper? #endif - public func isRecording() -> Bool { working } + func isRecording() -> Bool { working } - public func start(args: [String: Any]) throws { + func start(args: [String: Any]) throws { if working { throw PluginError("DEVICE_RECORD_ERR", "already recording") } #if canImport(JL_BLEKit) guard let server = server else { @@ -101,7 +101,7 @@ public class DeviceRecordFeature { #endif } - public func stop() { + func stop() { if !working { return } working = false let addr = deviceAddress diff --git a/local_plugins/device_jieli/ios/Classes/Feature/OtaFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/OtaFeature.swift index 540a15af0..0c124c506 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/OtaFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/OtaFeature.swift @@ -15,16 +15,16 @@ import JL_OTALib /// progress callback into the same `otaState` / `otaError` event shapes /// the Android side publishes — Dart `_parseOtaState(...)` keeps working /// unchanged. -public class OtaFeature { +class OtaFeature { weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } private var running: Bool = false - public func isRunning() -> Bool { running } + func isRunning() -> Bool { running } - public func start( + func start( address: String?, firmwareFilePath: String, blockSize: Int, @@ -47,9 +47,16 @@ public class OtaFeature { "state": "INQUIRING", "sent": 0, "total": 0, "percent": -1, "tsMs": Self.tsMs(), ]) - server.bleMultiple.otaFunc(withEntityM: entity, withFilePath: firmwareFilePath) { [weak self] result, progress in + // JL_OTA_RT 是 nullable closure (`JL_OTA_RT __nullable`),Swift 不接受 + // trailing closure 给 nullable closure 参数 —— 显式拼出 closure 字面量。 + let cb: JL_OTA_RT = { [weak self] result, progress in self?.onOtaCallback(result: result, progress: progress) } + server.bleMultiple.otaFunc( + withEntityM: entity, + withFilePath: firmwareFilePath, + result: cb + ) #else server?.dispatcher.send([ "type": "otaError", @@ -59,7 +66,7 @@ public class OtaFeature { #endif } - public func cancel() { + func cancel() { if !running { return } running = false server?.dispatcher.send([ diff --git a/local_plugins/device_jieli/ios/Classes/Feature/ScanFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/ScanFeature.swift index 31ed88077..3905f1d3f 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/ScanFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/ScanFeature.swift @@ -25,7 +25,7 @@ import CoreBluetooth /// exact entry point is wired we leave them null and rely on the connection /// path's BLE-only fallback (matches the Android "fallback when SDK can't /// parse" behavior). -public class ScanFeature: NSObject, CBCentralManagerDelegate { +class ScanFeature: NSObject, CBCentralManagerDelegate { private weak var server: JieliHomeServer? private weak var dispatcher: EventDispatcher? @@ -44,26 +44,26 @@ public class ScanFeature: NSObject, CBCentralManagerDelegate { // Track which addresses have been published this scan to dedupe. private var publishedIds: Set = [] - public init(dispatcher: EventDispatcher) { + init(dispatcher: EventDispatcher) { self.dispatcher = dispatcher super.init() } - public func attach(server: JieliHomeServer) { + func attach(server: JieliHomeServer) { self.server = server if centralManager == nil { centralManager = CBCentralManager(delegate: self, queue: .main) } } - public func detach() { + func detach() { stopScan() centralManager = nil } // MARK: - Public API (mirrors Android signatures) - public func startScan( + func startScan( timeoutMs: Int, nameList: [String], uuidList: [String], @@ -103,7 +103,7 @@ public class ScanFeature: NSObject, CBCentralManagerDelegate { DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(timeoutMs), execute: work) } - public func stopScan() { + func stopScan() { if let work = stopWorkItem { work.cancel(); stopWorkItem = nil } if let central = centralManager, central.state == .poweredOn { central.stopScan() @@ -120,11 +120,11 @@ public class ScanFeature: NSObject, CBCentralManagerDelegate { serviceFilters = [] } - public func isScanning() -> Bool { scanning } + func isScanning() -> Bool { scanning } // MARK: - CBCentralManagerDelegate - public func centralManagerDidUpdateState(_ central: CBCentralManager) { + func centralManagerDidUpdateState(_ central: CBCentralManager) { let on = central.state == .poweredOn dispatcher?.send([ "type": "adapterStatus", @@ -134,7 +134,7 @@ public class ScanFeature: NSObject, CBCentralManagerDelegate { if !on && scanning { stopScan() } } - public func centralManager( + func centralManager( _ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], diff --git a/local_plugins/device_jieli/ios/Classes/Feature/SpeechFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/SpeechFeature.swift index 6b3eb1329..d498118be 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/SpeechFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/SpeechFeature.swift @@ -14,27 +14,27 @@ import Foundation /// /// The MethodChannel surface is preserved so the Dart layer (which already /// expects errors here on missing devices) sees a clean `SPEECH_START_ERR`. -public class SpeechFeature { +class SpeechFeature { - public static let voiceTypePcm = 0 - public static let voiceTypeSpeex = 1 - public static let voiceTypeOpus = 2 + static let voiceTypePcm = 0 + static let voiceTypeSpeex = 1 + static let voiceTypeOpus = 2 - public static let sampleRate8k = 8 - public static let sampleRate16k = 16 + static let sampleRate8k = 8 + static let sampleRate16k = 16 - public static let vadWayDevice = 0 - public static let vadWaySdk = 1 + static let vadWayDevice = 0 + static let vadWaySdk = 1 - public static let reasonNormal = 0 - public static let reasonStop = 1 + static let reasonNormal = 0 + static let reasonStop = 1 weak var server: JieliHomeServer? init(server: JieliHomeServer) { self.server = server } - public func isRecording(address: String?) -> Bool { false } + func isRecording(address: String?) -> Bool { false } - public func start( + func start( address: String?, voiceType: Int, sampleRate: Int, @@ -45,7 +45,7 @@ public class SpeechFeature { completion(false, "speech.start not yet implemented on iOS") } - public func stop( + func stop( address: String?, reason: Int, completion: @escaping (Bool, String?) -> Void @@ -53,7 +53,7 @@ public class SpeechFeature { completion(false, "speech.stop not yet implemented on iOS") } - public func detach() { + func detach() { // No resources held while stubbed. } } diff --git a/local_plugins/device_jieli/ios/Classes/Feature/Translation/TranslationAudioBridge.swift b/local_plugins/device_jieli/ios/Classes/Feature/Translation/TranslationAudioBridge.swift index 3af7da017..ee14c7abb 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/Translation/TranslationAudioBridge.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/Translation/TranslationAudioBridge.swift @@ -3,7 +3,7 @@ import Foundation /// Bridge between a TranslationModeHandler and the outside world (Flutter /// EventChannel by default; can be replaced by host code for native-direct /// orchestration). Mirrors Android `feature/translation/TranslationAudioBridge.kt`. -public protocol TranslationAudioBridge: AnyObject { +protocol TranslationAudioBridge: AnyObject { /// Plugin → outside: one captured PCM frame from the device. func emitAudioFrame( @@ -47,14 +47,14 @@ public protocol TranslationAudioBridge: AnyObject { /// Default bridge backed by the EventDispatcher → Flutter EventChannel /// path. Mirrors Android `feature/translation/EventChannelAudioBridge.kt`. -public final class EventChannelAudioBridge: TranslationAudioBridge { +final class EventChannelAudioBridge: TranslationAudioBridge { private weak var dispatcher: EventDispatcher? /// Closure invoked when feedTranslatedAudio is called. The default impl /// routes back into TranslationFeature — same as Android's `injector`. private let injector: (Int, String, Data, TranslationAudioFormat, Bool) -> Bool - public init( + init( dispatcher: EventDispatcher, injector: @escaping (Int, String, Data, TranslationAudioFormat, Bool) -> Bool ) { @@ -62,7 +62,7 @@ public final class EventChannelAudioBridge: TranslationAudioBridge { self.injector = injector } - public func emitAudioFrame( + func emitAudioFrame( modeId: Int, streamId: String, pcm: Data, @@ -85,7 +85,7 @@ public final class EventChannelAudioBridge: TranslationAudioBridge { ]) } - public func emitTranslationResult( + func emitTranslationResult( modeId: Int, srcLang: String?, srcText: String?, @@ -104,7 +104,7 @@ public final class EventChannelAudioBridge: TranslationAudioBridge { ]) } - public func emitLog(modeId: Int, content: String) { + func emitLog(modeId: Int, content: String) { dispatcher?.send([ "type": "translationLog", "modeId": modeId, @@ -112,7 +112,7 @@ public final class EventChannelAudioBridge: TranslationAudioBridge { ]) } - public func emitError(modeId: Int, code: Int, message: String?) { + func emitError(modeId: Int, code: Int, message: String?) { dispatcher?.send([ "type": "translationError", "modeId": modeId, @@ -122,7 +122,7 @@ public final class EventChannelAudioBridge: TranslationAudioBridge { } @discardableResult - public func feedTranslatedAudio( + func feedTranslatedAudio( modeId: Int, outputStreamId: String, pcm: Data, diff --git a/local_plugins/device_jieli/ios/Classes/Feature/TranslationFeature.swift b/local_plugins/device_jieli/ios/Classes/Feature/TranslationFeature.swift index 115d4648f..ba10e16e6 100644 --- a/local_plugins/device_jieli/ios/Classes/Feature/TranslationFeature.swift +++ b/local_plugins/device_jieli/ios/Classes/Feature/TranslationFeature.swift @@ -9,7 +9,7 @@ import Foundation /// /// The `feedTranslatedAudio` / `feedTranslationResult` paths route to the /// active handler / bridge, exactly like Android. -public class TranslationFeature: NSObject { +class TranslationFeature: NSObject { weak var server: JieliHomeServer? @@ -38,7 +38,7 @@ public class TranslationFeature: NSObject { /// Replace the active bridge — used by host code that wants to keep /// audio inside native (mirrors Android `setTranslationBridge`). - public func setBridge(_ bridge: TranslationAudioBridge) { + func setBridge(_ bridge: TranslationAudioBridge) { self.bridge = bridge guard let server = server else { return } handlers = [ @@ -53,19 +53,19 @@ public class TranslationFeature: NSObject { // MARK: - Public API - public func isWorking() -> Bool { current?.isWorking ?? false } - public func currentModeId() -> Int? { + func isWorking() -> Bool { current?.isWorking ?? false } + func currentModeId() -> Int? { guard let h = current, h.isWorking else { return nil } return h.modeId } - public func currentInputStreams() -> [String] { + func currentInputStreams() -> [String] { current?.isWorking == true ? (current?.inputStreams ?? []) : [] } - public func currentOutputStreams() -> [String] { + func currentOutputStreams() -> [String] { current?.isWorking == true ? (current?.outputStreams ?? []) : [] } - public func start(modeId: Int, args: [String: Any]) throws { + func start(modeId: Int, args: [String: Any]) throws { // Match Android logic — auto-upgrade mode=3 + OPUS to mode=6 stereo when // the device supports it (and caller did not opt out). let bypassStereo = (args["bypassStereoUpgrade"] as? Bool) ?? false @@ -91,13 +91,13 @@ public class TranslationFeature: NSObject { current = handler } - public func stop() { + func stop() { current?.stop() current = nil } @discardableResult - public func feedTranslatedAudio( + func feedTranslatedAudio( streamId: String, pcm: Data, sampleRate: Int, @@ -119,7 +119,7 @@ public class TranslationFeature: NSObject { ) } - public func feedTranslationResult( + func feedTranslationResult( srcLang: String?, srcText: String?, destLang: String?, destText: String?, requestId: String? @@ -139,7 +139,7 @@ public class TranslationFeature: NSObject { /// `JLDeviceConfigTws.isSupportOpusStereo` flag when available. As a /// pragmatic default we just return `trIsPlayWithA2dp()`, matching the /// demo's `setupModeForCall` heuristic. - public func isSupportCallTranslationWithStereo(address: String?) -> Bool { + func isSupportCallTranslationWithStereo(address: String?) -> Bool { #if canImport(JL_BLEKit) guard let server = server else { return false } return server.translationCoordinator.manager?.trIsPlayWithA2dp() ?? false @@ -152,5 +152,5 @@ public class TranslationFeature: NSObject { /// dedicated handler maps to MODE_AUDIO_TRANSLATION which the demo drives /// by starting recording-and-play. Returns `false` until implemented to /// keep the Dart contract intact. - public func feedAudioFilePcm(pcm: Data, sampleRate: Int) -> Bool { false } + func feedAudioFilePcm(pcm: Data, sampleRate: Int) -> Bool { false } } diff --git a/local_plugins/device_jieli/ios/Classes/Integration/JieliNativeDevicePlugin.swift b/local_plugins/device_jieli/ios/Classes/Integration/JieliNativeDevicePlugin.swift index 4966eef30..1b04c73fb 100644 --- a/local_plugins/device_jieli/ios/Classes/Integration/JieliNativeDevicePlugin.swift +++ b/local_plugins/device_jieli/ios/Classes/Integration/JieliNativeDevicePlugin.swift @@ -19,11 +19,11 @@ import Foundation /// 3. Hand both to the registry. /// /// Until then `register()` is a no-op so the plugin still loads cleanly. -public enum JieliNativeDevicePlugin { +enum JieliNativeDevicePlugin { - public static let kVendor = "jieli" + static let kVendor = "jieli" - public static func register() { + static func register() { // TODO: when device_plugin_interface iOS gains a NativeDevicePluginRegistry, // wire the JieLi factory here, mirroring Android's // `JieliNativeDevicePlugin.register(context)`.