Skip to content

Commit cf81b86

Browse files
dcalhounclaude
andauthored
fix: Use a literal ellipsis in the Reader "view more" string (#26122)
* style: Format ReaderPostHeaderView with swift-format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R5NVRDoua98jmoS3sv6khR * fix: Use a literal ellipsis in the Reader "view more" string genstrings doesn't understand Swift's \u{2026} escape and copies it verbatim into Localizable.strings, where the .strings parser drops the backslash. The excerpt then showed "u{2026}view more", and translators copied the broken prefix into every locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R5NVRDoua98jmoS3sv6khR --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3a862a5 commit cf81b86

1 file changed

Lines changed: 120 additions & 68 deletions

File tree

‎Modules/Sources/WordPressReader/Detail/ReaderPostHeaderView.swift‎

Lines changed: 120 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public final class ReaderPostHeaderView: UIView {
174174
authorRow,
175175
featuredImageView,
176176
excerptLabel,
177-
separator,
177+
separator
178178
])
179179
stack.setCustomSpacing(9, after: separator)
180180
stack.axis = .vertical
@@ -276,14 +276,16 @@ public final class ReaderPostHeaderView: UIView {
276276

277277
private func setupView() {
278278
addSubview(mainStack)
279-
mainStack.pinEdges(insets: UIEdgeInsets(top: Constants.padding, left: Constants.padding, bottom: 20, right: Constants.padding))
279+
mainStack.pinEdges(
280+
insets: UIEdgeInsets(top: Constants.padding, left: Constants.padding, bottom: 20, right: Constants.padding)
281+
)
280282

281283
mainStack.setCustomSpacing(9, after: headerRow)
282284
mainStack.setCustomSpacing(12, after: featuredImageView)
283285

284286
avatarSizeConstraints = [
285287
avatarImageView.widthAnchor.constraint(equalToConstant: Constants.avatarSize),
286-
avatarImageView.heightAnchor.constraint(equalToConstant: Constants.avatarSize),
288+
avatarImageView.heightAnchor.constraint(equalToConstant: Constants.avatarSize)
287289
]
288290
NSLayoutConstraint.activate(avatarSizeConstraints)
289291

@@ -307,7 +309,9 @@ public final class ReaderPostHeaderView: UIView {
307309
excerptLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(excerptTapped)))
308310

309311
featuredImageView.isUserInteractionEnabled = true
310-
featuredImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(featuredImageTapped)))
312+
featuredImageView.addGestureRecognizer(
313+
UITapGestureRecognizer(target: self, action: #selector(featuredImageTapped))
314+
)
311315

312316
apply(.standard)
313317
}
@@ -356,7 +360,10 @@ public final class ReaderPostHeaderView: UIView {
356360
if isExcerptExpanded, let text = fullExcerptText {
357361
let font = displaySettings.font(with: .callout)
358362
let textColor = displaySettings.color.secondaryForeground
359-
excerptLabel.attributedText = NSAttributedString(string: text, attributes: [.font: font, .foregroundColor: textColor])
363+
excerptLabel.attributedText = NSAttributedString(
364+
string: text,
365+
attributes: [.font: font, .foregroundColor: textColor]
366+
)
360367
} else {
361368
updateExcerptTruncation()
362369
}
@@ -404,7 +411,10 @@ public final class ReaderPostHeaderView: UIView {
404411

405412
private func updateFeaturedImageAspectRatio(_ ratio: CGFloat) {
406413
featuredImageAspectConstraint?.isActive = false
407-
let constraint = featuredImageView.heightAnchor.constraint(equalTo: featuredImageView.widthAnchor, multiplier: ratio)
414+
let constraint = featuredImageView.heightAnchor.constraint(
415+
equalTo: featuredImageView.widthAnchor,
416+
multiplier: ratio
417+
)
408418
constraint.isActive = true
409419
featuredImageAspectConstraint = constraint
410420
}
@@ -441,12 +451,14 @@ public final class ReaderPostHeaderView: UIView {
441451
let maxHeight = font.lineHeight * CGFloat(Constants.excerptMaxLines) + 1
442452

443453
func isEnoughSpace(for string: String, maxHeight: CGFloat) -> Bool {
444-
let height = (string as NSString).boundingRect(
445-
with: CGSize(width: availableWidth, height: .greatestFiniteMagnitude),
446-
options: [.usesLineFragmentOrigin, .usesFontLeading],
447-
attributes: atttributes,
448-
context: nil
449-
).height
454+
let height = (string as NSString)
455+
.boundingRect(
456+
with: CGSize(width: availableWidth, height: .greatestFiniteMagnitude),
457+
options: [.usesLineFragmentOrigin, .usesFontLeading],
458+
attributes: atttributes,
459+
context: nil
460+
)
461+
.height
450462
return height <= maxHeight
451463
}
452464

@@ -474,10 +486,13 @@ public final class ReaderPostHeaderView: UIView {
474486
let trimmed = String(text.prefix(bestCut)).trimmingCharacters(in: .whitespacesAndNewlines)
475487
let result = NSMutableAttributedString(string: trimmed, attributes: atttributes)
476488
result.append(
477-
NSAttributedString(string: suffix, attributes: [
478-
.font: font.withWeight(.regular),
479-
.foregroundColor: displaySettings.color.foreground,
480-
])
489+
NSAttributedString(
490+
string: suffix,
491+
attributes: [
492+
.font: font.withWeight(.regular),
493+
.foregroundColor: displaySettings.color.foreground
494+
]
495+
)
481496
)
482497
excerptLabel.attributedText = result
483498
}
@@ -530,9 +545,10 @@ private enum Strings {
530545
comment: "Button in the reader post header showing the user is subscribed to the site"
531546
)
532547

548+
// Use a literal ellipsis: genstrings copies Swift `\u{…}` escapes verbatim into Localizable.strings.
533549
static let viewMore = AppLocalizedString(
534550
"reader.post.header.viewMore",
535-
value: "\u{2026}view more",
551+
value: "…view more",
536552
comment: "Appended to the truncated excerpt in the reader post header to indicate more content is available"
537553
)
538554

@@ -545,82 +561,118 @@ private enum Strings {
545561
static let authorAccessibilityHint = AppLocalizedString(
546562
"reader.post.header.author.a11yHint",
547563
value: "Views the author's profile",
548-
comment: "Accessibility hint for the author row in the reader post header. Tapping it shows the author's profile."
564+
comment:
565+
"Accessibility hint for the author row in the reader post header. Tapping it shows the author's profile."
549566
)
550567
}
551568

552569
// MARK: - Preview
553570

554571
@available(iOS 17, *)
555572
#Preview("Full Header") {
556-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
557-
siteName: "Automattic Design",
558-
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
559-
authorName: "Roosmarijn van Kessel",
560-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
561-
dateString: "Dec 18, 2025 at 3:30 PM",
562-
featuredImageURL: URL(string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024"),
563-
excerpt: "Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy."
564-
)))
573+
UINavigationController(
574+
rootViewController: ReaderPostHeaderPreviewController(
575+
viewModel: .init(
576+
siteName: "Automattic Design",
577+
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
578+
authorName: "Roosmarijn van Kessel",
579+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
580+
dateString: "Dec 18, 2025 at 3:30 PM",
581+
featuredImageURL: URL(
582+
string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024"
583+
),
584+
excerpt:
585+
"Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy."
586+
)
587+
)
588+
)
565589
}
566590

