35 lines
1.7 KiB
Swift
35 lines
1.7 KiB
Swift
import Foundation
|
|
import RDAIReaderView
|
|
|
|
/// Temporary speech content for an AI answer or summary. It deliberately uses
|
|
/// an in-memory identifier and disables progress persistence by default.
|
|
@MainActor
|
|
public final class RDAISpeechContentProvider: RDSpeechContentProvider {
|
|
private let descriptor: RDSpeechBookDescriptor
|
|
private let units: [RDSpeechTextUnit]
|
|
|
|
public init(title: String, text: String, language: String? = nil) {
|
|
let identifier = "rdai-speech-\(UUID().uuidString)"
|
|
descriptor = RDSpeechBookDescriptor(identifier: identifier, title: title)
|
|
let location = RDSpeechLocation(bookIdentifier: identifier, resourceIdentifier: "ai-result")
|
|
units = RDSpeechTextPreprocessor.makeUnits(text: text, location: location, language: language)
|
|
}
|
|
|
|
public func speechBookDescriptor() -> RDSpeechBookDescriptor { descriptor }
|
|
|
|
public func speechContentBatch(startingAt location: RDSpeechLocation?, limit: Int) async throws -> RDSpeechContentBatch {
|
|
let start = location.flatMap { requested in units.firstIndex { $0.location.textOffset >= requested.textOffset } } ?? 0
|
|
let batch = Array(units.dropFirst(start).prefix(max(1, limit)))
|
|
let nextIndex = start + batch.count
|
|
return RDSpeechContentBatch(units: batch, nextLocation: nextIndex < units.count ? units[nextIndex].location : nil)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
public extension RDSpeechReaderController {
|
|
convenience init(aiTitle: String, text: String, language: String? = nil, configuration: RDSpeechReaderConfiguration = .default) {
|
|
let provider = RDAISpeechContentProvider(title: aiTitle, text: text, language: language)
|
|
self.init(contentProvider: provider, configuration: configuration, progressStore: nil)
|
|
}
|
|
}
|