forked from aparoksha/adwaita-swift
Compare commits
14 Commits
main
...
about-dial
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ecee0e8d8 | |||
| 4d2b644d70 | |||
| efedb8313b | |||
| 0b27bf0482 | |||
| 83af8478c3 | |||
| 4ec1ac3769 | |||
| 5c37730483 | |||
| aababde03f | |||
| e6ccd23298 | |||
| 9cb8ca266d | |||
| 407fca10ff | |||
| 96e35c5777 | |||
| b3f222e316 | |||
| 9597c57b39 |
7
.swiftformat
Normal file
7
.swiftformat
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
--exclude **/Generated
|
||||||
|
--type-blank-lines insert
|
||||||
|
--self init-only
|
||||||
|
--empty-braces spaced
|
||||||
|
--extension-acl on-declarations
|
||||||
|
--trailing-commas never
|
||||||
|
--disable indent
|
||||||
@ -12,30 +12,15 @@ extension AnyView {
|
|||||||
/// Add an about dialog to the parent window.
|
/// Add an about dialog to the parent window.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - visible: Whether the dialog is presented.
|
/// - visible: Whether the dialog is presented.
|
||||||
/// - app: The app's name.
|
/// - configure: A closure that mutates the dialog configuration.
|
||||||
/// - developer: The developer's name.
|
|
||||||
/// - version: The version string.
|
|
||||||
/// - icon: The app icon.
|
|
||||||
/// - website: The app's website.
|
|
||||||
/// - issues: Website for reporting issues.
|
|
||||||
public func aboutDialog(
|
public func aboutDialog(
|
||||||
visible: Binding<Bool>,
|
visible: Binding<Bool>,
|
||||||
app: String? = nil,
|
configure: (inout AdwaitaAboutDialogConfig) -> Void
|
||||||
developer: String? = nil,
|
|
||||||
version: String? = nil,
|
|
||||||
icon: Icon? = nil,
|
|
||||||
website: URL? = nil,
|
|
||||||
issues: URL? = nil
|
|
||||||
) -> AnyView {
|
) -> AnyView {
|
||||||
AboutDialog(
|
AboutDialog(
|
||||||
visible: visible,
|
visible: visible,
|
||||||
child: self,
|
child: self,
|
||||||
appName: app,
|
configure: configure
|
||||||
developer: developer,
|
|
||||||
version: version,
|
|
||||||
icon: icon,
|
|
||||||
website: website,
|
|
||||||
issues: issues
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
328
Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift
Normal file
328
Sources/Adwaita/Model/AdwaitaAboutDialogConfig.swift
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
//
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,11 +5,13 @@
|
|||||||
// Created by david-swift on 06.08.23.
|
// Created by david-swift on 06.08.23.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
extension Array where Element == String {
|
extension Array where Element == String {
|
||||||
|
|
||||||
/// Get the C version of the array.
|
/// Get the C version of the array.
|
||||||
var cArray: UnsafePointer<UnsafePointer<CChar>?>? {
|
var cArray: UnsafePointer<UnsafePointer<CChar>?>? {
|
||||||
let cStrings = self.map { $0.utf8CString }
|
let cStrings = map { $0.utf8CString }
|
||||||
let cStringPointers = cStrings.map { $0.withUnsafeBufferPointer { $0.baseAddress } }
|
let cStringPointers = cStrings.map { $0.withUnsafeBufferPointer { $0.baseAddress } }
|
||||||
let optionalCStringPointers = cStringPointers + [nil]
|
let optionalCStringPointers = cStringPointers + [nil]
|
||||||
var optionalCStringPointersCopy = optionalCStringPointers
|
var optionalCStringPointersCopy = optionalCStringPointers
|
||||||
@ -25,4 +27,20 @@ extension Array where Element == String {
|
|||||||
return UnsafePointer(pointer)
|
return UnsafePointer(pointer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the mutable C version of the array.
|
||||||
|
var cMutableArray: UnsafeMutablePointer<UnsafePointer<CChar>?>? {
|
||||||
|
let pointer = UnsafeMutablePointer<UnsafePointer<CChar>?>.allocate(
|
||||||
|
capacity: count + 1
|
||||||
|
)
|
||||||
|
|
||||||
|
for (index, string) in enumerated() {
|
||||||
|
let cstr = strdup(string)
|
||||||
|
pointer[index] = UnsafePointer(cstr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer[count] = nil
|
||||||
|
|
||||||
|
return pointer
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,19 +15,8 @@ struct AboutDialog: AdwaitaWidget {
|
|||||||
@Binding var visible: Bool
|
@Binding var visible: Bool
|
||||||
/// The wrapped view.
|
/// The wrapped view.
|
||||||
var child: AnyView
|
var child: AnyView
|
||||||
|
/// The dialog configuration options.
|
||||||
/// The app's name.
|
var config: AdwaitaAboutDialogConfig
|
||||||
var appName: String?
|
|
||||||
/// The developer's name.
|
|
||||||
var developer: String?
|
|
||||||
/// The app version.
|
|
||||||
var version: String?
|
|
||||||
/// The app icon.
|
|
||||||
var icon: Icon?
|
|
||||||
/// The app's website.
|
|
||||||
var website: URL?
|
|
||||||
/// The link for opening issues.
|
|
||||||
var issues: URL?
|
|
||||||
|
|
||||||
/// The ID for the dialog's storage.
|
/// The ID for the dialog's storage.
|
||||||
let dialogID = "dialog"
|
let dialogID = "dialog"
|
||||||
@ -36,30 +25,18 @@ struct AboutDialog: AdwaitaWidget {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - visible: The visibility.
|
/// - visible: The visibility.
|
||||||
/// - child: The child view.
|
/// - child: The child view.
|
||||||
/// - appName: The app's name.
|
/// - configure: A closure that mutates the dialog configuration.
|
||||||
/// - developer: The developer's name.
|
|
||||||
/// - version: The version.
|
|
||||||
/// - icon: The icon.
|
|
||||||
/// - website: The website's URL.
|
|
||||||
/// - issues: The link for opening issues.
|
|
||||||
init(
|
init(
|
||||||
visible: Binding<Bool>,
|
visible: Binding<Bool>,
|
||||||
child: AnyView,
|
child: AnyView,
|
||||||
appName: String? = nil,
|
configure: (inout AdwaitaAboutDialogConfig) -> Void
|
||||||
developer: String? = nil,
|
|
||||||
version: String? = nil,
|
|
||||||
icon: Icon? = nil,
|
|
||||||
website: URL? = nil,
|
|
||||||
issues: URL? = nil
|
|
||||||
) {
|
) {
|
||||||
self._visible = visible
|
self._visible = visible
|
||||||
self.child = child
|
self.child = child
|
||||||
self.appName = appName
|
|
||||||
self.developer = developer
|
var cfg = AdwaitaAboutDialogConfig()
|
||||||
self.version = version
|
configure(&cfg)
|
||||||
self.icon = icon
|
self.config = cfg
|
||||||
self.website = website
|
|
||||||
self.issues = issues
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The view storage.
|
/// The view storage.
|
||||||
@ -97,26 +74,12 @@ struct AboutDialog: AdwaitaWidget {
|
|||||||
storage.opaquePointer?.cast()
|
storage.opaquePointer?.cast()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
let dialog = storage.content[dialogID]?.first?.opaquePointer
|
guard let dialog = storage.content[dialogID]?.first?.opaquePointer else {
|
||||||
if let appName {
|
return
|
||||||
adw_about_dialog_set_application_name(dialog, appName)
|
|
||||||
}
|
}
|
||||||
if let developer {
|
config.apply(to: dialog)
|
||||||
adw_about_dialog_set_developer_name(dialog, developer)
|
|
||||||
}
|
adw_dialog_set_content_height(dialog.cast(), -1)
|
||||||
if let version {
|
|
||||||
adw_about_dialog_set_version(dialog, version)
|
|
||||||
}
|
|
||||||
if let icon {
|
|
||||||
adw_about_dialog_set_application_icon(dialog, icon.string)
|
|
||||||
}
|
|
||||||
if let website {
|
|
||||||
adw_about_dialog_set_website(dialog, website.absoluteString)
|
|
||||||
}
|
|
||||||
if let issues {
|
|
||||||
adw_about_dialog_set_issue_url(dialog, issues.absoluteString)
|
|
||||||
}
|
|
||||||
adw_dialog_set_content_height(dialog?.cast(), -1)
|
|
||||||
} else {
|
} else {
|
||||||
if storage.content[dialogID]?.first != nil {
|
if storage.content[dialogID]?.first != nil {
|
||||||
let dialog = storage.content[dialogID]?.first?.opaquePointer
|
let dialog = storage.content[dialogID]?.first?.opaquePointer
|
||||||
|
|||||||
115
Sources/Demo/AboutDialogDemo.swift
Normal file
115
Sources/Demo/AboutDialogDemo.swift
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// AboutDialogDemo.swift
|
||||||
|
// Adwaita
|
||||||
|
//
|
||||||
|
// Created by lambdaclan on 24.01.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
// swiftlint:disable missing_docs
|
||||||
|
|
||||||
|
import Adwaita
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum AboutDialogDemo {
|
||||||
|
|
||||||
|
static var sample: (inout AdwaitaAboutDialogConfig) -> Void {
|
||||||
|
{ cfg in
|
||||||
|
applyDemoConfig(&cfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static let demoReleaseNotes = """
|
||||||
|
<p>This template supports three structures: paragraphs using <code><p></code>, ordered lists using
|
||||||
|
<code><ol></code>, and unordered lists using <code><ul></code>.
|
||||||
|
Both list types must contain list items marked with <code><li></code>.</p>
|
||||||
|
<p>Within paragraphs and list items, you may use <code><em></code> to apply
|
||||||
|
<em>emphasis</em>(italic text) and <code><code></code> to mark <code>inline code</code>
|
||||||
|
for monospaced text.
|
||||||
|
These inline styles are supported only inside those elements.</p>
|
||||||
|
<p>Any text placed outside <code><p></code>, <code><ol></code>,
|
||||||
|
<code><ul></code>, or <code><li></code> tags is ignored by the template
|
||||||
|
processor.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Ordered list items represent numbered content and may
|
||||||
|
include <code><em></code> for <em>emphasis</em> or <code><code></code> for inline code.</li>
|
||||||
|
<li>They follow the same rules as paragraphs regarding allowed inline styles.</li>
|
||||||
|
</ol>
|
||||||
|
<ul>
|
||||||
|
<li>Unordered list items represent bullet points and support the same inline styles.</li>
|
||||||
|
<li>They must contain only text and allowed inline formatting.</li>
|
||||||
|
</ul>
|
||||||
|
"""
|
||||||
|
|
||||||
|
private 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:
|
||||||
|
• <b>bold</b>
|
||||||
|
• <i>italic</i>
|
||||||
|
• <span foreground="steelblue">colored text</span>
|
||||||
|
|
||||||
|
Full reference: <a href="https://docs.gtk.org/Pango/pango_markup.html">Pango Markup
|
||||||
|
Reference</a>
|
||||||
|
|
||||||
|
Example markup:
|
||||||
|
<span font="14pt" weight="bold">Demo Title</span>
|
||||||
|
<span foreground="tomato">Highlighted text</span>
|
||||||
|
<u>Underlined text</u>
|
||||||
|
|
||||||
|
Useful links:
|
||||||
|
• <a href="https://adwaita-swift.aparoksha.dev/documentation/adwaita">Adwaita‑Swift Documentation</a>
|
||||||
|
|
||||||
|
You can embed these links directly in your UI using Pango markup.
|
||||||
|
"""
|
||||||
|
|
||||||
|
private static func applyDemoConfig(_ cfg: inout AdwaitaAboutDialogConfig) {
|
||||||
|
cfg.appName = "Demo"
|
||||||
|
cfg.developer = "david-swift"
|
||||||
|
cfg.version = "Test"
|
||||||
|
cfg.icon = .default(icon: .applicationXExecutable)
|
||||||
|
|
||||||
|
cfg.website = URL(string: "https://adwaita-swift.aparoksha.dev/tutorials/table-of-contents")
|
||||||
|
cfg.issues = URL(string: "https://git.aparoksha.dev/aparoksha/adwaita-swift/issues")
|
||||||
|
cfg.support = URL(string: "https://adwaita-swift.aparoksha.dev/")
|
||||||
|
|
||||||
|
cfg.links = [
|
||||||
|
.init(title: "Source Code", url: URL(string: "https://git.aparoksha.dev/aparoksha/adwaita-swift")),
|
||||||
|
.init(title: "Donate", url: URL(string: "https://ko-fi.com/david_swift"))
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.copyright = "© 2026 david-swift"
|
||||||
|
cfg.license = "MIT"
|
||||||
|
cfg.releaseNotes = demoReleaseNotes
|
||||||
|
cfg.comments = demoComments
|
||||||
|
|
||||||
|
cfg.credits = [
|
||||||
|
.init(role: .developer, name: "Jane Doe"),
|
||||||
|
.init(role: .developer, name: "John Roe"),
|
||||||
|
.init(role: .designer, name: "Mika Sato"),
|
||||||
|
.init(role: .artist, name: "Leo Martins"),
|
||||||
|
.init(role: .translator, name: "Yuki Nakamura"),
|
||||||
|
.init(role: .translator, name: "Tod Brown")
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.acknowledgements = [
|
||||||
|
.init(title: "Special Thanks", name: "GNOME Project"),
|
||||||
|
.init(title: "Special Thanks", name: "Swift Programming Language"),
|
||||||
|
.init(title: "Additional Support", name: "LibAdwaita Contributors")
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.otherApps = [
|
||||||
|
.init(
|
||||||
|
appID: "io.github.david_swift.Flashcards",
|
||||||
|
name: "Memorize",
|
||||||
|
summary: "An app for creating, studying, and importing flashcard sets with a built‑in test mode."
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable missing_docs
|
||||||
@ -150,15 +150,7 @@ struct Demo: App {
|
|||||||
}
|
}
|
||||||
.collapsed(!wide)
|
.collapsed(!wide)
|
||||||
.breakpoint(minWidth: 550, matches: $wide)
|
.breakpoint(minWidth: 550, matches: $wide)
|
||||||
.aboutDialog(
|
.aboutDialog(visible: $about, configure: AboutDialogDemo.sample)
|
||||||
visible: $about,
|
|
||||||
app: "Demo",
|
|
||||||
developer: "david-swift",
|
|
||||||
version: "Test",
|
|
||||||
icon: .default(icon: .applicationXExecutable),
|
|
||||||
website: .init(string: "https://adwaita-swift.aparoksha.dev/"),
|
|
||||||
issues: .init(string: "https://git.aparoksha.dev/aparoksha/adwaita-swift/issues")
|
|
||||||
)
|
|
||||||
.preferencesDialog(visible: $preferences)
|
.preferencesDialog(visible: $preferences)
|
||||||
.preferencesPage("Page 1", icon: .default(icon: .audioHeadset)) { page in
|
.preferencesPage("Page 1", icon: .default(icon: .audioHeadset)) { page in
|
||||||
page
|
page
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user