diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index c3b48a3..10e6af2 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -29,6 +29,9 @@ DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */; }; DE1F1A262A8B50D500A88DD8 /* BoxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */; }; DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */; }; + DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */; }; + DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A302A8BD68F00A88DD8 /* Double.swift */; }; + DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */; }; DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2AD3282A824EEB00002D51 /* Accessibility.swift */; }; DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA502A82580400713683 /* MenubarViewModel.swift */; }; DE77BA562A82637900713683 /* StateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE77BA552A82637900713683 /* StateManager.swift */; }; @@ -36,7 +39,7 @@ DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */; }; DE874F542A591F1400FC3B77 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F532A591F1400FC3B77 /* PreferencesView.swift */; }; DE874F572A591F2500FC3B77 /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F562A591F2500FC3B77 /* Icon.swift */; }; - DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */; }; + DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE874F5E2A5935CC00FC3B77 /* String.swift */; }; DEB862D42A85124500278FCD /* cleanCache.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D32A85124500278FCD /* cleanCache.sh */; }; DEB862D92A852C4500278FCD /* brewInGoinfre.sh in Resources */ = {isa = PBXBuildFile; fileRef = DEB862D82A852C4500278FCD /* brewInGoinfre.sh */; }; DEB862DC2A85347400278FCD /* Scripts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEB862DB2A85347400278FCD /* Scripts.swift */; }; @@ -70,6 +73,9 @@ DE1F1A222A8B50D500A88DD8 /* BoxViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewModel.swift; path = Main/BoxViewModel.swift; sourceTree = ""; }; DE1F1A232A8B50D500A88DD8 /* BoxViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoxViewController.swift; path = Main/BoxViewController.swift; sourceTree = ""; }; DE1F1A282A8B50E200A88DD8 /* BoxSizeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxSizeManager.swift; sourceTree = ""; }; + DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; + DE1F1A302A8BD68F00A88DD8 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = ""; }; + DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageConfig.swift; sourceTree = ""; }; DE2AD3282A824EEB00002D51 /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.swift; sourceTree = ""; }; DE77BA502A82580400713683 /* MenubarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenubarViewModel.swift; sourceTree = ""; }; DE77BA552A82637900713683 /* StateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateManager.swift; sourceTree = ""; }; @@ -77,7 +83,7 @@ DE874F4D2A591DEA00FC3B77 /* Hotkey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hotkey.swift; sourceTree = ""; }; DE874F532A591F1400FC3B77 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; DE874F562A591F2500FC3B77 /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; - DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + DE874F5E2A5935CC00FC3B77 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; DEB862D32A85124500278FCD /* cleanCache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = cleanCache.sh; sourceTree = ""; }; DEB862D82A852C4500278FCD /* brewInGoinfre.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = brewInGoinfre.sh; sourceTree = ""; }; DEB862DB2A85347400278FCD /* Scripts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Scripts.swift; path = Box42/Scripts/Scripts.swift; sourceTree = SOURCE_ROOT; }; @@ -125,19 +131,22 @@ DE77BA542A82636500713683 /* Shared */, DE874F512A591EC600FC3B77 /* Preferences */, DE018C0C2A509BDF00FF0AA3 /* Resources */, - DE018C062A509B9000FF0AA3 /* CPU */, + DE018C062A509B9000FF0AA3 /* System */, DE018C082A509BB500FF0AA3 /* WebView */, DE018C0E2A509C0C00FF0AA3 /* Menubar */, ); path = Box42; sourceTree = ""; }; - DE018C062A509B9000FF0AA3 /* CPU */ = { + DE018C062A509B9000FF0AA3 /* System */ = { isa = PBXGroup; children = ( + DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, DE018BE32A509B1700FF0AA3 /* CPU.swift */, + DE1F1A2D2A8BCC9800A88DD8 /* Storage.swift */, + DE1F1A352A8BDDDF00A88DD8 /* StorageConfig.swift */, ); - path = CPU; + path = System; sourceTree = ""; }; DE018C082A509BB500FF0AA3 /* WebView */ = { @@ -166,7 +175,6 @@ DE018BDF2A509B0600FF0AA3 /* Assets.xcassets */, DE018BBE2A5099FA00FF0AA3 /* Info.plist */, DE018C022A509B5D00FF0AA3 /* Main.storyboard */, - DE018BDC2A509AEB00FF0AA3 /* EventMonitor.swift */, DE018BB62A5099F900FF0AA3 /* Box42.xcdatamodeld */, ); path = Resources; @@ -264,8 +272,9 @@ DEF749302A85655E00D987C8 /* Extensions */ = { isa = PBXGroup; children = ( - DE874F5E2A5935CC00FC3B77 /* StringExtension.swift */, + DE874F5E2A5935CC00FC3B77 /* String.swift */, DEF749312A85657600D987C8 /* NSScreen.swift */, + DE1F1A302A8BD68F00A88DD8 /* Double.swift */, ); path = Extensions; sourceTree = ""; @@ -355,7 +364,7 @@ DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, DE018BE42A509B1700FF0AA3 /* CPU.swift in Sources */, - DE874F5F2A5935CC00FC3B77 /* StringExtension.swift in Sources */, + DE874F5F2A5935CC00FC3B77 /* String.swift in Sources */, DE874F4E2A591DEA00FC3B77 /* Hotkey.swift in Sources */, DE1F1A252A8B50D500A88DD8 /* BoxViewModel.swift in Sources */, DE018BB32A5099F900FF0AA3 /* AppDelegate.swift in Sources */, @@ -369,8 +378,11 @@ DE1F1A292A8B50E200A88DD8 /* BoxSizeManager.swift in Sources */, DEB862DC2A85347400278FCD /* Scripts.swift in Sources */, DE1F1A1D2A8B50C500A88DD8 /* BoxContentsViewGroup.swift in Sources */, + DE1F1A362A8BDDDF00A88DD8 /* StorageConfig.swift in Sources */, DE2AD3292A824EEB00002D51 /* Accessibility.swift in Sources */, DE874F572A591F2500FC3B77 /* Icon.swift in Sources */, + DE1F1A2E2A8BCC9800A88DD8 /* Storage.swift in Sources */, + DE1F1A312A8BD68F00A88DD8 /* Double.swift in Sources */, DE018BEA2A509B2100FF0AA3 /* WebViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate index 96111f9..4022600 100644 Binary files a/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate and b/Box42.xcodeproj/project.xcworkspace/xcuserdata/chanheki.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Box42/Extensions/Double.swift b/Box42/Extensions/Double.swift new file mode 100644 index 0000000..c539a74 --- /dev/null +++ b/Box42/Extensions/Double.swift @@ -0,0 +1,12 @@ +// +// Double.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +extension Double { + var roundedToTwoDecimalPlaces: Double { + return (self * 100).rounded() / 100 + } +} diff --git a/Box42/Extensions/StringExtension.swift b/Box42/Extensions/String.swift similarity index 94% rename from Box42/Extensions/StringExtension.swift rename to Box42/Extensions/String.swift index fd1f378..f04a1ed 100644 --- a/Box42/Extensions/StringExtension.swift +++ b/Box42/Extensions/String.swift @@ -1,5 +1,5 @@ // -// StringExtension.swift +// String.swift // Box42 // // Created by Chanhee Kim on 7/8/23. diff --git a/Box42/Main/BoxViewController.swift b/Box42/Main/BoxViewController.swift index 3d378fa..6deded0 100644 --- a/Box42/Main/BoxViewController.swift +++ b/Box42/Main/BoxViewController.swift @@ -47,6 +47,19 @@ class BoxViewController: NSViewController { extension BoxViewController { override func keyDown(with event: NSEvent) { print(event.keyCode) + if event.keyCode == 1 { + StorageConfig.shared.setThreshold(.percentage50) + StorageConfig.shared.setPeriod(.period10s) + } + if event.keyCode == 2 { +// SdtorageConfig.shared.setThreshold(.percentage30) + DispatchQueue.main.async { + StorageConfig.shared.setThreshold(.percentage30) + } + StorageConfig.shared.setPeriod(.period1s) + } + + if event.keyCode == 53 { // Escape 키의 keyCode는 53입니다. print("escape") menubarVCDelegate?.toggleWindow(sender: nil) diff --git a/Box42/Menubar/MenubarViewModel.swift b/Box42/Menubar/MenubarViewModel.swift index d131b10..7a7fb9e 100644 --- a/Box42/Menubar/MenubarViewModel.swift +++ b/Box42/Menubar/MenubarViewModel.swift @@ -38,7 +38,6 @@ class StatusBarViewModel { func startRunning() { statusBar.isRunning = cpu.processCPU(statusBar) -// self.animate() scheduleAnimation() } diff --git a/Box42/Resources/AppDelegate.swift b/Box42/Resources/AppDelegate.swift index 358a56c..e3ea76a 100644 --- a/Box42/Resources/AppDelegate.swift +++ b/Box42/Resources/AppDelegate.swift @@ -10,6 +10,8 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { var menubarController = MenubarViewController() + lazy var storage = Storage() + func applicationWillFinishLaunching(_ notification: Notification) { menubarController.menubarViewControllerInit() @@ -19,6 +21,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { menubarController.menubarViewControllerStart() // alertAccessibility() // hotkey() + storage.storageTimerEvent() } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/Box42/CPU/CPU.swift b/Box42/System/CPU.swift similarity index 99% rename from Box42/CPU/CPU.swift rename to Box42/System/CPU.swift index 1d31df6..f7a8dbf 100644 --- a/Box42/CPU/CPU.swift +++ b/Box42/System/CPU.swift @@ -8,7 +8,7 @@ import Foundation -public class CPU { +class CPU { var cpuTimer: Timer? = nil var usage: (value: Double, description: String) = (0.0, "") diff --git a/Box42/Resources/EventMonitor.swift b/Box42/System/EventMonitor.swift similarity index 74% rename from Box42/Resources/EventMonitor.swift rename to Box42/System/EventMonitor.swift index ca7722b..81234df 100644 --- a/Box42/Resources/EventMonitor.swift +++ b/Box42/System/EventMonitor.swift @@ -7,12 +7,12 @@ import Cocoa -public class EventMonitor { +class EventMonitor { private var monitor: Any? private let mask: NSEvent.EventTypeMask private let handler: (NSEvent?) -> Void - public init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { + init(monitor: Any? = nil, mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) { self.mask = mask self.handler = handler } @@ -21,12 +21,12 @@ public class EventMonitor { stop() } - public func start() { + func start() { print("EventMonitor: Starting") monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler) } - public func stop() { + func stop() { if monitor != nil { print("EventMonitor: Stoping") NSEvent.removeMonitor(monitor!) diff --git a/Box42/System/Storage.swift b/Box42/System/Storage.swift new file mode 100644 index 0000000..8c55f25 --- /dev/null +++ b/Box42/System/Storage.swift @@ -0,0 +1,100 @@ +// +// Storage.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +import Foundation +import Combine + +class Storage { + var storageTimer: Timer? = nil + var usage: (value: Double, description:String) = (0.0, "") + var count = 0 + let gibiByte = Double(1 << 30) + var config: StorageConfig + + private var subscriptions = Set() + + private var availableUsage: Double? + private var usedUsage: Double? + private var totalUsage: Double? + + init(config: StorageConfig = StorageConfig.shared) { + self.config = config + + config.$threshold.sink { [weak self] newThreshold in + self?.storageTimerEvent() + }.store(in: &subscriptions) + + config.$period.sink { [weak self] newPeriod in + self?.storageTimerEvent() + }.store(in: &subscriptions) + } + + func checkStorage() -> Bool { + do { + let fileSystemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()) + if let freeSpace = fileSystemAttributes[.systemFreeSize] as? NSNumber { + availableUsage = freeSpace.doubleValue / gibiByte + } + if let totalSpace = fileSystemAttributes[.systemSize] as? NSNumber { + totalUsage = totalSpace.doubleValue / gibiByte + } + if totalUsage != nil && availableUsage != nil { + usedUsage = totalUsage! - availableUsage! + } + } catch { + print("Error obtaining system storage info: \(error)") + return true + } + return false + } + + func storageTimerEvent(){ + storageTimer?.invalidate() + storageTimer = Timer.scheduledTimer(withTimeInterval: config.period.rawValue, repeats: true, block: { [weak self] _ in + guard let self = self else { return } + + if self.checkStorage() { + print("FileSystem정보를 가져오는데 실패 하였습니다.") + return + } + + if let usedUsage = self.usedUsage, let totalUsage = self.totalUsage, totalUsage != 0 { + let usagePercentage = usedUsage / totalUsage + if usagePercentage < self.config.threshold.rawValue { + self.cleanSh() + self.count += 1 + print(self.count > 5 ? "캐시 문제가 아닙니다. ncdu ~ 를 확인해주세요." : "\(usedUsage.roundedToTwoDecimalPlaces) GB", "Storage used is less than 30%") + } else { + self.count = 0 + } + } else { + print("Failed to get storage usage details") + } + }) + storageTimer?.fire() + } + + func cleanSh() { + if let scriptPath = Bundle.main.path(forResource: "cleanCache", ofType: "sh") { + let task = Process() + task.launchPath = "/bin/sh" + task.arguments = [scriptPath] + + task.launch() + task.waitUntilExit() + + // 실행되었다는 것을 알려주고 싶으면 파이프 뽑아서 하면됨. + } else { + print("Script not found") + } + } + + func change() { + config.setThreshold(.percentage30) + config.setPeriod(.period10s) + } +} diff --git a/Box42/System/StorageConfig.swift b/Box42/System/StorageConfig.swift new file mode 100644 index 0000000..1eec523 --- /dev/null +++ b/Box42/System/StorageConfig.swift @@ -0,0 +1,44 @@ +// +// StorageConfig.swift +// Box42 +// +// Created by Chanhee Kim on 8/16/23. +// + +enum StorageThreshold: Double { + case percentage05 = 0.05 + case percentage10 = 0.1 + case percentage30 = 0.3 + case percentage50 = 0.5 +} + +enum StoragePeriod: Double { + case period1s = 1.0 + case period3s = 3.0 + case period5s = 5.0 + case period10s = 10.0 +} + +import Combine + +class StorageConfig: ObservableObject { + static let shared = StorageConfig() + + @Published var threshold: StorageThreshold + @Published var period: StoragePeriod + + init(_ threshold: StorageThreshold = .percentage05, _ period: StoragePeriod = .period3s) { + self.threshold = threshold + self.period = period + } + + func setThreshold(_ threshold: StorageThreshold) { + self.threshold = threshold + print(self.threshold) + } + + func setPeriod(_ period: StoragePeriod) { + self.period = period + print(self.period) + } +}