diff --git a/Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift b/Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift index 0678104..25710c3 100644 --- a/Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift +++ b/Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift @@ -82,64 +82,34 @@ public struct AcknowledgementEntry { } +/// Other (additional) application entry. +public struct OtherAppEntry { + + /// The application identifier of the referenced app. + public var appID: String + + /// The display name of the referenced app. + public var name: String + + /// A short descriptive summary of the referenced app. + public var summary: String + + /// Creates a new other application entry. + /// - Parameters: + /// - appID: The application identifier of the referenced app. + /// - name: The display name of the referenced app. + /// - summary: A short descriptive summary of the referenced app. + public init(appID: String, name: String, summary: String) { + self.appID = appID + self.name = name + self.summary = summary + } + +} + /// Initialization options for the about dialog wrapper. public struct AdwaitaAboutDialogConfig { - /// Example HTML release notes used for demonstrating how the About dialog - /// renders structured content such as paragraphs, lists, and inline markup. - /// This sample is intended for testing, previews, and documentation. - public static let demoReleaseNotes = """ -

This template supports three structures: paragraphs using <p>, ordered lists using - <ol>, and unordered lists using <ul>. - Both list types must contain list items marked with <li>.

-

Within paragraphs and list items, you may use <em> to apply - emphasis(italic text) and <code> to mark inline code - for monospaced text. - These inline styles are supported only inside those elements.

-

Any text placed outside <p>, <ol>, - <ul>, or <li> tags is ignored by the template - processor.

-
    -
  1. Ordered list items represent numbered content and may - include <em> for emphasis or <code> for inline code.
  2. -
  3. They follow the same rules as paragraphs regarding allowed inline styles.
  4. -
