97 lines
2.7 KiB
Swift
97 lines
2.7 KiB
Swift
import SwiftUI
|
|
|
|
struct ReaderView: View {
|
|
@StateObject private var viewModel: ReaderViewModel
|
|
|
|
init(item: BookItem) {
|
|
_viewModel = StateObject(wrappedValue: ReaderViewModel(book: item))
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
Text(viewModel.book.title)
|
|
.font(.title2.weight(.semibold))
|
|
|
|
modelSection
|
|
|
|
Divider()
|
|
|
|
parsingSection
|
|
|
|
Spacer()
|
|
}
|
|
.padding(20)
|
|
.navigationTitle("Reader")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
}
|
|
|
|
private var modelSection: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("Kokoro Model")
|
|
.font(.headline)
|
|
Text(modelStatusText)
|
|
.foregroundStyle(.secondary)
|
|
|
|
switch viewModel.modelDownloadState {
|
|
case .idle, .failed:
|
|
Button("Download Model") {
|
|
viewModel.downloadModel()
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
case .downloading:
|
|
ProgressView(value: viewModel.modelDownloadProgress)
|
|
case .completed:
|
|
EmptyView()
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.padding(16)
|
|
.background(.thinMaterial)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
}
|
|
|
|
private var parsingSection: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("EPUB Parsing")
|
|
.font(.headline)
|
|
Text(parsingStatusText)
|
|
.foregroundStyle(.secondary)
|
|
|
|
Button("Parse EPUB") {
|
|
viewModel.parseBook()
|
|
}
|
|
.buttonStyle(.bordered)
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.padding(16)
|
|
.background(.thinMaterial)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
}
|
|
|
|
private var modelStatusText: String {
|
|
switch viewModel.modelDownloadState {
|
|
case .idle:
|
|
return "Model not downloaded"
|
|
case .downloading(let message):
|
|
return message
|
|
case .completed:
|
|
return "Model ready"
|
|
case .failed(let message):
|
|
return "Download failed: \(message)"
|
|
}
|
|
}
|
|
|
|
private var parsingStatusText: String {
|
|
switch viewModel.preparationState {
|
|
case .idle:
|
|
return "Ready to parse"
|
|
case .parsing:
|
|
return "Parsing EPUB"
|
|
case .ready(let count):
|
|
return "Parsed \(count) chapters"
|
|
case .failed(let message):
|
|
return "Parsing failed: \(message)"
|
|
}
|
|
}
|
|
}
|