Skip to content

Commit ab5d806

Browse files
committed
Modernize notification system: fix icons, dismiss lifecycle, and code quality
Replace multi-byte emoji icons with single-cell-width Unicode characters to prevent rendering corruption in the character buffer. Hook notification dismissal into window OnClosing event so title bar [X], Close button, Escape key, timeout, and programmatic close all properly clean up state. Add re-entrancy guard to prevent infinite recursion between dismiss and close. Extract magic numbers to ControlDefaults constants.
1 parent 5dec260 commit ab5d806

3 files changed

Lines changed: 126 additions & 198 deletions

File tree

SharpConsoleUI/Configuration/ControlDefaults.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,5 +284,21 @@ public static class ControlDefaults
284284
/// Extra padding for dropdown item width calculation including shortcut spacing (default: 10)
285285
/// </summary>
286286
public const int MenuItemDropdownPadding = 10;
287+
288+
// Notification defaults
289+
/// <summary>
290+
/// Horizontal padding added to notification window width beyond message length (default: 8)
291+
/// </summary>
292+
public const int NotificationHorizontalPadding = 8;
293+
294+
/// <summary>
295+
/// Vertical padding added to notification window height beyond message line count (default: 5)
296+
/// </summary>
297+
public const int NotificationVerticalPadding = 5;
298+
299+
/// <summary>
300+
/// Default auto-dismiss timeout for notifications in milliseconds (default: 5000)
301+
/// </summary>
302+
public const int NotificationDefaultTimeoutMs = 5000;
287303
}
288304
}

SharpConsoleUI/Core/NotificationSeverity.cs

Lines changed: 22 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -29,43 +29,32 @@ public enum NotificationSeverityEnum
2929

3030
/// <summary>
3131
/// Represents a notification severity level with associated visual properties such as colors and icons.
32+
/// Uses single-cell-width Unicode characters for reliable console rendering.
3233
/// </summary>
3334
public class NotificationSeverity
3435
{
35-
/// <summary>
36-
/// Represents a danger/error notification severity with a red visual theme.
37-
/// </summary>
36+
/// <summary>Danger/error severity with red theme. Icon: ✘ (U+2718).</summary>
3837
public static readonly NotificationSeverity Danger = new NotificationSeverity(
39-
"Error", "", NotificationSeverityEnum.Danger);
38+
"Error", "\u2718", NotificationSeverityEnum.Danger);
4039

41-
/// <summary>
42-
/// Represents an informational notification severity with a blue visual theme.
43-
/// </summary>
40+
/// <summary>Informational severity with blue theme. Icon: ● (U+25CF).</summary>
4441
public static readonly NotificationSeverity Info = new NotificationSeverity(
45-
"Info", "ℹ️", NotificationSeverityEnum.Info);
42+
"Info", "\u25cf", NotificationSeverityEnum.Info);
4643

47-
/// <summary>
48-
/// Represents a generic notification with no specific severity.
49-
/// </summary>
44+
/// <summary>Generic notification with no specific severity.</summary>
5045
public static readonly NotificationSeverity None = new NotificationSeverity(
5146
"Notification", "", NotificationSeverityEnum.None);
5247

53-
/// <summary>
54-
/// Represents a success notification severity with a green visual theme.
55-
/// </summary>
48+
/// <summary>Success severity with green theme. Icon: ✔ (U+2714).</summary>
5649
public static readonly NotificationSeverity Success = new NotificationSeverity(
57-
"Success", "✔️", NotificationSeverityEnum.Success);
50+
"Success", "\u2714", NotificationSeverityEnum.Success);
5851

59-
/// <summary>
60-
/// Represents a warning notification severity with a yellow visual theme.
61-
/// </summary>
52+
/// <summary>Warning severity with yellow theme. Icon: ▲ (U+25B2).</summary>
6253
public static readonly NotificationSeverity Warning = new NotificationSeverity(
63-
"Warning", "⚠️", NotificationSeverityEnum.Warning);
54+
"Warning", "\u25b2", NotificationSeverityEnum.Warning);
6455

65-
/// <summary>
66-
/// Gets the severity level enum value.
67-
/// </summary>
68-
public NotificationSeverityEnum Severity;
56+
/// <summary>Gets the severity level enum value.</summary>
57+
public NotificationSeverityEnum Severity { get; }
6958