567591
@available(iOS 17, *)
568592
#Preview("No Featured Image") {
569-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
570-
siteName: "Automattic Design",
571-
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
572-
authorName: "Roosmarijn van Kessel",
573-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
574-
dateString: "Dec 18, 2025 at 3:30 PM",
575-
excerpt: "Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy."
576-
)))
593+
UINavigationController(
594+
rootViewController: ReaderPostHeaderPreviewController(
595+
viewModel: .init(
596+
siteName: "Automattic Design",
597+
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
598+
authorName: "Roosmarijn van Kessel",
599+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
600+
dateString: "Dec 18, 2025 at 3:30 PM",
601+
excerpt:
602+
"Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy."
603+
)
604+
)
605+
)
577606
}
578607

579608
@available(iOS 17, *)
580609
#Preview("No Excerpt") {
581-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
582-
siteName: "Automattic Design",
583-
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
584-
authorName: "Roosmarijn van Kessel",
585-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
586-
dateString: "Dec 18, 2025 at 3:30 PM",
587-
featuredImageURL: URL(string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024")
588-
)))
610+
UINavigationController(
611+
rootViewController: ReaderPostHeaderPreviewController(
612+
viewModel: .init(
613+
siteName: "Automattic Design",
614+
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
615+
authorName: "Roosmarijn van Kessel",
616+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
617+
dateString: "Dec 18, 2025 at 3:30 PM",
618+
featuredImageURL: URL(
619+
string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024"
620+
)
621+
)
622+
)
623+
)
589624
}
590625

