mirror of
https://github.com/yattee/yattee.git
synced 2026-05-13 02:45:03 +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) {
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
LoggingService.shared.logCloudKit("Requesting remote notification registration...")
|
LoggingService.shared.logCloudKit("Requesting remote notification registration...")
|
||||||
NSApplication.shared.registerForRemoteNotifications()
|
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) {
|
func application(_ application: NSApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
import UIKit
|
import UIKit
|
||||||
|
#elseif os(macOS)
|
||||||
|
import AppKit
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extension SettingsManager {
|
extension SettingsManager {
|
||||||
@@ -35,9 +37,8 @@ extension SettingsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - App Icon Settings (iOS only)
|
// MARK: - App Icon Settings
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
var appIcon: AppIcon {
|
var appIcon: AppIcon {
|
||||||
get {
|
get {
|
||||||
if let cached = _appIcon { return cached }
|
if let cached = _appIcon { return cached }
|
||||||
@@ -53,14 +54,53 @@ extension SettingsManager {
|
|||||||
|
|
||||||
// Apply the icon change
|
// Apply the icon change
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
|
#if os(iOS)
|
||||||
do {
|
do {
|
||||||
try await UIApplication.shared.setAlternateIconName(newValue.alternateIconName)
|
try await UIApplication.shared.setAlternateIconName(newValue.alternateIconName)
|
||||||
} catch {
|
} catch {
|
||||||
LoggingService.shared.error("Failed to set alternate icon: \(error)", category: .general)
|
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
|
#endif
|
||||||
|
|
||||||
/// Whether to show a checkmark badge on fully watched video thumbnails.
|
/// 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 {
|
enum AppIcon: String, CaseIterable, Codable {
|
||||||
case `default`
|
case `default`
|
||||||
case classic
|
case classic
|
||||||
@@ -89,7 +88,6 @@ enum AppIcon: String, CaseIterable, Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// MARK: - Video Quality
|
// MARK: - Video Quality
|
||||||
|
|
||||||
|
|||||||
@@ -203,9 +203,7 @@ final class SettingsManager {
|
|||||||
|
|
||||||
// Appearance settings
|
// Appearance settings
|
||||||
var _listStyle: VideoListStyle?
|
var _listStyle: VideoListStyle?
|
||||||
#if os(iOS)
|
|
||||||
var _appIcon: AppIcon?
|
var _appIcon: AppIcon?
|
||||||
#endif
|
|
||||||
|
|
||||||
// Video Swipe Actions
|
// Video Swipe Actions
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ struct AppearanceSettingsView: View {
|
|||||||
ThemeSection(settings: settings)
|
ThemeSection(settings: settings)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// App icon section (iOS only)
|
// App icon section
|
||||||
#if os(iOS)
|
#if !os(tvOS)
|
||||||
AppIconSection(settings: settings)
|
AppIconSection(settings: settings)
|
||||||
#endif
|
#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 {
|
private struct AppIconSection: View {
|
||||||
@Bindable var settings: SettingsManager
|
@Bindable var settings: SettingsManager
|
||||||
|
|
||||||
@@ -131,7 +131,9 @@ private struct AppIconPickerView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(String(localized: "settings.appearance.appIcon.header"))
|
.navigationTitle(String(localized: "settings.appearance.appIcon.header"))
|
||||||
|
#if os(iOS)
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user