7059
private NotificationSeverity(string name, string icon, NotificationSeverityEnum severity)
7160
{
@@ -74,21 +63,15 @@ private NotificationSeverity(string name, string icon, NotificationSeverityEnum
7463
Severity = severity;
7564
}
7665

77-
/// <summary>
78-
/// Gets the icon associated with this severity level.
79-
/// </summary>
66+
/// <summary>Gets the icon character for this severity level.</summary>
8067
public string Icon { get; }
8168

82-
/// <summary>
83-
/// Gets the display name for this severity level.
84-
/// </summary>
69+
/// <summary>Gets the display name for this severity level.</summary>
8570
public string? Name { get; }
8671

8772
/// <summary>
8873
/// Gets a <see cref="NotificationSeverity"/> instance from a severity enum value.
8974
/// </summary>
90-
/// <param name="severity">The severity enum value.</param>
91-
/// <returns>The corresponding <see cref="NotificationSeverity"/> instance.</returns>
9275
/// <exception cref="NotImplementedException">Thrown if an unknown severity value is provided.</exception>
9376
public static NotificationSeverity FromSeverity(NotificationSeverityEnum severity)
9477
{
@@ -103,83 +86,33 @@ public static NotificationSeverity FromSeverity(NotificationSeverityEnum severit
10386
};
10487
}
10588

106-
/// <summary>
107-
/// Gets the active border foreground color for this severity level.
108-
/// </summary>
109-
/// <param name="consoleWindowSystem">The console window system to get theme colors from.</param>
110-
/// <returns>The foreground color for active window borders.</returns>
89+
/// <summary>Gets the active border foreground color (always white).</summary>
11190
public Color ActiveBorderForegroundColor(ConsoleWindowSystem consoleWindowSystem)
11291
{
113-
return Severity switch
114-
{
115-
NotificationSeverityEnum.Danger => Color.White,
116-
NotificationSeverityEnum.Info => Color.White,
117-
NotificationSeverityEnum.None => Color.White,
118-
NotificationSeverityEnum.Success => Color.White,
119-
NotificationSeverityEnum.Warning => Color.White,
120-
_ => throw new NotImplementedException()
121-
};
92+
return Color.White;
12293
}
12394

124-
/// <summary>
125-
/// Gets the active title foreground color for this severity level.
126-
/// </summary>
127-
/// <param name="consoleWindowSystem">The console window system to get theme colors from.</param>
128-
/// <returns>The foreground color for active window titles.</returns>
95+
/// <summary>Gets the active title foreground color (always white).</summary>
12996
public Color ActiveTitleForegroundColor(ConsoleWindowSystem consoleWindowSystem)
13097
{
131-
return Severity switch
132-
{
133-
NotificationSeverityEnum.Danger => Color.White,
134-
NotificationSeverityEnum.Info => Color.White,
135-
NotificationSeverityEnum.None => Color.White,
136-
NotificationSeverityEnum.Success => Color.White,
137-
NotificationSeverityEnum.Warning => Color.White,
138-
_ => throw new NotImplementedException()
139-
};
98+
return Color.White;
14099
}
141100

142-
/// <summary>
143-
/// Gets the inactive border foreground color for this severity level.
144-
/// </summary>
145-
/// <param name="consoleWindowSystem">The console window system to get theme colors from.</param>
146-
/// <returns>The foreground color for inactive window borders.</returns>
101+
/// <summary>Gets the inactive border foreground color (always white).</summary>
147102
public Color InactiveBorderForegroundColor(ConsoleWindowSystem consoleWindowSystem)
148103
{
149-
return Severity switch
150-
{
151-
NotificationSeverityEnum.Danger => Color.White,
152-
NotificationSeverityEnum.Info => Color.White,
153-
NotificationSeverityEnum.None => Color.White,
154-
NotificationSeverityEnum.Success => Color.White,
155-
NotificationSeverityEnum.Warning => Color.White,
156-
_ => throw new NotImplementedException()
157-
};
104+
return Color.White;
158105
}
159106

160-
/// <summary>
161-
/// Gets the inactive title foreground color for this severity level.
162-
/// </summary>
163-
/// <param name="consoleWindowSystem">The console window system to get theme colors from.</param>
164-
/// <returns>The foreground color for inactive window titles.</returns>
107+
/// <summary>Gets the inactive title foreground color (always white).</summary>
165108
public Color InactiveTitleForegroundColor(ConsoleWindowSystem consoleWindowSystem)
166109
{
167-
return Severity switch
168-
{
169-
NotificationSeverityEnum.Danger => Color.White,
170-
NotificationSeverityEnum.Info => Color.White,
171-
NotificationSeverityEnum.None => Color.White,
172-
NotificationSeverityEnum.Success => Color.White,
173-
NotificationSeverityEnum.Warning => Color.White,
174-
_ => throw new NotImplementedException()
175-
};
110+
return Color.White;
176111
}
177112

178113
/// <summary>
179114
/// Gets the window background color for this severity level based on the current theme.
180115
/// </summary>
181-
/// <param name="consoleWindowSystem">The console window system to get theme colors from.</param>
182-
/// <returns>The background color for notification windows of this severity.</returns>
183116
public Color WindowBackgroundColor(ConsoleWindowSystem consoleWindowSystem)
184117
{
185118
return Severity switch

0 commit comments

Comments
 (0)