import Foundation // MARK: - String helpers for display purposes extension String { /// Strips trailing relative-date suffixes (e.g. "2 years ago", "3 days ago") /// that may be embedded in chapter titles coming from older scraped records. func strippingTrailingDate() -> String { let units = ["second", "minute", "hour", "day", "week", "month", "year"] let lower = self.lowercased() for unit in units { for suffix in [unit + "s ago", unit + " ago"] { guard let suffixRange = lower.range(of: suffix, options: .backwards) else { continue } // Walk backwards past whitespace to find the numeric token let before = String(self[self.startIndex ..< suffixRange.lowerBound]) let trimmed = before.trimmingCharacters(in: .whitespaces) // Find start of last word (should be a number) if let spaceIdx = trimmed.lastIndex(of: " ") { let potentialNum = String(trimmed[trimmed.index(after: spaceIdx)...]) if Int(potentialNum) != nil { return String(trimmed[trimmed.startIndex ..< spaceIdx]) .trimmingCharacters(in: .whitespaces) } } else if Int(trimmed) != nil { // The entire string is just a number + "ago" return "" } } } return self } } // MARK: - App-wide layout constants enum AppLayout { /// Height of the persistent mini-player bar: /// 12pt vertical padding (top) + 56pt cover height + 12pt vertical padding (bottom) + 12pt horizontal margin. static let miniPlayerBarHeight: CGFloat = 92 }