Commit b5af561d68
b5af561d68e7535726b79d4ceec0d0a45abf0042
parent: a5073a1fa1
Unsigned
cmc <hello@cleberg.net> · 2026-03-19 00:52 UTC
use native markdown rendering for settings bio
Layout: unified · split
Hutch.xcodeproj/project.pbxproj
+4 −4
| @@ -363,7 +363,7 @@ |
| 363 | 363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 364 | 364 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; |
| 365 | 365 | CODE_SIGN_STYLE = Automatic; |
| 366 | | CURRENT_PROJECT_VERSION = 1; |
| 366 | CURRENT_PROJECT_VERSION = 2; |
| 367 | 367 | DEVELOPMENT_TEAM = ZCNAX3VL9D; |
| 368 | 368 | ENABLE_PREVIEWS = YES; |
| 369 | 369 | GENERATE_INFOPLIST_FILE = YES; |
| @@ -380,7 +380,7 @@ |
| 380 | 380 | "$(inherited)", |
| 381 | 381 | "@executable_path/Frameworks", |
| 382 | 382 | ); |
| 383 | | MARKETING_VERSION = 1.0; |
| 383 | MARKETING_VERSION = 1.2; |
| 384 | 384 | PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; |
| 385 | 385 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 386 | 386 | STRING_CATALOG_GENERATE_SYMBOLS = YES; |
| @@ -399,7 +399,7 @@ |
| 399 | 399 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 400 | 400 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; |
| 401 | 401 | CODE_SIGN_STYLE = Automatic; |
| 402 | | CURRENT_PROJECT_VERSION = 1; |
| 402 | CURRENT_PROJECT_VERSION = 2; |
| 403 | 403 | DEVELOPMENT_TEAM = ZCNAX3VL9D; |
| 404 | 404 | ENABLE_PREVIEWS = YES; |
| 405 | 405 | GENERATE_INFOPLIST_FILE = YES; |
| @@ -416,7 +416,7 @@ |
| 416 | 416 | "$(inherited)", |
| 417 | 417 | "@executable_path/Frameworks", |
| 418 | 418 | ); |
| 419 | | MARKETING_VERSION = 1.0; |
| 419 | MARKETING_VERSION = 1.2; |
| 420 | 420 | PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; |
| 421 | 421 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 422 | 422 | STRING_CATALOG_GENERATE_SYMBOLS = YES; |
Hutch/Views/Settings/SettingsView.swift
+26 −7
| @@ -1,6 +1,10 @@ |
| 1 | 1 | import PhotosUI |
| 2 | 2 | import SwiftUI |
| 3 | 3 | |
| 4 | private let settingsBioMarkdownOptions = AttributedString.MarkdownParsingOptions( |
| 5 | interpretedSyntax: .inlineOnlyPreservingWhitespace |
| 6 | ) |
| 7 | |
| 4 | 8 | struct SettingsView: View { |
| 5 | 9 | @Environment(AppState.self) private var appState |
| 6 | 10 | @Environment(\.colorScheme) private var colorScheme |
| @@ -163,13 +167,7 @@ struct SettingsView: View { |
| 163 | 167 | Text("Bio") |
| 164 | 168 | .font(.caption) |
| 165 | 169 | .foregroundStyle(.secondary) |
| 166 | | RenderedMarkupContentView( |
| 167 | | content: .markdown(bio), |
| 168 | | readmePath: nil, |
| 169 | | colorScheme: colorScheme, |
| 170 | | ownerCanonicalName: "", |
| 171 | | repositoryName: "" |
| 172 | | ) |
| 170 | SettingsBioView(markdown: bio) |
| 173 | 171 | } |
| 174 | 172 | } |
| 175 | 173 | |
| @@ -424,6 +422,27 @@ struct SettingsView: View { |
| 424 | 422 | } |
| 425 | 423 | } |
| 426 | 424 | |
| 425 | private struct SettingsBioView: View { |
| 426 | let markdown: String |
| 427 | |
| 428 | var body: some View { |
| 429 | Text(settingsBioAttributedString(markdown)) |
| 430 | .frame(maxWidth: .infinity, alignment: .leading) |
| 431 | .tint(.accentColor) |
| 432 | .textSelection(.enabled) |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | func settingsBioAttributedString(_ markdown: String) -> AttributedString { |
| 437 | guard let attributed = try? AttributedString( |
| 438 | markdown: markdown, |
| 439 | options: settingsBioMarkdownOptions |
| 440 | ) else { |
| 441 | return AttributedString(markdown) |
| 442 | } |
| 443 | return attributed |
| 444 | } |
| 445 | |
| 427 | 446 | // MARK: - Edit Profile Sheet |
| 428 | 447 | |
| 429 | 448 | private struct EditProfileSheet: View { |
HutchTests/SettingsViewTests.swift
added
+22
| @@ -0,0 +1,22 @@ |
| 1 | import Foundation |
| 2 | import Testing |
| 3 | @testable import Hutch |
| 4 | |
| 5 | struct SettingsViewTests { |
| 6 | |
| 7 | @Test |
| 8 | @MainActor |
| 9 | func settingsBioAttributedStringPreservesInlineMarkdown() { |
| 10 | let attributed = settingsBioAttributedString("Hello **world** and [link](https://example.com)") |
| 11 | |
| 12 | #expect(String(attributed.characters).contains("Hello world and link")) |
| 13 | } |
| 14 | |
| 15 | @Test |
| 16 | @MainActor |
| 17 | func settingsBioAttributedStringFallsBackForInvalidMarkdown() { |
| 18 | let attributed = settingsBioAttributedString("[broken") |
| 19 | |
| 20 | #expect(String(attributed.characters) == "[broken") |
| 21 | } |
| 22 | } |