// // RenderingBlockView.swift // GeminiRenderer // // Created by Shadowfacts on 7/13/20. // import SwiftUI import GeminiFormat struct RenderingBlockView: View { let block: RenderingBlock let changeURL: ((URL) -> Void)? @State var hovering = false init(block: RenderingBlock, changeURL: ((URL) -> Void)? = nil) { self.block = block self.changeURL = changeURL } @ViewBuilder var body: some View { switch block { case let .text(text): self.text(text) case let .link(url, text: linkText): self.link(url, text: linkText) case let .preformatted(text, alt: _): preformatted(text) case let .heading(text, level: level): heading(text, level: level) case let .unorderedListItem(text): unorderedListItem(text) case let .quote(text): quote(text) } } private func text(_ text: String) -> some View { Text(text) .font(.documentBody) .frame(maxWidth: .infinity, alignment: .leading) } private func link(_ url: URL, text: String?) -> some View { let text = text ?? url.absoluteString #if os(macOS) let buttonStyle = LinkButtonStyle() #elseif os(iOS) let buttonStyle = PlainButtonStyle() #endif let button: some View = Button { self.changeURL?(url) } label: { Text(verbatim: text) .font(.documentBody) .foregroundColor(hovering ? .blue : Color.blue.opacity(0.8)) .underline() .frame(maxWidth: .infinity, alignment: .leading) } .buttonStyle(buttonStyle) .onHover { hovering in self.hovering = hovering } if #available(macOS 10.16, iOS 14.0, *) { return AnyView(button.help(url.absoluteString)) } else { return AnyView(button) } } private func preformatted(_ text: String) -> some View { ScrollView(.horizontal) { Text(verbatim: text) .font(.documentBodyPreformatted) .frame(maxWidth: .infinity, alignment: .leading) } } private func heading(_ text: String, level: Document.HeadingLevel) -> some View { Text(verbatim: text) .font(level.font) .frame(maxWidth: .infinity, alignment: .leading) } private func unorderedListItem(_ text: String) -> some View { // todo: should this be .firstTextBaseline? HStack(alignment: .top, spacing: 4) { Text(verbatim: "\u{2022}") Text(verbatim: text) .font(.documentBody) Spacer() }.frame(maxWidth: .infinity, alignment: .leading) } private func quote(_ text: String) -> some View { HStack(spacing: 4) { Color.gray .frame(width: 4) Text(verbatim: text) .font(Font.documentBody.italic()) .foregroundColor(.gray) Spacer() }.frame(maxWidth: .infinity, alignment: .leading) } } struct RenderingBlockView_Previews: PreviewProvider { static var previews: some View { Group { RenderingBlockView(block: .text("Some Text")) RenderingBlockView(block: .quote("A Quote")) } } }