Restore vertical scroll + line-based markdown; swipe on bottom bar; bump to 3.3
Build iOS App / Build .ipa and publish source (push) Failing after 16s
Build iOS App / Build .ipa and publish source (push) Failing after 16s
The horizontal paging ScrollView squished the markdown text and the TabView broke navigation. Revert to the plain vertical ScrollView + switch (always rendered correctly). Swipe-to-change now lives on the bottom tab bar itself (simultaneous DragGesture), so tapping tabs still works. Rewrite MarkdownText line-based: each source line renders on its own line (AttributedString collapses single newlines into spaces), with heading/bullet/code handling. Bump to 3.3.
This commit is contained in:
1 parent
221d23a6a3
commit
dd0fc84238
3 files changed
+78
-30
No files matched your search
@@ -167,6 +167,11 @@ struct OverviewTab: View {
|
||||
|
||||
/// A Text view that renders a markdown string, falling back to plain text if
|
||||
/// the markdown can't be parsed.
|
||||
///
|
||||
/// Line-based: each source line renders on its own line (AttributedString
|
||||
/// collapses single newlines into spaces, which squishes PR bodies that use
|
||||
/// one-line-per-key formatting). Handles headings, bullets, and code fences;
|
||||
/// inline formatting (bold, italic, links, inline code) via AttributedString.
|
||||
struct MarkdownText: View {
|
||||
let markdown: String
|
||||
|
||||
@@ -175,12 +180,55 @@ struct MarkdownText: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if let attributed = try? AttributedString(markdown: markdown) {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
let lines = markdown.components(separatedBy: "\n")
|
||||
var inCodeBlock = false
|
||||
ForEach(Array(lines.enumerated()), id: \.offset) { _, line in
|
||||
if line.hasPrefix("```") {
|
||||
inCodeBlock.toggle()
|
||||
} else if inCodeBlock {
|
||||
Text(line)
|
||||
.font(.caption.monospaced())
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(4)
|
||||
.background(Color(.secondarySystemBackground))
|
||||
} else if line.hasPrefix("# ") || line.hasPrefix("## ") || line.hasPrefix("### ") {
|
||||
heading(line)
|
||||
} else if line.hasPrefix("- ") || line.hasPrefix("* ") {
|
||||
bullet(line)
|
||||
} else if line.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
Spacer(minLength: 4)
|
||||
} else {
|
||||
inline(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func heading(_ line: String) -> some View {
|
||||
let level = line.prefix(while: { $0 == "#" }).count
|
||||
let text = line.dropFirst(level).trimmingCharacters(in: .whitespaces)
|
||||
return Text(text)
|
||||
.font(level == 1 ? .title2.bold() : level == 2 ? .title3.bold() : .headline)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func bullet(_ line: String) -> some View {
|
||||
HStack(alignment: .top, spacing: 6) {
|
||||
Text("•")
|
||||
inline(String(line.dropFirst(2)))
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
private func inline(_ text: String) -> some View {
|
||||
if let attributed = try? AttributedString(markdown: text) {
|
||||
Text(attributed)
|
||||
.font(.callout)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
} else {
|
||||
Text(markdown)
|
||||
Text(text)
|
||||
.font(.callout)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user