🎉 ShotScreen v1.0 - Initial Release
🚀 First official release of ShotScreen with complete feature set: ✨ Core Features: - Advanced screenshot capture system - Multi-monitor support - Professional UI/UX design - Automated update system with Sparkle - Apple notarized & code signed 🛠 Technical Excellence: - Native Swift macOS application - Professional build & deployment pipeline - Comprehensive error handling - Memory optimized performance 📦 Distribution Ready: - Professional DMG packaging - Apple notarization complete - No security warnings for users - Ready for public distribution This is the foundation release that establishes ShotScreen as a premium screenshot tool for macOS.
This commit is contained in:
176
ShotScreen/Sources/ThemeManager.swift
Normal file
176
ShotScreen/Sources/ThemeManager.swift
Normal file
@@ -0,0 +1,176 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Centralized Theme Manager
|
||||
class ThemeManager {
|
||||
static let shared = ThemeManager()
|
||||
|
||||
private init() {}
|
||||
|
||||
// MARK: - System-Aware Colors (automatic light/dark adaptation)
|
||||
|
||||
/// Background colors for containers (GLASS EFFECT zoals stash)
|
||||
var containerBackground: NSColor {
|
||||
// NIEUW: Glass effect achtergrond zoals stash window
|
||||
// Gebruik transparante achtergrond zodat visual effect view erdoor kan
|
||||
return NSColor.clear
|
||||
}
|
||||
|
||||
/// Glass effect background for visual effect views
|
||||
var glassEffectMaterial: NSVisualEffectView.Material {
|
||||
return .hudWindow // Exact hetzelfde als stash window
|
||||
}
|
||||
|
||||
/// Glass effect blending mode
|
||||
var glassEffectBlending: NSVisualEffectView.BlendingMode {
|
||||
return .behindWindow // Exact hetzelfde als stash window
|
||||
}
|
||||
|
||||
/// Glass effect alpha
|
||||
var glassEffectAlpha: CGFloat {
|
||||
return 0.95 // Exact hetzelfde als stash window
|
||||
}
|
||||
|
||||
/// Background colors for secondary containers
|
||||
var secondaryContainerBackground: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor(white: 0.42, alpha: 0.90) // Dark mode: iets lichter
|
||||
} else {
|
||||
return NSColor(white: 0.98, alpha: 0.90) // Light mode: bijna wit
|
||||
}
|
||||
}
|
||||
|
||||
/// Button and icon colors (adaptive)
|
||||
var buttonTintColor: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor(white: 0.95, alpha: 1.0) // Dark mode: wit
|
||||
} else {
|
||||
return NSColor(white: 0.25, alpha: 1.0) // Light mode: donkergrijs
|
||||
}
|
||||
}
|
||||
|
||||
/// Text colors (adaptive)
|
||||
var primaryTextColor: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor.white // Dark mode: wit
|
||||
} else {
|
||||
return NSColor.black // Light mode: zwart
|
||||
}
|
||||
}
|
||||
|
||||
var secondaryTextColor: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor(white: 0.7, alpha: 1.0) // Dark mode: grijs
|
||||
} else {
|
||||
return NSColor(white: 0.4, alpha: 1.0) // Light mode: donkergrijs
|
||||
}
|
||||
}
|
||||
|
||||
/// Filename label text color (adaptive with opacity)
|
||||
var filenameLabelTextColor: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor(white: 0.7, alpha: 1.0) // Dark mode: lichtgrijs
|
||||
} else {
|
||||
return NSColor(white: 0.1, alpha: 1.0) // Light mode: veel donkerder voor betere zichtbaarheid
|
||||
}
|
||||
}
|
||||
|
||||
/// Grid cell icon background (adaptive)
|
||||
var gridCellIconBackground: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor.white.withAlphaComponent(0.25) // Dark mode
|
||||
} else {
|
||||
return NSColor.black.withAlphaComponent(0.25) // Light mode
|
||||
}
|
||||
}
|
||||
|
||||
/// Grid cell text color with hover effect
|
||||
func gridCellTextColor(isHovered: Bool) -> NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return isHovered ? NSColor.white : NSColor.white.withAlphaComponent(0.1)
|
||||
} else {
|
||||
return isHovered ? NSColor.black : NSColor.black.withAlphaComponent(0.1)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Shadow Configuration (adaptive)
|
||||
var shadowColor: NSColor {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return NSColor.black // Dark mode: black shadows
|
||||
} else {
|
||||
return NSColor.black.withAlphaComponent(0.3) // Light mode: lighter shadows
|
||||
}
|
||||
}
|
||||
|
||||
var shadowOpacity: Float {
|
||||
if NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua {
|
||||
return 0.50 // Dark mode: stronger shadows
|
||||
} else {
|
||||
return 0.25 // Light mode: subtle shadows
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Utility Methods
|
||||
|
||||
/// Check if currently in dark mode
|
||||
var isDarkMode: Bool {
|
||||
return NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua
|
||||
}
|
||||
|
||||
/// Debug function to print current theme info
|
||||
func printCurrentTheme() {
|
||||
let mode = isDarkMode ? "DARK" : "LIGHT"
|
||||
print("🎨 THEME DEBUG: Current mode = \(mode)")
|
||||
print("🎨 THEME DEBUG: Container background = GLASS EFFECT (\(glassEffectMaterial.rawValue))")
|
||||
print("🎨 THEME DEBUG: Glass effect alpha = \(glassEffectAlpha)")
|
||||
print("🎨 THEME DEBUG: Button tint = \(buttonTintColor)")
|
||||
print("🎨 THEME DEBUG: Primary text = \(primaryTextColor)")
|
||||
print("🎨 THEME DEBUG: Shadow opacity = \(shadowOpacity)")
|
||||
}
|
||||
|
||||
/// Get hover color for buttons
|
||||
var buttonHoverColor: NSColor {
|
||||
if isDarkMode {
|
||||
return NSColor.white
|
||||
} else {
|
||||
return NSColor.black
|
||||
}
|
||||
}
|
||||
|
||||
/// Get original button color (for hover restoration)
|
||||
var buttonOriginalColor: NSColor {
|
||||
return buttonTintColor
|
||||
}
|
||||
|
||||
// MARK: - Notification for Theme Changes
|
||||
func observeThemeChanges(callback: @escaping () -> Void) {
|
||||
// Observer voor system appearance changes
|
||||
DistributedNotificationCenter.default.addObserver(
|
||||
forName: NSNotification.Name("AppleInterfaceThemeChangedNotification"),
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { _ in
|
||||
print("🎨 THEME: System theme changed - notifying observers")
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SwiftUI Color Extensions
|
||||
extension Color {
|
||||
static var adaptiveContainerBackground: Color {
|
||||
Color(ThemeManager.shared.containerBackground)
|
||||
}
|
||||
|
||||
static var adaptiveSecondaryBackground: Color {
|
||||
Color(ThemeManager.shared.secondaryContainerBackground)
|
||||
}
|
||||
|
||||
static var adaptivePrimaryText: Color {
|
||||
Color(ThemeManager.shared.primaryTextColor)
|
||||
}
|
||||
|
||||
static var adaptiveSecondaryText: Color {
|
||||
Color(ThemeManager.shared.secondaryTextColor)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user