@@ -433,6 +433,66 @@ private func actionStrdup(_ string: String) -> UnsafeMutablePointer<CChar> {
433433 return string. withCString { strdup ( $0) ! }
434434}
435435
436+ // MARK: - Alert dialog
437+
438+ /// Run a modal alert dialog and return the title of the button that was clicked.
439+ ///
440+ /// Config JSON keys (all optional):
441+ /// title: String — bold heading text
442+ /// message: String — informative text below the title
443+ /// style: String — "informational" (default), "warning", or "critical"
444+ /// buttons: [String] — button titles, first is the default (rightmost),
445+ /// second is placed to its left, etc.
446+ /// Defaults to ["OK"] if omitted.
447+ ///
448+ /// Returns the title of the clicked button as a C string, or nil on error.
449+ @_cdecl ( " actionUIAppRunAlert " )
450+ public func actionUIAppRunAlert(
451+ _ configJSON: UnsafePointer < CChar > ?
452+ ) -> UnsafeMutablePointer < CChar > ? {
453+ let jsonString = configJSON. map { String ( cString: $0) }
454+ return runOnMainActorSync {
455+ var config : [ String : Any ] = [ : ]
456+ if let json = jsonString,
457+ let data = json. data ( using: . utf8) ,
458+ let parsed = try ? JSONSerialization . jsonObject ( with: data) as? [ String : Any ] {
459+ config = parsed
460+ }
461+
462+ let alert = NSAlert ( )
463+
464+ if let title = config [ " title " ] as? String {
465+ alert. messageText = title
466+ }
467+ if let message = config [ " message " ] as? String {
468+ alert. informativeText = message
469+ }
470+
471+ switch config [ " style " ] as? String {
472+ case " warning " :
473+ alert. alertStyle = . warning
474+ case " critical " :
475+ alert. alertStyle = . critical
476+ default :
477+ alert. alertStyle = . informational
478+ }
479+
480+ let buttons = config [ " buttons " ] as? [ String ] ?? [ " OK " ]
481+ for title in buttons {
482+ alert. addButton ( withTitle: title)
483+ }
484+
485+ let response = alert. runModal ( )
486+
487+ // NSAlert buttons are numbered .alertFirstButtonReturn, +1, +2, …
488+ let index = response. rawValue - NSApplication. ModalResponse. alertFirstButtonReturn. rawValue
489+ if index >= 0 && index < buttons. count {
490+ return actionStrdup ( buttons [ index] )
491+ }
492+ return nil
493+ }
494+ }
495+
436496// MARK: - File panels (NSOpenPanel / NSSavePanel)
437497
438498/// Parse a JSON config dictionary and configure an `NSOpenPanel`.
0 commit comments