Skip to content

Commit d490729

Browse files
committed
Added sticky notifications. Allowed multiple notifications to overlay UI. Improved aesthetics of notification banner
1 parent c1b0355 commit d490729

5 files changed

Lines changed: 51 additions & 38 deletions

File tree

CodeEdit/Features/InspectorArea/FileInspector/FileInspectorView.swift

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,6 @@ struct FileInspectorView: View {
5959
widthOptions
6060
wrapLinesToggle
6161
}
62-
Section {
63-
Button("Add Test Notification") {
64-
addTestNotification()
65-
}
66-
Button("Add Test Notification After Delay") {
67-
addTestNotificationAfterDelay()
68-
}
69-
}
7062
}
7163
} else {
7264
NoSelectionInspectorView()
@@ -89,26 +81,9 @@ struct FileInspectorView: View {
8981
}
9082
}
9183

92-
func addTestNotification () {
93-
NotificationManager.shared.post(
94-
iconSymbol: "bell.badge.fill",
95-
iconColor: .red,
96-
title: "New Notification Created",
97-
description: "Successfully created new notification",
98-
actionButtonTitle: "Action",
99-
action: {
100-
print("Action taken")
101-
}
102-
)
103-
}
104-
105-
func addTestNotificationAfterDelay () {
106-
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
107-
addTestNotification()
108-
}
109-
}
110-
11184
@ViewBuilder private var fileNameField: some View {
85+
@State var isValid: Bool = true
86+
11287
if let file {
11388
TextField("Name", text: $fileName)
11489
.background(
@@ -136,6 +111,7 @@ struct FileInspectorView: View {
136111
}
137112
}
138113
} else {
114+
isValid = false
139115
fileName = file.labelFileName()
140116
}
141117
}

CodeEdit/Features/Notifications/NotificationManager.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ final class NotificationManager: NSObject, ObservableObject {
2222
@Published private(set) var notifications: [CENotification] = []
2323

2424
private var isAppActive: Bool = true
25+
private var hiddenStickyNotifications: [CENotification] = []
26+
private var hiddenNonStickyNotifications: [CENotification] = []
27+
private var dismissedNotificationIds: Set<UUID> = [] // Track dismissed notifications
2528

2629
/// Number of unread notifications
2730
var unreadCount: Int {

CodeEdit/Features/Notifications/Views/NotificationBannerView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ struct NotificationBannerView: View {
1414
@EnvironmentObject private var workspace: WorkspaceDocument
1515
@ObservedObject private var notificationManager = NotificationManager.shared
1616

17+
@Environment(\.colorScheme)
18+
private var colorScheme
19+
1720
let notification: CENotification
1821
let onDismiss: () -> Void
1922
let onAction: () -> Void

CodeEdit/Features/Notifications/Views/NotificationListView.swift

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,22 @@
88
import SwiftUI
99

1010
struct NotificationListView: View {
11+
@Environment(\.dismiss)
12+
private var dismiss
13+
1114
@ObservedObject private var notificationManager = NotificationManager.shared
15+
1216
@Namespace private var animation
1317

18+
private var sortedNotifications: [CENotification] {
19+
notificationManager.notifications.sorted { first, second in
20+
if first.isSticky == second.isSticky {
21+
return first.timestamp > second.timestamp
22+
}
23+
return first.isSticky && !second.isSticky
24+
}
25+
}
26+
1427
var body: some View {
1528
ScrollView {
1629
VStack(spacing: 10) {
@@ -19,30 +32,48 @@ struct NotificationListView: View {
1932
.foregroundColor(.secondary)
2033
.padding()
2134
} else {
22-
ForEach(notificationManager.notifications) { notification in
35+
ForEach(sortedNotifications) { notification in
2336
NotificationBannerView(
2437
notification: notification,
2538
namespace: animation,
2639
onDismiss: {
27-
withAnimation(.easeInOut(duration: 0.2)) {
28-
notificationManager.dismissNotification(notification)
40+
if !notification.isSticky && notificationManager.notifications.count == 1 {
41+
dismiss()
42+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
43+
withAnimation(.easeInOut(duration: 0.2)) {
44+
notificationManager.dismissNotification(notification)
45+
}
46+
}
47+
} else {
48+
withAnimation(.easeInOut(duration: 0.2)) {
49+
notificationManager.dismissNotification(notification)
50+
}
2951
}
3052
},
3153
onAction: {
32-
withAnimation(.easeInOut(duration: 0.2)) {
33-
notification.action()
34-
notificationManager.dismissNotification(notification)
54+
if !notification.isSticky && notificationManager.notifications.count == 1 {
55+
dismiss()
56+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
57+
notification.action()
58+
withAnimation(.easeInOut(duration: 0.2)) {
59+
notificationManager.dismissNotification(notification)
60+
}
61+
}
62+
} else {
63+
withAnimation(.easeInOut(duration: 0.2)) {
64+
notification.action()
65+
notificationManager.dismissNotification(notification)
66+
}
3567
}
3668
}
3769
)
3870
.environment(\.isOverlay, false)
3971
.environment(\.isSingleListItem, notificationManager.notifications.count == 1)
40-
.transition(.opacity.combined(with: .move(edge: .trailing)))
72+
.transition(.opacity)
4173
}
4274
}
4375
}
44-
.padding(notificationManager.notifications.count == 1 ? 0 : 10)
45-
.animation(.easeInOut(duration: 0.2), value: notificationManager.notifications)
76+
.padding(10)
4677
}
4778
}
4879
}

CodeEdit/Features/Notifications/Views/NotificationOverlayView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct NotificationOverlayView: View {
1717

1818
var body: some View {
1919
VStack(spacing: 10) {
20-
ForEach(Array([notificationManager.activeNotification].compactMap { $0 }), id: \.id) { notification in
20+
ForEach(notificationManager.activeNotifications, id: \.id) { notification in
2121
if controlActiveState == .active || controlActiveState == .key {
2222
NotificationBannerView(
2323
notification: notification,
@@ -41,6 +41,6 @@ struct NotificationOverlayView: View {
4141
}
4242
}
4343
.padding(8)
44-
.animation(.easeInOut(duration: 0.2), value: notificationManager.activeNotification?.id)
44+
.animation(.easeInOut(duration: 0.2), value: notificationManager.activeNotifications)
4545
}
4646
}

0 commit comments

Comments
 (0)