171 lines
4.4 KiB
Swift
171 lines
4.4 KiB
Swift
import SwiftUI
|
|
|
|
final class Post: ObservableObject {
|
|
|
|
let id: Int
|
|
|
|
@Published
|
|
var isDraft: Bool
|
|
|
|
@Published
|
|
var startDate: Date
|
|
|
|
@Published
|
|
var hasEndDate: Bool
|
|
|
|
@Published
|
|
var endDate: Date
|
|
|
|
@Published
|
|
var tags: [Tag]
|
|
|
|
let title: LocalizedText
|
|
|
|
let text: LocalizedText
|
|
|
|
var images: [ImageResource]
|
|
|
|
/// The page linked to by this post
|
|
@Published
|
|
var linkedPage: Page?
|
|
|
|
init(id: Int,
|
|
isDraft: Bool = false,
|
|
startDate: Date,
|
|
endDate: Date? = nil,
|
|
title: LocalizedText,
|
|
text: LocalizedText,
|
|
tags: [Tag],
|
|
images: [ImageResource]) {
|
|
self.id = id
|
|
self.isDraft = isDraft
|
|
self.startDate = startDate
|
|
self.hasEndDate = endDate != nil
|
|
self.endDate = endDate ?? startDate
|
|
self.title = title
|
|
self.text = text
|
|
self.tags = tags
|
|
self.images = images
|
|
}
|
|
}
|
|
|
|
extension Post: Identifiable {
|
|
|
|
}
|
|
|
|
extension Post: Equatable {
|
|
|
|
static func == (lhs: Post, rhs: Post) -> Bool {
|
|
lhs.id == rhs.id
|
|
}
|
|
}
|
|
|
|
extension Post: Hashable {
|
|
|
|
func hash(into hasher: inout Hasher) {
|
|
hasher.combine(id)
|
|
}
|
|
}
|
|
|
|
|
|
// MARK: Feed entry
|
|
|
|
extension Post {
|
|
|
|
private static let englishDate: DateFormatter = {
|
|
let df = DateFormatter()
|
|
df.locale = .init(identifier: "en")
|
|
df.dateFormat = "d. MMMM yyyy"
|
|
return df
|
|
}()
|
|
|
|
private static let germanDate: DateFormatter = {
|
|
let df = DateFormatter()
|
|
df.locale = .init(identifier: "de")
|
|
df.dateFormat = "d. MMMM yyyy"
|
|
return df
|
|
}()
|
|
|
|
private static let englishDayAndMonth: DateFormatter = {
|
|
let df = DateFormatter()
|
|
df.locale = .init(identifier: "en")
|
|
df.dateFormat = "d. MMMM"
|
|
return df
|
|
}()
|
|
|
|
private static let germanDayAndMonth: DateFormatter = {
|
|
let df = DateFormatter()
|
|
df.locale = .init(identifier: "de")
|
|
df.dateFormat = "d. MMMM"
|
|
return df
|
|
}()
|
|
|
|
private static let day: DateFormatter = {
|
|
let df = DateFormatter()
|
|
df.dateFormat = "d."
|
|
return df
|
|
}()
|
|
|
|
private static func dayAndMonth(of date: Date, in language: ContentLanguage) -> String {
|
|
switch language {
|
|
case .english: return englishDayAndMonth.string(from: date)
|
|
case .german: return germanDayAndMonth.string(from: date)
|
|
}
|
|
}
|
|
|
|
private static func dateString(for date: Date, in language: ContentLanguage) -> String {
|
|
switch language {
|
|
case .english: return englishDate.string(from: date)
|
|
case .german: return germanDate.string(from: date)
|
|
}
|
|
}
|
|
|
|
private func datePrefixString(in language: ContentLanguage) -> String {
|
|
guard Calendar.current.isDate(startDate, equalTo: endDate, toGranularity: .year) else {
|
|
// Different year, return full string
|
|
return startDate.formatted(date: .long, time: .omitted)
|
|
}
|
|
guard Calendar.current.isDate(startDate, equalTo: endDate, toGranularity: .month) else {
|
|
// Different month
|
|
return Post.dayAndMonth(of: startDate, in: language)
|
|
}
|
|
|
|
return Post.day.string(from: startDate)
|
|
}
|
|
|
|
func dateText(in language: ContentLanguage) -> String {
|
|
guard hasEndDate else {
|
|
return Post.dateString(for: startDate, in: language)
|
|
}
|
|
let endText = Post.dateString(for: endDate, in: language)
|
|
return "\(datePrefixString(in: language)) - \(endText)"
|
|
}
|
|
|
|
private func paragraphs(in language: ContentLanguage) -> [String] {
|
|
text
|
|
.getText(for: language)
|
|
.components(separatedBy: "\n")
|
|
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
|
.filter { $0 != "" }
|
|
}
|
|
|
|
func linkToPageInFeed(for language: ContentLanguage) -> FeedEntryData.Link? {
|
|
nil //.init(url: <#T##String#>, text: <#T##String#>)
|
|
}
|
|
|
|
func feedEntry(for language: ContentLanguage) -> FeedEntryData {
|
|
.init(
|
|
entryId: "\(id)",
|
|
title: title.getText(for: language),
|
|
textAboveTitle: dateText(in: language),
|
|
link: linkToPageInFeed(for: language),
|
|
tags: tags.map { $0.data(in: language) },
|
|
text: paragraphs(in: language),
|
|
images: images.map { $0.feedEntryImage(for: language) })
|
|
}
|
|
|
|
var displayImages: [Image] {
|
|
images.map { $0.imageToDisplay }
|
|
}
|
|
}
|