mirror of
https://github.com/yattee/yattee.git
synced 2026-05-12 10:25:02 +00:00
Enable app icon selection on macOS
This commit is contained in:
@@ -78,6 +78,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
LoggingService.shared.logCloudKit("Requesting remote notification registration...")
|
||||
NSApplication.shared.registerForRemoteNotifications()
|
||||
|
||||
if let rawValue = UserDefaults.standard.string(forKey: "appIcon"),
|
||||
let icon = AppIcon(rawValue: rawValue) {
|
||||
SettingsManager.applyMacAppIcon(icon)
|
||||
}
|
||||
}
|
||||
|
||||
func application(_ application: NSApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
#elseif os(macOS)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
extension SettingsManager {
|
||||
@@ -35,9 +37,8 @@ extension SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - App Icon Settings (iOS only)
|
||||
// MARK: - App Icon Settings
|
||||
|
||||
#if os(iOS)
|
||||
var appIcon: AppIcon {
|
||||
get {
|
||||
if let cached = _appIcon { return cached }
|
||||
@@ -53,14 +54,53 @@ extension SettingsManager {
|
||||
|
||||
// Apply the icon change
|
||||
Task { @MainActor in
|
||||
#if os(iOS)
|
||||
do {
|
||||
try await UIApplication.shared.setAlternateIconName(newValue.alternateIconName)
|
||||
} catch {
|
||||
LoggingService.shared.error("Failed to set alternate icon: \(error)", category: .general)
|
||||
}
|
||||
#elseif os(macOS)
|
||||
SettingsManager.applyMacAppIcon(newValue)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
static func applyMacAppIcon(_ icon: AppIcon) {
|
||||
if icon == .default {
|
||||
NSApp.applicationIconImage = nil
|
||||
} else if let source = NSImage(named: icon.previewImageName) {
|
||||
NSApp.applicationIconImage = makeMacIconImage(from: source)
|
||||
}
|
||||
}
|
||||
|
||||
/// Paints the source image onto a 1024×1024 canvas with the standard macOS
|
||||
/// squircle mask and transparent padding so the Dock renders it like a
|
||||
/// native app icon.
|
||||
private static func makeMacIconImage(from source: NSImage) -> NSImage {
|
||||
let canvasSize: CGFloat = 1024
|
||||
// macOS icon grid: artwork occupies ~824×824 centered in a 1024 canvas,
|
||||
// with a ~185pt corner radius on the masked rect.
|
||||
let artworkSize: CGFloat = 824
|
||||
let cornerRadius: CGFloat = 185
|
||||
let inset = (canvasSize - artworkSize) / 2
|
||||
let artworkRect = NSRect(x: inset, y: inset, width: artworkSize, height: artworkSize)
|
||||
|
||||
let image = NSImage(size: NSSize(width: canvasSize, height: canvasSize))
|
||||
image.lockFocus()
|
||||
let path = NSBezierPath(roundedRect: artworkRect, xRadius: cornerRadius, yRadius: cornerRadius)
|
||||
path.addClip()
|
||||
source.draw(in: artworkRect,
|
||||
from: .zero,
|
||||
operation: .sourceOver,
|
||||
fraction: 1.0,
|
||||
respectFlipped: true,
|
||||
hints: [.interpolation: NSImageInterpolation.high.rawValue])
|
||||
image.unlockFocus()
|
||||
return image
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Whether to show a checkmark badge on fully watched video thumbnails.
|
||||
|
||||
@@ -52,7 +52,6 @@ enum AccentColor: String, CaseIterable, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
enum AppIcon: String, CaseIterable, Codable {
|
||||
case `default`
|
||||
case classic
|
||||
@@ -89,7 +88,6 @@ enum AppIcon: String, CaseIterable, Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - Video Quality
|
||||
|
||||
|
||||
@@ -203,9 +203,7 @@ final class SettingsManager {
|
||||
|
||||
// Appearance settings
|
||||
var _listStyle: VideoListStyle?
|
||||
#if os(iOS)
|
||||
var _appIcon: AppIcon?
|
||||
#endif
|
||||
|
||||
// Video Swipe Actions
|
||||
#if !os(tvOS)
|
||||
|
||||
@@ -18,8 +18,8 @@ struct AppearanceSettingsView: View {
|
||||
ThemeSection(settings: settings)
|
||||
#endif
|
||||
|
||||
// App icon section (iOS only)
|
||||
#if os(iOS)
|
||||
// App icon section
|
||||
#if !os(tvOS)
|
||||
AppIconSection(settings: settings)
|
||||
#endif
|
||||
|
||||
@@ -66,9 +66,9 @@ private struct ThemeSection: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - App Icon Section (iOS only)
|
||||
// MARK: - App Icon Section
|
||||
|
||||
#if os(iOS)
|
||||
#if !os(tvOS)
|
||||
private struct AppIconSection: View {
|
||||
@Bindable var settings: SettingsManager
|
||||
|
||||
@@ -131,7 +131,9 @@ private struct AppIconPickerView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle(String(localized: "settings.appearance.appIcon.header"))
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user