| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import Cocoa
- enum SidebarDestination: Int, CaseIterable {
- case home
- case scan
- case scanAndHome
- case settings
- }
- final class SidebarView: NSView {
- var onDestinationSelected: ((SidebarDestination) -> Void)?
- private var navItems: [SidebarNavItem] = []
- init() {
- super.init(frame: .zero)
- wantsLayer = true
- layer?.backgroundColor = AppTheme.sidebarBackground.cgColor
- translatesAutoresizingMaskIntoConstraints = false
- setup()
- }
- @available(*, unavailable)
- required init?(coder: NSCoder) { nil }
- func select(_ destination: SidebarDestination) {
- for (index, item) in navItems.enumerated() {
- item.isSelected = index == destination.rawValue
- }
- }
- private func setup() {
- let logoContainer = NSView()
- logoContainer.translatesAutoresizingMaskIntoConstraints = false
- let logoIcon = NSImageView()
- logoIcon.translatesAutoresizingMaskIntoConstraints = false
- if let image = NSImage(systemSymbolName: "printer.fill", accessibilityDescription: "Smart Printer") {
- let config = NSImage.SymbolConfiguration(pointSize: 28, weight: .medium)
- logoIcon.image = image.withSymbolConfiguration(config)
- }
- logoIcon.contentTintColor = AppTheme.purple
- let appNameLabel = NSTextField(labelWithString: "Smart Printer")
- appNameLabel.font = AppTheme.semiboldFont(size: 15)
- appNameLabel.textColor = AppTheme.textPrimary
- appNameLabel.alignment = .center
- appNameLabel.translatesAutoresizingMaskIntoConstraints = false
- let navStack = NSStackView()
- navStack.orientation = .vertical
- navStack.spacing = 4
- navStack.alignment = .leading
- navStack.translatesAutoresizingMaskIntoConstraints = false
- let bottomNavStack = NSStackView()
- bottomNavStack.orientation = .vertical
- bottomNavStack.spacing = 4
- bottomNavStack.alignment = .leading
- bottomNavStack.translatesAutoresizingMaskIntoConstraints = false
- let homeItem = SidebarNavItem(title: "Home", symbolName: "house.fill", isSelected: true)
- let scanItem = SidebarNavItem(title: "Scan", symbolName: "viewfinder")
- let scanAndHomeItem = SidebarNavItem(title: "Premium", symbolName: "diamond.fill", accent: .premium)
- let settingsItem = SidebarNavItem(title: "Settings", symbolName: "gearshape")
- let mainNavItems = [homeItem, scanItem, scanAndHomeItem]
- navItems = mainNavItems + [settingsItem]
- for (index, item) in navItems.enumerated() {
- item.onClick = { [weak self] in
- guard let self, let destination = SidebarDestination(rawValue: index) else { return }
- self.select(destination)
- self.onDestinationSelected?(destination)
- }
- }
- for item in mainNavItems {
- navStack.addArrangedSubview(item)
- }
- bottomNavStack.addArrangedSubview(settingsItem)
- addSubview(logoContainer)
- logoContainer.addSubview(logoIcon)
- addSubview(appNameLabel)
- addSubview(navStack)
- addSubview(bottomNavStack)
- let divider = NSBox()
- divider.boxType = .separator
- divider.translatesAutoresizingMaskIntoConstraints = false
- addSubview(divider)
- NSLayoutConstraint.activate([
- widthAnchor.constraint(equalToConstant: AppTheme.sidebarWidth),
- logoContainer.topAnchor.constraint(equalTo: topAnchor, constant: 52),
- logoContainer.centerXAnchor.constraint(equalTo: centerXAnchor),
- logoContainer.widthAnchor.constraint(equalToConstant: 48),
- logoContainer.heightAnchor.constraint(equalToConstant: 48),
- logoIcon.centerXAnchor.constraint(equalTo: logoContainer.centerXAnchor),
- logoIcon.centerYAnchor.constraint(equalTo: logoContainer.centerYAnchor),
- logoIcon.widthAnchor.constraint(equalToConstant: 36),
- logoIcon.heightAnchor.constraint(equalToConstant: 36),
- appNameLabel.topAnchor.constraint(equalTo: logoContainer.bottomAnchor, constant: 8),
- appNameLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
- navStack.topAnchor.constraint(equalTo: appNameLabel.bottomAnchor, constant: 32),
- navStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
- navStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
- bottomNavStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
- bottomNavStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
- bottomNavStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -24),
- homeItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
- scanItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
- scanAndHomeItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
- settingsItem.widthAnchor.constraint(equalTo: bottomNavStack.widthAnchor),
- divider.trailingAnchor.constraint(equalTo: trailingAnchor),
- divider.topAnchor.constraint(equalTo: topAnchor),
- divider.bottomAnchor.constraint(equalTo: bottomAnchor),
- divider.widthAnchor.constraint(equalToConstant: 1),
- ])
- }
- }
|