Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Date): Create ThreadFormatStyle #1291

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Mail/Components/ThreadCell/ThreadCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct ThreadCellDataHolder {

init(thread: Thread) {
let lastMessageNotFromSent = thread.messages.last { $0.folder?.role != .sent } ?? thread.messages.last
date = thread.date.customRelativeFormatted
date = thread.date.formatted(.thread(.list))

subject = thread.formattedSubject

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct MessageHeaderDateView: View {
let date: Date

var body: some View {
Text(date.messageHeaderRelativeFormatted)
Text(date, format: .thread(.header))
.lineLimit(1)
.layoutPriority(1)
.textStyle(.labelSecondary)
Expand Down
103 changes: 67 additions & 36 deletions MailCore/Utils/Formatters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,66 @@

import Foundation

// MARK: Date

public extension Date {
var customRelativeFormatted: String {
if self > .now {
return formatted(date: .numeric, time: .omitted)
} else if Calendar.current.isDateInToday(self) {
return formatted(date: .omitted, time: .shortened)
} else if Calendar.current.isDateInYesterday(self) {
let dateMidnight = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: self)!
return dateMidnight.formatted(.relative(presentation: .named))
} else if let lastWeek = Calendar.current.date(byAdding: .day, value: -7, to: Date()), self > lastWeek {
return formatted(.dateTime.weekday(.wide))
} else if Calendar.current.isDate(self, equalTo: .now, toGranularity: .year) {
return formatted(.dateTime.day().month())
} else {
return formatted(date: .numeric, time: .omitted)
struct ThreadFormatStyle: Foundation.FormatStyle {
// swiftlint:disable:next nesting
public enum Style: Codable, Equatable, Hashable {
case list
case header
}
}

var messageHeaderRelativeFormatted: String {
if self > .now {
return formatted(date: .numeric, time: .shortened)
} else if Calendar.current.isDateInToday(self) {
return formatted(date: .omitted, time: .shortened)
} else if Calendar.current.isDateInYesterday(self) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
dateFormatter.formattingContext = .middleOfSentence
dateFormatter.doesRelativeDateFormatting = true
return dateFormatter.string(from: self)
} else if Calendar.current.isDate(self, equalTo: .now, toGranularity: .year) {
return formatted(.dateTime.day().month().hour().minute())
} else {
return formatted(.dateTime.year().day().month().hour().minute())
private let style: Style

init(style: Style) {
self.style = style
}
}
}

public extension FormatStyle where Self == ByteCountFormatStyle {
static var defaultByteCount: ByteCountFormatStyle {
return .byteCount(style: .binary)
public func format(_ value: Date) -> String {
switch style {
case .list:
return formatToCustomRelative(value)
case .header:
return formatToMessageHeaderRelative(value)
}
}

private func formatToCustomRelative(_ date: Date) -> String {
if date > .now {
return date.formatted(date: .numeric, time: .omitted)
} else if Calendar.current.isDateInToday(date) {
return date.formatted(date: .omitted, time: .shortened)
} else if Calendar.current.isDateInYesterday(date) {
let dateMidnight = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: date)!
return dateMidnight.formatted(.relative(presentation: .named))
} else if let lastWeek = Calendar.current.date(byAdding: .day, value: -7, to: .now), date > lastWeek {
return date.formatted(.dateTime.weekday(.wide))
} else if Calendar.current.isDate(date, equalTo: .now, toGranularity: .year) {
return date.formatted(.dateTime.day().month())
} else {
return date.formatted(date: .numeric, time: .omitted)
}
}

private func formatToMessageHeaderRelative(_ date: Date) -> String {
if date > .now {
return date.formatted(date: .numeric, time: .shortened)
} else if Calendar.current.isDateInToday(date) {
return date.formatted(date: .omitted, time: .shortened)
} else if Calendar.current.isDateInYesterday(date) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
dateFormatter.formattingContext = .middleOfSentence
dateFormatter.doesRelativeDateFormatting = true
return dateFormatter.string(from: date)
} else if Calendar.current.isDate(date, equalTo: .now, toGranularity: .year) {
return date.formatted(.dateTime.day().month().hour().minute())
} else {
return date.formatted(.dateTime.year().day().month().hour().minute())
}
}
}
}

Expand All @@ -78,4 +97,16 @@ public extension FormatStyle where Self == Date.FormatStyle {
static var calendarDateTime: Date.FormatStyle {
return .dateTime.day().month().year().hour().minute()
}

static func thread(_ style: Date.ThreadFormatStyle.Style) -> Date.ThreadFormatStyle {
return .init(style: style)
}
}

// MARK: ByteCount

public extension FormatStyle where Self == ByteCountFormatStyle {
static var defaultByteCount: ByteCountFormatStyle {
return .byteCount(style: .binary)
}
}
Loading