diff --git a/CHANGELOG.md b/CHANGELOG.md index 645006f..a479805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ **July 2026** +Each note in the list now shows a calendar-style date badge, with the time of day in the details line + +A refreshed app icon on iPhone, Mac, and Apple Watch + Transcripts now appear in their own section of a voice note, separate from your own text, with a button to insert them into it Re-transcribing a note in another language now works, and every previous transcript is kept diff --git a/Notes/Views/Components/CalendarBadge.swift b/Notes/Views/Components/CalendarBadge.swift new file mode 100644 index 0000000..3223b25 --- /dev/null +++ b/Notes/Views/Components/CalendarBadge.swift @@ -0,0 +1,53 @@ +import SwiftUI + +/// A torn-calendar-page date badge: month header over a day number and +/// weekday, used to give note rows an at-a-glance date. +struct CalendarBadge: View { + let date: Date + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + VStack(spacing: 0) { + Text(month) + .font(.system(size: 8, weight: .semibold)) + .foregroundColor(.white) + .frame(maxWidth: .infinity) + .padding(.top, 6) + .padding(.bottom, 2) + .background(Color.accentColor) + + VStack(spacing: 1) { + Text(dayNumber) + .font(.system(size: 16, weight: .bold)) + Text(dayOfWeek) + .font(.system(size: 7)) + .foregroundColor(.secondary) + } + .frame(maxWidth: .infinity) + .padding(.top, 3) + .padding(.bottom, 5) + .background(.quaternary) + } + .frame(width: 36, height: 44) + .clipShape(RoundedRectangle(cornerRadius: 5)) + .overlay( + RoundedRectangle(cornerRadius: 5) + .strokeBorder( + colorScheme == .dark ? Color.white.opacity(0.1) : Color.clear, + lineWidth: 0.5 + ) + ) + } + + private var month: String { + date.formatted(.dateTime.month(.abbreviated)).uppercased() + } + + private var dayNumber: String { + date.formatted(.dateTime.day()) + } + + private var dayOfWeek: String { + date.formatted(.dateTime.weekday(.abbreviated)).uppercased() + } +} diff --git a/Notes/Views/Notes/NoteRowView.swift b/Notes/Views/Notes/NoteRowView.swift index 4d5eb8a..596ddc8 100644 --- a/Notes/Views/Notes/NoteRowView.swift +++ b/Notes/Views/Notes/NoteRowView.swift @@ -4,35 +4,39 @@ struct NoteRowView: View { let note: NoteEntity var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(displayTitle) - .font(.body.weight(.medium)) - .lineLimit(2) + HStack(alignment: .center, spacing: 10) { + CalendarBadge(date: note.createdAt) - HStack(spacing: 4) { - if note.hasAudio { - Image(systemName: "waveform") - Text(AudioPlayerView.timeString(note.audioDuration ?? 0)) - Text("·") + VStack(alignment: .leading, spacing: 4) { + Text(displayTitle) + .font(.body.weight(.medium)) + .lineLimit(2) + + HStack(spacing: 4) { + if note.hasAudio { + Image(systemName: "waveform") + Text(AudioPlayerView.timeString(note.audioDuration ?? 0)) + Text("·") + } + Text(note.createdAt, format: .dateTime.hour().minute()) + if let place = note.context.summary { + Text("·") + Text(place) + .lineLimit(1) + } } - Text(note.createdAt, format: .dateTime.day().month().year()) - if let place = note.context.summary { - Text("·") - Text(place) + .font(.caption) + .foregroundStyle(.secondary) + + transcriptionChip + + if !note.tags.isEmpty { + Text(note.tags.map { "#\($0)" }.joined(separator: " ")) + .font(.caption) + .foregroundStyle(.tint) .lineLimit(1) } } - .font(.caption) - .foregroundStyle(.secondary) - - transcriptionChip - - if !note.tags.isEmpty { - Text(note.tags.map { "#\($0)" }.joined(separator: " ")) - .font(.caption) - .foregroundStyle(.tint) - .lineLimit(1) - } } .padding(.vertical, 2) }