forked from aparoksha/adwaita-swift
329 lines
10 KiB
Swift
329 lines
10 KiB
Swift
//
|
|
// AdwaitaAboutDialogConfig.swift
|
|
// Adwaita
|
|
//
|
|
// Created by lambdaclan on 09.01.2026.
|
|
//
|
|
|
|
import CAdw
|
|
import Foundation
|
|
|
|
/// A link shown in the About dialog.
|
|
public struct AboutLink {
|
|
|
|
/// The link title.
|
|
public var title: String
|
|
|
|
/// The destination URL.
|
|
public var url: URL?
|
|
|
|
/// Create a new link.
|
|
/// - Parameters:
|
|
/// - title: The link title.
|
|
/// - url: The destination URL.
|
|
public init(title: String, url: URL?) {
|
|
self.title = title
|
|
self.url = url
|
|
}
|
|
|
|
}
|
|
|
|
/// The type of contribution made by a credited person.
|
|
public enum ContributionRole {
|
|
|
|
/// A person who contributed to development.
|
|
case developer
|
|
/// A person who contributed to design.
|
|
case designer
|
|
/// A person who contributed artwork or visuals.
|
|
case artist
|
|
/// A person who contributed translations.
|
|
case translator
|
|
|
|
}
|
|
|
|
/// A credited person and their contribution role.
|
|
public struct CreditEntry {
|
|
|
|
/// The contributor's role.
|
|
public var role: ContributionRole
|
|
|
|
/// The contributor's name.
|
|
public var name: String
|
|
|
|
/// Create a new credit entry.
|
|
/// - Parameters:
|
|
/// - role: The contributor's role.
|
|
/// - name: The contributor's name.
|
|
public init(role: ContributionRole, name: String) {
|
|
self.role = role
|
|
self.name = name
|
|
}
|
|
|
|
}
|
|
|
|
/// An acknowledgement entry.
|
|
public struct AcknowledgementEntry {
|
|
|
|
/// The acknowledgement section title.
|
|
public var title: String
|
|
|
|
/// Acknowledged person/organization name.
|
|
public var name: String
|
|
|
|
/// Create a new acknowledgement entry.
|
|
/// - Parameters:
|
|
/// - title: The acknowledgement section title.
|
|
/// - name: The acknowledged person or organization.
|
|
public init(title: String, name: String) {
|
|
self.title = title
|
|
self.name = name
|
|
}
|
|
|
|
}
|
|
|
|
/// 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 {
|
|
|
|
/// The app's name.
|
|
public var appName: String?
|
|
/// The developer's name.
|
|
public var developer: String?
|
|
/// The app version.
|
|
public var version: String?
|
|
/// The app icon.
|
|
public var icon: Icon?
|
|
/// The app's website.
|
|
public var website: URL?
|
|
/// The link for opening issues.
|
|
public var issues: URL?
|
|
/// The link for getting support.
|
|
public var support: URL?
|
|
/// Additional links related to the app.
|
|
public var links: [AboutLink]?
|
|
/// The app's copyright information.
|
|
public var copyright: String?
|
|
/// The app's license.
|
|
public var license: String?
|
|
/// The app's release notes.
|
|
public var releaseNotes: String?
|
|
/// The comments about the application.
|
|
public var comments: String?
|
|
/// Recognition by name and role of contributors.
|
|
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:
|
|
/// - appName: The app's name.
|
|
/// - developer: The developer's name.
|
|
/// - version: The version string.
|
|
/// - icon: The app icon.
|
|
/// - website: The app's website.
|
|
/// - issues: Website for reporting issues.
|
|
/// - support: Website for getting support.
|
|
/// - links: Additional links related to the app.
|
|
/// - copyright: The app's copyright information.
|
|
/// - license: The app's license.
|
|
/// - releaseNotes: The app's release notes.
|
|
/// - 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,
|
|
version: String? = nil,
|
|
icon: Icon? = nil,
|
|
website: URL? = nil,
|
|
issues: URL? = nil,
|
|
support: URL? = nil,
|
|
links: [AboutLink]? = nil,
|
|
copyright: String? = nil,
|
|
license: String? = nil,
|
|
releaseNotes: String? = nil,
|
|
comments: String? = nil,
|
|
credits: [CreditEntry]? = nil,
|
|
acknowledgements: [AcknowledgementEntry]? = nil,
|
|
otherApps: [OtherAppEntry]? = nil
|
|
) {
|
|
self.appName = appName
|
|
self.developer = developer
|
|
self.version = version
|
|
self.icon = icon
|
|
self.website = website
|
|
self.issues = issues
|
|
self.support = support
|
|
self.links = links
|
|
self.copyright = copyright
|
|
self.license = license
|
|
self.releaseNotes = releaseNotes
|
|
self.comments = comments
|
|
self.credits = credits
|
|
self.acknowledgements = acknowledgements
|
|
self.otherApps = otherApps
|
|
}
|
|
|
|
/// Applies a string value to the dialog using the given setter.
|
|
/// - Parameters:
|
|
/// - value: The optional string to apply.
|
|
/// - setter: The C function that sets the value on the dialog.
|
|
/// - dialog: The dialog instance.
|
|
@inline(__always)
|
|
private func set(
|
|
_ value: String?,
|
|
using setter: (OpaquePointer, UnsafePointer<CChar>?) -> Void,
|
|
on dialog: OpaquePointer
|
|
) {
|
|
guard let value else {
|
|
return
|
|
}
|
|
|
|
setter(dialog, value)
|
|
}
|
|
|
|
/// Applies a list of links to the dialog.
|
|
/// - Parameters:
|
|
/// - links: The optional list of links.
|
|
/// - dialog: The dialog instance.
|
|
@inline(__always)
|
|
private func set(
|
|
_ links: [AboutLink]?,
|
|
on dialog: OpaquePointer
|
|
) {
|
|
links?.forEach { link in
|
|
adw_about_dialog_add_link(dialog, link.title, link.url?.absoluteString)
|
|
}
|
|
}
|
|
|
|
/// Applies credit entries to the dialog.
|
|
/// - Parameters:
|
|
/// - credits: The optional list of credit entries.
|
|
/// - dialog: The dialog instance.
|
|
@inline(__always)
|
|
private func set(_ credits: [CreditEntry]?, on dialog: OpaquePointer) {
|
|
guard let credits else {
|
|
return
|
|
}
|
|
|
|
let grouped = Dictionary(grouping: credits, by: \.role)
|
|
|
|
if let devs = grouped[.developer]?.map(\.name),
|
|
let ptr = devs.cMutableArray {
|
|
adw_about_dialog_set_developers(dialog, ptr)
|
|
}
|
|
|
|
if let designers = grouped[.designer]?.map(\.name),
|
|
let ptr = designers.cMutableArray {
|
|
adw_about_dialog_set_designers(dialog, ptr)
|
|
}
|
|
|
|
if let artists = grouped[.artist]?.map(\.name),
|
|
let ptr = artists.cMutableArray {
|
|
adw_about_dialog_set_artists(dialog, ptr)
|
|
}
|
|
|
|
if let translators = grouped[.translator]?.map(\.name),
|
|
!translators.isEmpty {
|
|
let joined = translators.joined(separator: "\n")
|
|
adw_about_dialog_set_translator_credits(dialog, joined)
|
|
}
|
|
}
|
|
|
|
/// Applies acknowledgement entries to the dialog.
|
|
/// - Parameters:
|
|
/// - acknowledgements: The optional list of acknowledgement entries.
|
|
/// - dialog: The dialog instance.
|
|
@inline(__always)
|
|
private func set(
|
|
_ acknowledgements: [AcknowledgementEntry]?,
|
|
on dialog: OpaquePointer
|
|
) {
|
|
guard let acknowledgements else {
|
|
return
|
|
}
|
|
|
|
let grouped = Dictionary(grouping: acknowledgements) { $0.title }
|
|
|
|
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.
|
|
func apply(to dialog: OpaquePointer) {
|
|
set(appName, using: adw_about_dialog_set_application_name, on: dialog)
|
|
set(developer, using: adw_about_dialog_set_developer_name, on: dialog)
|
|
set(version, using: adw_about_dialog_set_version, on: dialog)
|
|
set(icon?.string, using: adw_about_dialog_set_application_icon, on: dialog)
|
|
set(website?.absoluteString, using: adw_about_dialog_set_website, on: dialog)
|
|
set(issues?.absoluteString, using: adw_about_dialog_set_issue_url, on: dialog)
|
|
set(support?.absoluteString, using: adw_about_dialog_set_support_url, on: dialog)
|
|
set(copyright, using: adw_about_dialog_set_copyright, on: dialog)
|
|
set(license, using: adw_about_dialog_set_license, on: dialog)
|
|
set(releaseNotes, using: adw_about_dialog_set_release_notes, on: dialog)
|
|
set(comments, using: adw_about_dialog_set_comments, on: dialog)
|
|
set(links, on: dialog)
|
|
set(credits, on: dialog)
|
|
set(acknowledgements, on: dialog)
|
|
set(otherApps, on: dialog)
|
|
}
|
|
|
|
}
|