import SwiftUI // MARK: - Scripture Sheet Components struct ScriptureSheet: View { @Binding var scriptureText: String @Environment(\.dismiss) private var dismiss init(scriptureText: Binding) { self._scriptureText = scriptureText } var body: some View { NavigationStack { ScrollView { VStack(alignment: .leading, spacing: 20) { if scriptureText.isEmpty { Text("No scripture text available") .foregroundStyle(.secondary) .padding() } else { let sections = formatScriptureText(scriptureText) ForEach(Array(sections.enumerated()), id: \.offset) { index, section in VStack(alignment: .leading, spacing: 8) { // Verse text Text(section.verse) .font(.body) .lineSpacing(4) #if os(iOS) .textSelection(.enabled) #endif // Reference if !section.reference.isEmpty { Text(section.reference) .font(.caption) .fontWeight(.medium) .foregroundStyle(.secondary) .padding(.top, 4) } } .padding(.horizontal) // Add divider between sections (except last) if index < sections.count - 1 { Divider() .padding(.horizontal) } } Spacer(minLength: 20) } } .padding(.vertical) } .navigationTitle("Scripture Reading") #if os(iOS) .navigationBarTitleDisplayMode(.inline) #endif .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Done") { dismiss() } } } } .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) } private func formatScriptureText(_ text: String) -> [ScriptureSection] { // Use the Rust implementation for consistent formatting across platforms let jsonString = formatScriptureTextJson(scriptureText: text) guard let data = jsonString.data(using: .utf8), let sections = try? JSONDecoder().decode([ScriptureSection].self, from: data) else { // Fallback if JSON parsing fails return [ScriptureSection(verse: text, reference: "")] } return sections } } // MARK: - Scripture Sheet with Sermon ID (loads data automatically) struct ScriptureSheetForSermon: View { let sermonId: String @Environment(\.dismiss) private var dismiss @State private var scriptureText: String = "" @State private var isLoading = true var body: some View { NavigationStack { ScrollView { VStack(alignment: .leading, spacing: 20) { if isLoading { ProgressView("Loading scripture...") .padding() } else if scriptureText.isEmpty { Text("No scripture text available for this sermon") .foregroundStyle(.secondary) .padding() } else { let sections = formatScriptureText(scriptureText) ForEach(Array(sections.enumerated()), id: \.offset) { index, section in VStack(alignment: .leading, spacing: 8) { // Verse text Text(section.verse) .font(.body) .lineSpacing(4) #if os(iOS) .textSelection(.enabled) #endif // Reference if !section.reference.isEmpty { Text(section.reference) .font(.caption) .fontWeight(.medium) .foregroundStyle(.secondary) .padding(.top, 4) } } .padding(.horizontal) // Add divider between sections (except last) if index < sections.count - 1 { Divider() .padding(.horizontal) } } Spacer(minLength: 20) } } .padding(.vertical) } .navigationTitle("Scripture Reading") #if os(iOS) .navigationBarTitleDisplayMode(.inline) #endif .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Done") { dismiss() } } } } .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) .task { isLoading = true scriptureText = fetchScriptureVersesForSermonJson(sermonId: sermonId) isLoading = false } } private func formatScriptureText(_ text: String) -> [ScriptureSection] { // Use the Rust implementation for consistent formatting across platforms let jsonString = formatScriptureTextJson(scriptureText: text) guard let data = jsonString.data(using: .utf8), let sections = try? JSONDecoder().decode([ScriptureSection].self, from: data) else { // Fallback if JSON parsing fails return [ScriptureSection(verse: text, reference: "")] } return sections } } struct ScriptureSection: Codable { let verse: String let reference: String } // MARK: - Scripture Utilities func extractScriptureReferences(from text: String) -> String { // Use the Rust implementation for consistent parsing across platforms return extractScriptureReferencesString(scriptureText: text) } // MARK: - Share Utilities func createShareItems(for sermon: Sermon) -> [Any] { // Use the Rust implementation for consistent share text across platforms let jsonString = createSermonShareItemsJson( title: sermon.title, speaker: sermon.speaker, videoUrl: sermon.videoUrl, audioUrl: sermon.audioUrl ) guard let data = jsonString.data(using: .utf8), let shareStrings = try? JSONDecoder().decode([String].self, from: data) else { // Fallback return ["Check out this sermon: \"\(sermon.title)\" by \(sermon.speaker)"] } var items: [Any] = [] for shareString in shareStrings { if let url = URL(string: shareString), shareString.hasPrefix("http") { items.append(url) } else { items.append(shareString) } } return items }