diff --git a/Sources/Gitify/App/GitifyApp.swift b/Sources/Gitify/App/GitifyApp.swift index cbcb0ef..c0be7e0 100644 --- a/Sources/Gitify/App/GitifyApp.swift +++ b/Sources/Gitify/App/GitifyApp.swift @@ -45,20 +45,22 @@ final class AppDelegate: NSObject, NSApplicationDelegate { // (e.g. `swift run`), where Info.plist's CFBundleIconFile doesn't apply. // Inside a .app bundle the icon is already set via Info.plist's CFBundleIconFile, // so we only attempt this when the SwiftPM resource bundle is available. - if let url = resourceBundle?.url(forResource: "AppIcon", withExtension: "icns"), + if let url = Bundle.safeModule?.url(forResource: "AppIcon", withExtension: "icns"), let image = NSImage(contentsOf: url) { NSApplication.shared.applicationIconImage = image } } +} - /// Returns the SwiftPM resource bundle if it exists, or nil. - /// `Bundle.module` calls fatalError when the bundle is missing, so we +extension Bundle { + /// Returns the SwiftPM resource bundle if it exists, or `nil`. + /// `Bundle.module` calls `fatalError` when the bundle is missing, so we /// replicate its lookup logic without the fatal trap. - private var resourceBundle: Bundle? { + static var safeModule: Bundle? { let bundleName = "Gitify_Gitify" let candidates = [ Bundle.main.resourceURL, - Bundle(for: AppDelegate.self).resourceURL, + Bundle.main.bundleURL, ] for candidate in candidates { if let url = candidate?.appendingPathComponent(bundleName + ".bundle"), diff --git a/Sources/Gitify/Views/RootView.swift b/Sources/Gitify/Views/RootView.swift index 851472d..7fe0992 100644 --- a/Sources/Gitify/Views/RootView.swift +++ b/Sources/Gitify/Views/RootView.swift @@ -56,7 +56,8 @@ struct RootView: View { .task { let version = currentAppVersion guard version != AppDefaults.lastSeenVersion else { return } - guard let url = Bundle.module.url(forResource: "CHANGELOG", withExtension: "md"), + guard let bundle = Bundle.safeModule, + let url = bundle.url(forResource: "CHANGELOG", withExtension: "md"), let text = try? String(contentsOf: url, encoding: .utf8) else { return } let entries = ChangelogParser.parse(text) guard !entries.isEmpty else { return }