From 62db63df4fb3756844484d478619cea612e66d75 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Thu, 15 Aug 2024 12:15:37 +0200 Subject: [PATCH] feat: added an option to hide disks in the popup view (#1862) --- Kit/helpers.swift | 30 ++++++++++++++++++++++++++-- Modules/Disk/main.swift | 5 +++++ Modules/Disk/popup.swift | 40 ++++++++++++++++++++++++++++++-------- Modules/Disk/readers.swift | 3 +++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/Kit/helpers.swift b/Kit/helpers.swift index 0937cb7d..16433ef0 100644 --- a/Kit/helpers.swift +++ b/Kit/helpers.swift @@ -1207,11 +1207,14 @@ var isDarkMode: Bool { public class PreferencesSection: NSStackView { private let container: NSStackView = NSStackView() - public init(label: String = "", _ components: [NSView] = []) { + public init(label: String = "", id: String? = nil, _ components: [NSView] = []) { super.init(frame: .zero) self.orientation = .vertical self.spacing = 0 + if let id { + self.identifier = NSUserInterfaceItemIdentifier(id) + } if label != "" { self.addLabel(label) @@ -1271,6 +1274,25 @@ public class PreferencesSection: NSStackView { self.container.addArrangedSubview(view) } + public func delete(_ id: String) { + let views = self.container.subviews.filter({ $0.identifier != nil }) + views.enumerated().forEach { (i, v) in + guard v.identifier?.rawValue == id else { return } + if self.container.subviews.indices.contains(i-1) { + let prev = self.container.subviews[i-1] + if prev.identifier?.rawValue == "PreferencesSeparator" { + prev.removeFromSuperview() + } + } + v.removeFromSuperview() + } + return + } + + public func contains(_ id: String) -> Bool { + self.container.subviews.contains(where: { $0.identifier?.rawValue == id }) + } + public func toggleVisibility(_ at: Int, newState: Bool) { for i in self.container.subviews.indices where i/2 == at && Double(i).remainder(dividingBy: 2) == 0 { self.container.subviews[i-1].isHidden = !newState @@ -1285,6 +1307,7 @@ private class PreferencesSeparator: NSView { self.wantsLayer = true self.layer?.backgroundColor = NSColor.separatorColor.withAlphaComponent(0.05).cgColor self.heightAnchor.constraint(equalToConstant: 1).isActive = true + self.identifier = NSUserInterfaceItemIdentifier("PreferencesSeparator") } required init?(coder: NSCoder) { @@ -1297,7 +1320,7 @@ private class PreferencesSeparator: NSView { } public class PreferencesRow: NSStackView { - public init(_ title: String? = nil, _ description: String? = nil, component: NSView) { + public init(_ title: String? = nil, _ description: String? = nil, id: String? = nil, component: NSView) { super.init(frame: .zero) self.orientation = .horizontal @@ -1305,6 +1328,9 @@ public class PreferencesRow: NSStackView { self.alignment = .centerY self.edgeInsets = NSEdgeInsets(top: Constants.Settings.margin/2, left: 0, bottom: (Constants.Settings.margin/2) - 1, right: 0) self.spacing = 0 + if let id { + self.identifier = NSUserInterfaceItemIdentifier(id) + } self.addArrangedSubview(self.text(title, description)) self.addArrangedSubview(NSView()) diff --git a/Modules/Disk/main.swift b/Modules/Disk/main.swift index ea38a3eb..73ff360d 100644 --- a/Modules/Disk/main.swift +++ b/Modules/Disk/main.swift @@ -29,6 +29,7 @@ public struct smart_t: Codable { public struct drive: Codable { var parent: io_object_t = 0 + var uuid: String = "" var mediaName: String = "" var BSDName: String = "" @@ -55,6 +56,10 @@ public struct drive: Codable { } return Double(usedSpace) / Double(total) } + + public var popupState: Bool { + Store.shared.bool(key: "Disk_\(self.uuid)_popup", defaultValue: true) + } } public class Disks: Codable { diff --git a/Modules/Disk/popup.swift b/Modules/Disk/popup.swift index b7bf37fb..6bfe145d 100644 --- a/Modules/Disk/popup.swift +++ b/Modules/Disk/popup.swift @@ -39,6 +39,9 @@ internal class Popup: PopupWrapper { private var processes: ProcessesView? = nil private var processesView: NSView? = nil + private let settingsSection = PreferencesSection(label: "Drives") + private var lastList: [String] = [] + public init(_ module: ModuleType) { self.title = module.rawValue @@ -99,22 +102,37 @@ internal class Popup: PopupWrapper { if h > 0 && self.disks.frame.size.height != h { self.disks.setFrameSize(NSSize(width: self.frame.width, height: h)) self.recalculateHeight() + } else if h < 0 && self.disks.frame.size.height != 0 { + self.disks.setFrameSize(NSSize(width: self.frame.width, height: 0)) + self.recalculateHeight() + } + self.lastList = value.array.compactMap{ $0.uuid } + } + + self.lastList.filter { !value.map { $0.uuid }.contains($0) }.forEach { self.settingsSection.delete($0) } + value.forEach { (drive: drive) in + if !self.settingsSection.contains(drive.uuid) { + let btn = switchView( + action: #selector(self.toggleDisk), + state: drive.popupState + ) + btn.identifier = NSUserInterfaceItemIdentifier(drive.uuid) + self.settingsSection.add(PreferencesRow(drive.mediaName, id: drive.uuid, component: btn)) } } self.disks.subviews.filter{ $0 is DiskView }.map{ $0 as! DiskView }.forEach { (v: DiskView) in - if !value.map({$0.BSDName}).contains(v.BSDName) { + if !value.array.filter({ $0.popupState }).map({$0.uuid}).contains(v.uuid) { v.removeFromSuperview() } } - - value.forEach { (drive: drive) in - if let view = self.disks.subviews.filter({ $0 is DiskView }).map({ $0 as! DiskView }).first(where: { $0.BSDName == drive.BSDName }) { + value.array.filter({ $0.popupState }).forEach { (drive: drive) in + if let view = self.disks.subviews.filter({ $0 is DiskView }).map({ $0 as! DiskView }).first(where: { $0.uuid == drive.uuid }) { view.update(free: drive.free, smart: drive.smart) } else { self.disks.addArrangedSubview(DiskView( width: Constants.Popup.width, - BSDName: drive.BSDName, + uuid: drive.uuid, name: drive.mediaName, size: drive.size, free: drive.free, @@ -192,6 +210,8 @@ internal class Popup: PopupWrapper { )) ])) + view.addArrangedSubview(self.settingsSection) + return view } @@ -231,11 +251,15 @@ internal class Popup: PopupWrapper { Store.shared.set(key: "\(self.title)_reverseOrder", value: self.reverseOrderState) self.display() } + @objc private func toggleDisk(_ sender: NSControl) { + guard let id = sender.identifier else { return } + Store.shared.set(key: "\(self.title)_\(id.rawValue)_popup", value: controlState(sender)) + } } internal class DiskView: NSStackView { public var name: String - public var BSDName: String + public var uuid: String private var nameView: NameView private var chartView: ChartView @@ -246,8 +270,8 @@ internal class DiskView: NSStackView { private var temperatureView: TemperatureView? private var lifeView: LifeView? - init(width: CGFloat, BSDName: String = "", name: String = "", size: Int64 = 1, free: Int64 = 1, path: URL? = nil, smart: smart_t? = nil) { - self.BSDName = BSDName + init(width: CGFloat, uuid: String = "", name: String = "", size: Int64 = 1, free: Int64 = 1, path: URL? = nil, smart: smart_t? = nil) { + self.uuid = uuid self.name = name let innerWidth: CGFloat = width - (Constants.Popup.margins * 2) self.nameView = NameView(width: innerWidth, name: name, size: size, free: free, path: path) diff --git a/Modules/Disk/readers.swift b/Modules/Disk/readers.swift index 0afa0632..306aeb65 100644 --- a/Modules/Disk/readers.swift +++ b/Modules/Disk/readers.swift @@ -280,6 +280,9 @@ private func driveDetails(_ disk: DADisk, removableState: Bool) -> drive? { } } + if let mediaUUID = dict[kDADiskDescriptionMediaUUIDKey as String] { + d.uuid = CFUUIDCreateString(kCFAllocatorDefault, (mediaUUID as! CFUUID)) as String + } if let mediaName = dict[kDADiskDescriptionVolumeNameKey as String] { d.mediaName = mediaName as! String if d.mediaName == "Recovery" {