- - """ - - /// Example Pango‑markup comments showcasing how styled text, links, and - /// formatting behave inside the About dialog’s “Details” section. - /// Useful for previews, testing, and as a reference for developers who want - /// to embed formatted text in their own dialogs. - public static let demoComments = """ - This text demonstrates basic Pango markup along with helpful documentation links. - - Comments shown in an Adwaita AboutDialog will appear on the Details page. - They can be long and detailed, and they may include links and Pango markup for - formatting. - - Pango markup supports tags like: - • bold - • italic - • colored text - - Full reference: Pango Markup - Reference - - Example markup: - Demo Title - Highlighted text - Underlined text - - Useful links: - • Adwaita‑Swift Documentation - - You can embed these links directly in your UI using Pango markup. - """ - /// The app's name. public var appName: String? /// The developer's name. @@ -168,6 +138,8 @@ public struct AdwaitaAboutDialogConfig { public var credits: [CreditEntry]? /// Acknowledgements to display in the dialog. public var acknowledgements: [AcknowledgementEntry]? + /// Additional applications. + public var otherApps: [OtherAppEntry]? /// Initialize the about dialog wrapper. /// - Parameters: @@ -185,6 +157,7 @@ public struct AdwaitaAboutDialogConfig { /// - comments: The comments about the application. /// - credits: Recognition by name and role of contributors. /// - acknowledgements: List of acknowledgements. + /// - otherApps: List of other applications. public init( appName: String? = nil, developer: String? = nil, @@ -199,7 +172,8 @@ public struct AdwaitaAboutDialogConfig { releaseNotes: String? = nil, comments: String? = nil, credits: [CreditEntry]? = nil, - acknowledgements: [AcknowledgementEntry]? = nil + acknowledgements: [AcknowledgementEntry]? = nil, + otherApps: [OtherAppEntry]? = nil ) { self.appName = appName self.developer = developer @@ -215,6 +189,7 @@ public struct AdwaitaAboutDialogConfig { self.comments = comments self.credits = credits self.acknowledgements = acknowledgements + self.otherApps = otherApps } /// Applies a string value to the dialog using the given setter. @@ -228,9 +203,11 @@ public struct AdwaitaAboutDialogConfig { using setter: (OpaquePointer, UnsafePointer?) -> Void, on dialog: OpaquePointer ) { - if let value { - setter(dialog, value) + guard let value else { + return } + + setter(dialog, value) } /// Applies a list of links to the dialog. @@ -252,45 +229,32 @@ public struct AdwaitaAboutDialogConfig { /// - credits: The optional list of credit entries. /// - dialog: The dialog instance. @inline(__always) - private func set( - _ credits: [CreditEntry]?, - on dialog: OpaquePointer - ) { - if let credits { - var developers: [String] = [] - var designers: [String] = [] - var artists: [String] = [] - var translators: [String] = [] + private func set(_ credits: [CreditEntry]?, on dialog: OpaquePointer) { + guard let credits else { + return + } - for entry in credits { - switch entry.role { - case .developer: - developers.append(entry.name) - case .designer: - designers.append(entry.name) - case .artist: - artists.append(entry.name) - case .translator: - translators.append(entry.name) - } - } + let grouped = Dictionary(grouping: credits, by: \.role) - if let ptr = developers.cMutableArray, !developers.isEmpty { - adw_about_dialog_set_developers(dialog, ptr) - } + if let devs = grouped[.developer]?.map(\.name), + let ptr = devs.cMutableArray { + adw_about_dialog_set_developers(dialog, ptr) + } - if let ptr = designers.cMutableArray, !designers.isEmpty { - adw_about_dialog_set_designers(dialog, ptr) - } + if let designers = grouped[.designer]?.map(\.name), + let ptr = designers.cMutableArray { + adw_about_dialog_set_designers(dialog, ptr) + } - if let ptr = artists.cMutableArray, !artists.isEmpty { - adw_about_dialog_set_artists(dialog, ptr) - } + if let artists = grouped[.artist]?.map(\.name), + let ptr = artists.cMutableArray { + adw_about_dialog_set_artists(dialog, ptr) + } - if !translators.isEmpty { - let joined = translators.joined(separator: "\n") - adw_about_dialog_set_translator_credits(dialog, joined) - } + if let translators = grouped[.translator]?.map(\.name), + !translators.isEmpty { + let joined = translators.joined(separator: "\n") + adw_about_dialog_set_translator_credits(dialog, joined) } } @@ -303,18 +267,43 @@ public struct AdwaitaAboutDialogConfig { _ acknowledgements: [AcknowledgementEntry]?, on dialog: OpaquePointer ) { - if let acknowledgements { - let grouped = Dictionary(grouping: acknowledgements) { $0.title } + guard let acknowledgements else { + return + } - for (title, entries) in grouped { - let names = entries.map { $0.name } - guard let people = names.cMutableArray else { continue } + let grouped = Dictionary(grouping: acknowledgements) { $0.title } - adw_about_dialog_add_acknowledgement_section(dialog, title, people) - } + for (title, entries) in grouped { + let names = entries.map { $0.name } + guard let people = names.cMutableArray else { continue } + + adw_about_dialog_add_acknowledgement_section(dialog, title, people) } } + /// Applies other apps entries to the dialog. + /// - Parameters: + /// - otherApps: The optional list of other app entries. + /// - dialog: The dialog instance. + @inline(__always) + private func set( + _ otherApps: [OtherAppEntry]?, + on dialog: OpaquePointer + ) { + guard let otherApps else { + return + } + + for entry in otherApps { + adw_about_dialog_add_other_app( + dialog, + entry.appID, + entry.name, + entry.summary + ) + } + } + /// Apply the configuration values to the given dialog. /// - Parameters: /// - dialog: The underlying Adwaita dialog instance to update with the configuration. @@ -333,6 +322,7 @@ public struct AdwaitaAboutDialogConfig { set(links, on: dialog) set(credits, on: dialog) set(acknowledgements, on: dialog) + set(otherApps, on: dialog) } }