Skip to content

Commit c44e4de

Browse files
authored
fix: fallback notification icon, updates timestamps on view refresh (#161)
1 parent d4d31d3 commit c44e4de

6 files changed

Lines changed: 149 additions & 90 deletions

File tree

Splajompy/Notifications/MockNotificationService.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
5959
facets: [
6060
Facet(type: "mention", userId: 25, indexStart: 0, indexEnd: 5)
6161
],
62-
notificationType: .like,
62+
notificationType: "like",
6363
post: Post(
6464
postId: 2001,
6565
userId: 6,
@@ -85,7 +85,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
8585
facets: [
8686
Facet(type: "mention", userId: 120, indexStart: 0, indexEnd: 11)
8787
],
88-
notificationType: .comment,
88+
notificationType: "comment",
8989
post: Post(
9090
postId: 2002,
9191
userId: 6,
@@ -117,7 +117,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
117117
facets: [
118118
Facet(type: "mention", userId: 6, indexStart: 0, indexEnd: 7)
119119
],
120-
notificationType: .mention,
120+
notificationType: "mention",
121121
post: Post(
122122
postId: 2003,
123123
userId: 1,
@@ -145,7 +145,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
145145
facets: [
146146
Facet(type: "mention", userId: 103, indexStart: 0, indexEnd: 11)
147147
],
148-
notificationType: .like,
148+
notificationType: "like",
149149
post: Post(
150150
postId: 2004,
151151
userId: 15,
@@ -177,7 +177,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
177177
facets: [
178178
Facet(type: "mention", userId: 112, indexStart: 0, indexEnd: 9)
179179
],
180-
notificationType: .like,
180+
notificationType: "like",
181181
post: Post(
182182
postId: 2001,
183183
userId: 6,
@@ -203,7 +203,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
203203
facets: [
204204
Facet(type: "mention", userId: 97, indexStart: 0, indexEnd: 6)
205205
],
206-
notificationType: .comment,
206+
notificationType: "comment",
207207
post: Post(
208208
postId: 2005,
209209
userId: 30,
@@ -233,7 +233,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
233233
imageWidth: 0,
234234
imageHeight: 0,
235235
facets: nil,
236-
notificationType: .announcement,
236+
notificationType: "announcement",
237237
post: nil,
238238
comment: nil
239239
),
@@ -253,7 +253,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
253253
facets: [
254254
Facet(type: "mention", userId: 113, indexStart: 0, indexEnd: 5)
255255
],
256-
notificationType: .announcement,
256+
notificationType: "announcement",
257257
post: nil,
258258
comment: nil
259259
),
@@ -292,7 +292,7 @@ class MockNotificationService: @unchecked Sendable, NotificationServiceProtocol
292292
imageWidth: 0,
293293
imageHeight: 0,
294294
facets: nil,
295-
notificationType: .comment,
295+
notificationType: "comment",
296296
post: nil,
297297
comment: nil
298298
)

Splajompy/Notifications/NotificationIcon.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import SwiftUI
22

33
struct NotificationIcon {
4-
private static func iconName(for notificationType: NotificationType) -> String {
4+
private static func iconName(for notificationType: String) -> String {
55
switch notificationType {
6-
case .like:
6+
case "like":
77
return "heart"
8-
case .comment:
8+
case "comment":
99
return "bubble.middle.bottom"
10-
case .announcement:
10+
case "announcement":
1111
return "megaphone"
12-
case .mention:
12+
case "mention":
1313
return "at"
14-
case .none:
14+
default:
1515
return "bell"
1616
}
1717
}
1818

19-
static func icon(for notificationType: NotificationType) -> some View {
19+
static func icon(for notificationType: String) -> some View {
2020
Image(systemName: iconName(for: notificationType))
2121
}
2222

Splajompy/Notifications/NotificationRepository.swift

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
import Foundation
22

3-
enum NotificationType: String, Decodable, CaseIterable {
4-
case none = "default"
5-
case like = "like"
6-
case comment = "comment"
7-
case announcement = "announcement"
8-
case mention = "mention"
9-
}
10-
113
struct Notification: Identifiable, Decodable, Equatable {
124
let notificationId: Int
135
let userId: Int
@@ -21,7 +13,7 @@ struct Notification: Identifiable, Decodable, Equatable {
2113
let imageWidth: Int32?
2214
let imageHeight: Int32?
2315
let facets: [Facet]?
24-
let notificationType: NotificationType
16+
let notificationType: String
2517

2618
var post: Post?
2719
var comment: Comment?
@@ -41,17 +33,6 @@ struct Notification: Identifiable, Decodable, Equatable {
4133
)
4234
}
4335

44-
var relativeDate: String {
45-
let decoder = ISO8601DateFormatter()
46-
decoder.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
47-
48-
let formatter = RelativeDateTimeFormatter()
49-
formatter.unitsStyle = .full
50-
51-
let date = decoder.date(from: self.createdAt) ?? Date()
52-
return formatter.localizedString(for: date, relativeTo: Date())
53-
}
54-
5536
static func == (lhs: Notification, rhs: Notification) -> Bool {
5637
return lhs.notificationId == rhs.notificationId
5738
}

Splajompy/Notifications/NotificationRow.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ import SwiftUI
22

33
struct NotificationRow: View {
44
let notification: Notification
5+
let refreshId: UUID
6+
7+
private func relativeDate(from createdAt: String) -> String {
8+
let date = sharedISO8601Formatter.date(from: createdAt) ?? Date()
9+
return sharedRelativeDateTimeFormatter.localizedString(for: date, relativeTo: Date())
10+
}
511

612
var body: some View {
713
Group {
@@ -25,7 +31,7 @@ struct NotificationRow: View {
2531
VStack(alignment: .leading, spacing: 4) {
2632
ContentTextView(attributedText: notification.richContent)
2733

28-
Text(notification.relativeDate)
34+
Text(relativeDate(from: notification.createdAt))
2935
.font(.caption)
3036
.foregroundColor(.secondary)
3137
}

Splajompy/Notifications/NotificationsView.swift

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import SwiftUI
33
struct NotificationsView: View {
44
@StateObject private var viewModel = ViewModel()
55
@EnvironmentObject private var authManager: AuthManager
6+
@State private var refreshId = UUID()
67

78
var body: some View {
89
Group {
@@ -72,7 +73,7 @@ struct NotificationsView: View {
7273
if !unreadNotifications.isEmpty {
7374
Section {
7475
ForEach(unreadNotifications, id: \.notificationId) { notification in
75-
NotificationRow(notification: notification)
76+
NotificationRow(notification: notification, refreshId: refreshId)
7677
.swipeActions(edge: .leading) {
7778
Button {
7879
Task {
@@ -85,6 +86,15 @@ struct NotificationsView: View {
8586
}
8687
}
8788
.tint(.blue)
89+
.onAppear {
90+
if notification.notificationId
91+
== unreadNotifications.last?.notificationId
92+
{
93+
Task {
94+
await viewModel.loadMoreUnreadNotifications()
95+
}
96+
}
97+
}
8898
}
8999
} header: {
90100
HStack {
@@ -104,51 +114,56 @@ struct NotificationsView: View {
104114
}
105115
}
106116

107-
ForEach(NotificationDateSection.allCases, id: \.self) { section in
108-
if let notifications = sections[section], !notifications.isEmpty {
109-
Section(header: Text(section.rawValue)) {
110-
ForEach(notifications, id: \.notificationId) { notification in
111-
NotificationRow(notification: notification)
112-
.onAppear {
113-
var lastSectionWithNotifications: NotificationDateSection? =
114-
nil
115-
for sectionCase in NotificationDateSection.allCases.reversed() {
116-
if let sectionNotifications = sections[sectionCase],
117-
!sectionNotifications.isEmpty
118-
{
119-
lastSectionWithNotifications = sectionCase
120-
break
117+
if !viewModel.hasMoreUnreadToLoad {
118+
ForEach(NotificationDateSection.allCases, id: \.self) { section in
119+
if let notifications = sections[section], !notifications.isEmpty {
120+
Section(header: Text(section.rawValue)) {
121+
ForEach(notifications, id: \.notificationId) { notification in
122+
NotificationRow(notification: notification, refreshId: refreshId)
123+
.onAppear {
124+
var lastSectionWithNotifications: NotificationDateSection? =
125+
nil
126+
for sectionCase in NotificationDateSection.allCases.reversed() {
127+
if let sectionNotifications = sections[sectionCase],
128+
!sectionNotifications.isEmpty
129+
{
130+
lastSectionWithNotifications = sectionCase
131+
break
132+
}
121133
}
122-
}
123134

124-
if section == lastSectionWithNotifications
125-
&& notification.notificationId
126-
== notifications.last?.notificationId
127-
{
128-
Task {
129-
await viewModel.loadMoreNotifications()
135+
if section == lastSectionWithNotifications
136+
&& notification.notificationId
137+
== notifications.last?.notificationId
138+
{
139+
Task {
140+
await viewModel.loadMoreNotifications()
141+
}
130142
}
131143
}
132-
}
144+
}
133145
}
134146
}
135147
}
136148
}
137149

138150
// the uuid part is a fix from: https://stackoverflow.com/questions/70627642/progressview-hides-on-list-scroll/75431883#75431883
139-
HStack {
140-
Spacer()
141-
ProgressView()
142-
.scaleEffect(1.1)
143-
.padding()
144-
Spacer()
151+
if viewModel.hasMoreUnreadToLoad || viewModel.hasMoreToLoad {
152+
HStack {
153+
Spacer()
154+
ProgressView()
155+
.scaleEffect(1.1)
156+
.padding()
157+
Spacer()
158+
}
159+
.id(UUID())
145160
}
146-
.id(UUID())
147161
}
148162
.listStyle(.plain)
149163
.listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
150164
.refreshable {
151165
await viewModel.refreshNotifications()
166+
refreshId = UUID()
152167
}
153168
}
154169
}

0 commit comments

Comments
 (0)