591626
@available(iOS 17, *)
592627
#Preview("Long Excerpt") {
593-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
594-
siteName: "Automattic Design",
595-
postTitle: "A Very Long Title That Spans Multiple Lines to Test How the Layout Handles Wrapping Text in the Header",
596-
authorName: "Roosmarijn van Kessel",
597-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
598-
dateString: "Dec 18, 2025 at 3:30 PM",
599-
featuredImageURL: URL(string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024"),
600-
excerpt: "Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy. Her work has been featured in numerous publications and exhibitions across Europe and the Americas. She specializes in editorial illustration, children's books, and cultural event posters, bringing a unique blend of traditional and contemporary techniques to every project she undertakes."
601-
)))
628+
UINavigationController(
629+
rootViewController: ReaderPostHeaderPreviewController(
630+
viewModel: .init(
631+
siteName: "Automattic Design",
632+
postTitle:
633+
"A Very Long Title That Spans Multiple Lines to Test How the Layout Handles Wrapping Text in the Header",
634+
authorName: "Roosmarijn van Kessel",
635+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
636+
dateString: "Dec 18, 2025 at 3:30 PM",
637+
featuredImageURL: URL(
638+
string: "https://automattic.design/wp-content/uploads/2025/12/a8ch25_zoom-bg-1.png?w=1024"
639+
),
640+
excerpt:
641+
"Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience. She studied Fine Arts in Salamanca and Kassel (Germany), and recently completed an artist residency in Washington, DC, through a program of the Spanish Embassy. Her work has been featured in numerous publications and exhibitions across Europe and the Americas. She specializes in editorial illustration, children's books, and cultural event posters, bringing a unique blend of traditional and contemporary techniques to every project she undertakes."
642+
)
643+
)
644+
)
602645
}
603646

604647
@available(iOS 17, *)
605648
#Preview("Portrait Image") {
606-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
607-
siteName: "Automattic Design",
608-
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
609-
authorName: "Roosmarijn van Kessel",
610-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
611-
dateString: "Dec 18, 2025 at 3:30 PM",
612-
featuredImageURL: URL(string: "https://automattic.design/wp-content/uploads/2025/12/aecc_stars.png"),
613-
excerpt: "Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience."
614-
)))
649+
UINavigationController(
650+
rootViewController: ReaderPostHeaderPreviewController(
651+
viewModel: .init(
652+
siteName: "Automattic Design",
653+
postTitle: "Drawing the holiday spirit — Interviewing Cinta Arribas",
654+
authorName: "Roosmarijn van Kessel",
655+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
656+
dateString: "Dec 18, 2025 at 3:30 PM",
657+
featuredImageURL: URL(string: "https://automattic.design/wp-content/uploads/2025/12/aecc_stars.png"),
658+
excerpt:
659+
"Based in a small city in Northern Spain, Cinta Arribas is an illustrator and visual artist with over ten years of professional experience."
660+
)
661+
)
662+
)
615663
}
616664

617665
@available(iOS 17, *)
618666
#Preview("Minimal") {
619-
UINavigationController(rootViewController: ReaderPostHeaderPreviewController(viewModel: .init(
620-
siteName: "Blog",
621-
postTitle: "Hello World",
622-
authorName: "admin",
623-
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
624-
dateString: "Mar 1, 2026"
625-
)))
667+
UINavigationController(
668+
rootViewController: ReaderPostHeaderPreviewController(
669+
viewModel: .init(
670+
siteName: "Blog",
671+
postTitle: "Hello World",
672+
authorName: "admin",
673+
authorAvatarURL: URL(string: "https://picsum.photos/id/237/120/120.jpg"),
674+
dateString: "Mar 1, 2026"
675+
)
676+
)
677+
)
626678
}

0 commit comments

Comments
 (0)