commit bc368db575bb1538da1849d69d20343a372bdf7f Author: Serhiy Mytrovtsiy Date: Wed May 29 21:25:14 2019 +0200 initial init diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4afbdf09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Pods +.DS_Store +build diff --git a/Mini Stats.xcodeproj/project.pbxproj b/Mini Stats.xcodeproj/project.pbxproj new file mode 100755 index 00000000..6b8eec8e --- /dev/null +++ b/Mini Stats.xcodeproj/project.pbxproj @@ -0,0 +1,390 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 9A1410F9229E721100D29793 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1410F8229E721100D29793 /* AppDelegate.swift */; }; + 9A1410FD229E721200D29793 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9A1410FC229E721200D29793 /* Assets.xcassets */; }; + 9A141100229E721200D29793 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A1410FE229E721200D29793 /* Main.storyboard */; }; + 9A5B1CB6229E73BB008B9D3C /* StatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CB4229E73BB008B9D3C /* StatusBarView.swift */; }; + 9A5B1CB7229E73BB008B9D3C /* StatusBarView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A5B1CB5229E73BB008B9D3C /* StatusBarView.xib */; }; + 9A5B1CB9229E7664008B9D3C /* CpuUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CB8229E7664008B9D3C /* CpuUsage.swift */; }; + 9A5B1CBC229E78B3008B9D3C /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CBB229E78B3008B9D3C /* Store.swift */; }; + 9A5B1CBF229E78F0008B9D3C /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CBE229E78F0008B9D3C /* Observable.swift */; }; + 9A5B1CC1229E7A1C008B9D3C /* NilLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CC0229E7A1C008B9D3C /* NilLoadable.swift */; }; + 9A5B1CC5229E7B40008B9D3C /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CC4229E7B40008B9D3C /* Extensions.swift */; }; + 9A5B1CC7229E7F44008B9D3C /* MemoryUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CC6229E7F44008B9D3C /* MemoryUsage.swift */; }; + 9A5B1CC9229E8621008B9D3C /* DiskUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5B1CC8229E8621008B9D3C /* DiskUsage.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9A1410F5229E721100D29793 /* Mini Stats.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mini Stats.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9A1410F8229E721100D29793 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 9A1410FC229E721200D29793 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 9A1410FF229E721200D29793 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9A141101229E721200D29793 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9A141102229E721200D29793 /* Mini_Stats.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mini_Stats.entitlements; sourceTree = ""; }; + 9A5B1CB4229E73BB008B9D3C /* StatusBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarView.swift; sourceTree = ""; }; + 9A5B1CB5229E73BB008B9D3C /* StatusBarView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusBarView.xib; sourceTree = ""; }; + 9A5B1CB8229E7664008B9D3C /* CpuUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CpuUsage.swift; sourceTree = ""; }; + 9A5B1CBB229E78B3008B9D3C /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; + 9A5B1CBE229E78F0008B9D3C /* Observable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = ""; }; + 9A5B1CC0229E7A1C008B9D3C /* NilLoadable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NilLoadable.swift; sourceTree = ""; }; + 9A5B1CC4229E7B40008B9D3C /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + 9A5B1CC6229E7F44008B9D3C /* MemoryUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryUsage.swift; sourceTree = ""; }; + 9A5B1CC8229E8621008B9D3C /* DiskUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskUsage.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9A1410F2229E721100D29793 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9A1410EC229E721100D29793 = { + isa = PBXGroup; + children = ( + 9A1410F7229E721100D29793 /* Mini Stats */, + 9A1410F6229E721100D29793 /* Products */, + ); + sourceTree = ""; + }; + 9A1410F6229E721100D29793 /* Products */ = { + isa = PBXGroup; + children = ( + 9A1410F5229E721100D29793 /* Mini Stats.app */, + ); + name = Products; + sourceTree = ""; + }; + 9A1410F7229E721100D29793 /* Mini Stats */ = { + isa = PBXGroup; + children = ( + 9A5B1CBD229E78D2008B9D3C /* libs */, + 9A5B1CBA229E7892008B9D3C /* Readers */, + 9A5B1CB3229E72A7008B9D3C /* Supporting Files */, + 9A1410F8229E721100D29793 /* AppDelegate.swift */, + 9A5B1CB4229E73BB008B9D3C /* StatusBarView.swift */, + 9A5B1CB5229E73BB008B9D3C /* StatusBarView.xib */, + 9A5B1CBB229E78B3008B9D3C /* Store.swift */, + ); + path = "Mini Stats"; + sourceTree = ""; + }; + 9A5B1CB3229E72A7008B9D3C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9A1410FC229E721200D29793 /* Assets.xcassets */, + 9A1410FE229E721200D29793 /* Main.storyboard */, + 9A141101229E721200D29793 /* Info.plist */, + 9A141102229E721200D29793 /* Mini_Stats.entitlements */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + 9A5B1CBA229E7892008B9D3C /* Readers */ = { + isa = PBXGroup; + children = ( + 9A5B1CB8229E7664008B9D3C /* CpuUsage.swift */, + 9A5B1CC6229E7F44008B9D3C /* MemoryUsage.swift */, + 9A5B1CC8229E8621008B9D3C /* DiskUsage.swift */, + ); + path = Readers; + sourceTree = ""; + }; + 9A5B1CBD229E78D2008B9D3C /* libs */ = { + isa = PBXGroup; + children = ( + 9A5B1CBE229E78F0008B9D3C /* Observable.swift */, + 9A5B1CC0229E7A1C008B9D3C /* NilLoadable.swift */, + 9A5B1CC4229E7B40008B9D3C /* Extensions.swift */, + ); + path = libs; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9A1410F4229E721100D29793 /* Mini Stats */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9A141105229E721200D29793 /* Build configuration list for PBXNativeTarget "Mini Stats" */; + buildPhases = ( + 9A1410F1229E721100D29793 /* Sources */, + 9A1410F2229E721100D29793 /* Frameworks */, + 9A1410F3229E721100D29793 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Mini Stats"; + productName = "Mini Stats"; + productReference = 9A1410F5229E721100D29793 /* Mini Stats.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9A1410ED229E721100D29793 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1020; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "Serhiy Mytrovtsiy"; + TargetAttributes = { + 9A1410F4229E721100D29793 = { + CreatedOnToolsVersion = 10.2.1; + }; + }; + }; + buildConfigurationList = 9A1410F0229E721100D29793 /* Build configuration list for PBXProject "Mini Stats" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9A1410EC229E721100D29793; + productRefGroup = 9A1410F6229E721100D29793 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9A1410F4229E721100D29793 /* Mini Stats */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9A1410F3229E721100D29793 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A5B1CB7229E73BB008B9D3C /* StatusBarView.xib in Resources */, + 9A1410FD229E721200D29793 /* Assets.xcassets in Resources */, + 9A141100229E721200D29793 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9A1410F1229E721100D29793 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A5B1CB6229E73BB008B9D3C /* StatusBarView.swift in Sources */, + 9A5B1CC1229E7A1C008B9D3C /* NilLoadable.swift in Sources */, + 9A5B1CC7229E7F44008B9D3C /* MemoryUsage.swift in Sources */, + 9A5B1CBF229E78F0008B9D3C /* Observable.swift in Sources */, + 9A1410F9229E721100D29793 /* AppDelegate.swift in Sources */, + 9A5B1CC9229E8621008B9D3C /* DiskUsage.swift in Sources */, + 9A5B1CB9229E7664008B9D3C /* CpuUsage.swift in Sources */, + 9A5B1CBC229E78B3008B9D3C /* Store.swift in Sources */, + 9A5B1CC5229E7B40008B9D3C /* Extensions.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9A1410FE229E721200D29793 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9A1410FF229E721200D29793 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9A141103229E721200D29793 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 9A141104229E721200D29793 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 9A141106229E721200D29793 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Mini Stats/Supporting Files/Mini_Stats.entitlements"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = RP2S87B72W; + INFOPLIST_FILE = "$(SRCROOT)/Mini Stats/Supporting Files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = "eu.exelban.Mini-Stats"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + }; + name = Debug; + }; + 9A141107229E721200D29793 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Mini Stats/Supporting Files/Mini_Stats.entitlements"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = RP2S87B72W; + INFOPLIST_FILE = "$(SRCROOT)/Mini Stats/Supporting Files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = "eu.exelban.Mini-Stats"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9A1410F0229E721100D29793 /* Build configuration list for PBXProject "Mini Stats" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9A141103229E721200D29793 /* Debug */, + 9A141104229E721200D29793 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9A141105229E721200D29793 /* Build configuration list for PBXNativeTarget "Mini Stats" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9A141106229E721200D29793 /* Debug */, + 9A141107229E721200D29793 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9A1410ED229E721100D29793 /* Project object */; +} diff --git a/Mini Stats.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Mini Stats.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..25bf5390 --- /dev/null +++ b/Mini Stats.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Mini Stats.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Mini Stats.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/Mini Stats.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Mini Stats.xcodeproj/project.xcworkspace/xcuserdata/samuelgrant.xcuserdatad/UserInterfaceState.xcuserstate b/Mini Stats.xcodeproj/project.xcworkspace/xcuserdata/samuelgrant.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 00000000..be32e2d6 Binary files /dev/null and b/Mini Stats.xcodeproj/project.xcworkspace/xcuserdata/samuelgrant.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100755 index 00000000..fe2b4541 --- /dev/null +++ b/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcschemes/xcschememanagement.plist b/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 00000000..7a1a634f --- /dev/null +++ b/Mini Stats.xcodeproj/xcuserdata/samuelgrant.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Mini Stats.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Mini Stats/AppDelegate.swift b/Mini Stats/AppDelegate.swift new file mode 100755 index 00000000..fa851e5a --- /dev/null +++ b/Mini Stats/AppDelegate.swift @@ -0,0 +1,68 @@ +// +// AppDelegate.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 28.05.2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + var statusItem = NSStatusBar.system.statusItem(withLength: CGFloat(84)) + let statusBarView: StatusBarView = StatusBarView.createFromNib()! + + func applicationDidFinishLaunching(_ aNotification: Notification) { + self.statusItem.length = CGFloat(28 * store.activeWidgets.value) + + let _ = CpuUsage() + let _ = MemoryUsage() + let _ = DiskUsage() + + if let button = statusItem.button { + button.addSubview(statusBarView) + } + statusItem.menu = statusBarView.buildMenu() + + store.activeWidgets.subscribe(observer: self) { (newValue, oldValue) in + self.statusItem.length = CGFloat(28 * newValue) + + if let button = self.statusItem.button { + if newValue == 0 { + self.statusItem.length = NSStatusItem.squareLength + for view in button.subviews { + view.removeFromSuperview() + } + button.image = NSImage(named:NSImage.Name("tray_icon")) + } else { + button.image = nil + button.addSubview(self.statusBarView) + } + } + } + } + + func applicationWillTerminate(_ aNotification: Notification) { + } + + @objc func toggleStatus(_ sender : NSMenuItem) { + let status = sender.state != NSControl.StateValue.on + sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on + + switch sender.title { + case "CPU": + store.cpuStatus << status + case "Memory": + store.memoryStatus << status + case "Disk": + store.diskStatus << status + case "Colors": + store.colors << status + return + default: break + } + + store.activeWidgets << (status ? store.activeWidgets.value+1 : store.activeWidgets.value-1) + } +} diff --git a/Mini Stats/Readers/CpuUsage.swift b/Mini Stats/Readers/CpuUsage.swift new file mode 100755 index 00000000..e555cae8 --- /dev/null +++ b/Mini Stats/Readers/CpuUsage.swift @@ -0,0 +1,81 @@ +// +// CpuUsage.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation + +class CpuUsage { + var cpuInfo: processor_info_array_t! + var prevCpuInfo: processor_info_array_t? + var numCpuInfo: mach_msg_type_number_t = 0 + var numPrevCpuInfo: mach_msg_type_number_t = 0 + var numCPUs: uint = 0 + var updateTimer: Timer! + let CPUUsageLock: NSLock = NSLock() + + init() { + let mibKeys: [Int32] = [ CTL_HW, HW_NCPU ] + mibKeys.withUnsafeBufferPointer() { mib in + var sizeOfNumCPUs: size_t = MemoryLayout.size + let status = sysctl(processor_info_array_t(mutating: mib.baseAddress), 2, &numCPUs, &sizeOfNumCPUs, nil, 0) + if status != 0 { + numCPUs = 1 + } + read() + updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + } + } + + @objc func read() { + var numCPUsU: natural_t = 0 + let err: kern_return_t = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUsU, &cpuInfo, &numCpuInfo); + if err == KERN_SUCCESS { + CPUUsageLock.lock() + + var inUseOnAllCores: Int32 = 0 + var totalOnAllCores: Int32 = 0 + for i in 0 ..< Int32(numCPUs) { + var inUse: Int32 + var total: Int32 + if let prevCpuInfo = prevCpuInfo { + inUse = cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)] + - prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)] + + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)] + - prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)] + + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)] + - prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)] + total = inUse + (cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)] + - prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)]) + } else { + inUse = cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)] + + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)] + + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)] + total = inUse + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)] + } + + inUseOnAllCores = inUseOnAllCores + inUse + totalOnAllCores = totalOnAllCores + total + } + store.cpuUsage << (Float(inUseOnAllCores) / Float(totalOnAllCores)) + + CPUUsageLock.unlock() + + if let prevCpuInfo = prevCpuInfo { + let prevCpuInfoSize: size_t = MemoryLayout.stride * Int(numPrevCpuInfo) + vm_deallocate(mach_task_self_, vm_address_t(bitPattern: prevCpuInfo), vm_size_t(prevCpuInfoSize)) + } + + prevCpuInfo = cpuInfo + numPrevCpuInfo = numCpuInfo + + cpuInfo = nil + numCpuInfo = 0 + } else { + print("Error KERN_SUCCESS!") + } + } +} diff --git a/Mini Stats/Readers/DiskUsage.swift b/Mini Stats/Readers/DiskUsage.swift new file mode 100755 index 00000000..e05943f8 --- /dev/null +++ b/Mini Stats/Readers/DiskUsage.swift @@ -0,0 +1,46 @@ +// +// DiskUsage.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation + +class DiskUsage { + var updateTimer: Timer! + + init() { + read() + updateTimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(read), userInfo: nil, repeats: true) + } + + @objc func read() { + let total = totalDiskSpaceInBytes() + let free = freeDiskSpaceInBytes() + let usedSpace = total - free + + store.diskUsage << (Float(usedSpace) / Float(total)) + } + + func totalDiskSpaceInBytes() -> Int64 { + do { + let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String) + let space = (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value + return space! + } catch { + return 0 + } + } + + func freeDiskSpaceInBytes() -> Int64 { + do { + let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String) + let freeSpace = (systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value + return freeSpace! + } catch { + return 0 + } + } +} diff --git a/Mini Stats/Readers/MemoryUsage.swift b/Mini Stats/Readers/MemoryUsage.swift new file mode 100755 index 00000000..a6ae9365 --- /dev/null +++ b/Mini Stats/Readers/MemoryUsage.swift @@ -0,0 +1,59 @@ +// +// MemoryUsage.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation + +class MemoryUsage { + var updateTimer: Timer! + var totalSize: Float + + init() { + var stats = host_basic_info() + var count = UInt32(MemoryLayout.size / MemoryLayout.size) + + let kerr: kern_return_t = withUnsafeMutablePointer(to: &stats) { + $0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { + host_info(mach_host_self(), HOST_BASIC_INFO, $0, &count) + } + } + + if kerr == KERN_SUCCESS { + self.totalSize = Float(stats.max_mem) + } + else { + self.totalSize = 0 + print("Error with host_info(): " + (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error")) + } + + read() + updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + } + + @objc func read() { + var stats = vm_statistics64() + var count = UInt32(MemoryLayout.size / MemoryLayout.size) + + let kerr: kern_return_t = withUnsafeMutablePointer(to: &stats) { + $0.withMemoryRebound(to: integer_t.self, capacity: 1) { + host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count) + } + } + + if kerr == KERN_SUCCESS { +// let active = Float(stats.active_count) * Float(PAGE_SIZE) + let inactive = Float(stats.inactive_count) * Float(PAGE_SIZE) +// let wired = Float(stats.wire_count) * Float(PAGE_SIZE) +// let compressed = Float(stats.compressor_page_count) * Float(PAGE_SIZE) + + store.memoryUsage << ((totalSize - inactive) / totalSize) + } + else { + print("Error with host_statistics64(): " + (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error")) + } + } +} diff --git a/Mini Stats/StatusBarView.swift b/Mini Stats/StatusBarView.swift new file mode 100755 index 00000000..2836c4b2 --- /dev/null +++ b/Mini Stats/StatusBarView.swift @@ -0,0 +1,123 @@ +// +// StatusBarView.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 28.05.2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Cocoa + +class StatusBarView: NSView, NibLoadable { + @IBOutlet weak var CPUView: NSView! + @IBOutlet weak var CPUTitleLabel: NSTextField! + @IBOutlet weak var CPUValueLabel: NSTextField! + @IBOutlet weak var MemoryView: NSView! + @IBOutlet weak var MemoryTitleLabel: NSTextField! + @IBOutlet weak var MemoryValueLabel: NSTextField! + @IBOutlet weak var DiskView: NSView! + @IBOutlet weak var DiskTitleLabel: NSTextField! + @IBOutlet weak var DiskValueLabel: NSTextField! + + override init(frame: CGRect) { + super.init(frame: frame) + prepare() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + prepare() + } + + func prepare() { + if store.cpuUsage.value != 0 { + self.CPUValueLabel.stringValue = "\(Int(Float(store.cpuUsage.value.roundTo(decimalPlaces: 2))! * 100))%" + self.CPUValueLabel.textColor = store.cpuUsage.value.usageColor() + } + if store.memoryUsage.value != 0 { + self.MemoryValueLabel.stringValue = "\(Int(Float(store.memoryUsage.value.roundTo(decimalPlaces: 2))! * 100))%" + self.MemoryValueLabel.textColor = store.memoryUsage.value.usageColor() + } + if store.diskUsage.value != 0 { + self.DiskValueLabel.stringValue = "\(Int(Float(store.diskUsage.value.roundTo(decimalPlaces: 2))! * 100))%" + self.DiskValueLabel.textColor = store.diskUsage.value.usageColor() + } + + store.cpuUsage.subscribe(observer: self) { (newValue, _) in + let percentage = Int(Float(newValue.roundTo(decimalPlaces: 2))! * 100) + self.CPUValueLabel.stringValue = "\(percentage)%" + if store.colors.value { + self.CPUValueLabel.textColor = newValue.usageColor() + } + } + store.memoryUsage.subscribe(observer: self) { (newValue, _) in + let percentage = Int(Float(newValue.roundTo(decimalPlaces: 2))! * 100) + self.MemoryValueLabel.stringValue = "\(percentage)%" + if store.colors.value { + self.MemoryValueLabel.textColor = newValue.usageColor() + } + } + store.diskUsage.subscribe(observer: self) { (newValue, _) in + let percentage = Int(Float(newValue.roundTo(decimalPlaces: 2))! * 100) + self.DiskValueLabel.stringValue = "\(percentage)%" + if store.colors.value { + self.DiskValueLabel.textColor = newValue.usageColor() + } + } + + store.cpuStatus.subscribe(observer: self) { (newValue, _) in + self.CPUView.isHidden = !newValue + } + store.memoryStatus.subscribe(observer: self) { (newValue, _) in + self.MemoryView.isHidden = !newValue + } + store.diskStatus.subscribe(observer: self) { (newValue, _) in + self.DiskView.isHidden = !newValue + } + + store.activeWidgets.subscribe(observer: self) { (newValue, _) in + self.frame = CGRect(x: 0 , y: 0, width: CGFloat(28 * newValue), height: self.frame.height) + } + + store.colors.subscribe(observer: self) { (newValue, _) in + if newValue { + self.CPUValueLabel.textColor = store.cpuUsage.value.usageColor() + self.MemoryValueLabel.textColor = store.memoryUsage.value.usageColor() + self.DiskValueLabel.textColor = store.diskUsage.value.usageColor() + } else { + self.CPUValueLabel.textColor = NSColor.labelColor + self.MemoryValueLabel.textColor = NSColor.labelColor + self.DiskValueLabel.textColor = NSColor.labelColor + } + } + } + + func buildMenu() -> NSMenu { + let menu = NSMenu() + + let cpuStatus = NSMenuItem(title: "CPU", action: #selector(AppDelegate.toggleStatus(_:)), keyEquivalent: "") + cpuStatus.state = NSControl.StateValue.on + cpuStatus.isEnabled = true + + let memoryStatus = NSMenuItem(title: "Memory", action: #selector(AppDelegate.toggleStatus(_:)), keyEquivalent: "") + memoryStatus.state = NSControl.StateValue.on + + let diskStatus = NSMenuItem(title: "Disk", action: #selector(AppDelegate.toggleStatus(_:)), keyEquivalent: "") + diskStatus.state = NSControl.StateValue.on + + menu.addItem(cpuStatus) + menu.addItem(memoryStatus) + menu.addItem(diskStatus) + + menu.addItem(NSMenuItem.separator()) + + let colorStatus = NSMenuItem(title: "Colors", action: #selector(AppDelegate.toggleStatus(_:)), keyEquivalent: "") + colorStatus.state = store.colors.value ? NSControl.StateValue.on : NSControl.StateValue.off + menu.addItem(colorStatus) + + menu.addItem(NSMenuItem.separator()) + menu.addItem(NSMenuItem(title: "Quit Mini Stats", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "")) + + return menu + } +} diff --git a/Mini Stats/StatusBarView.xib b/Mini Stats/StatusBarView.xib new file mode 100755 index 00000000..bb03c13f --- /dev/null +++ b/Mini Stats/StatusBarView.xib @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mini Stats/Store.swift b/Mini Stats/Store.swift new file mode 100755 index 00000000..6c07afd8 --- /dev/null +++ b/Mini Stats/Store.swift @@ -0,0 +1,68 @@ +// +// Store.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation + +class Store { + let defaults = UserDefaults.standard + + let cpuUsage: Observable + let memoryUsage: Observable + let diskUsage: Observable + + let cpuStatus: Observable + let memoryStatus: Observable + let diskStatus: Observable + + let colors: Observable + + let activeWidgets: Observable + + init() { + cpuUsage = Observable(0) + memoryUsage = Observable(0) + diskUsage = Observable(0) + + cpuStatus = Observable(true) + memoryStatus = Observable(true) + diskStatus = Observable(true) + + activeWidgets = Observable(3) + + colors = Observable(false) + + if UserDefaults.standard.object(forKey: "cpuStatus") != nil { + cpuStatus << defaults.bool(forKey: "cpuStatus") + } + if UserDefaults.standard.object(forKey: "memoryStatus") != nil { + memoryStatus << defaults.bool(forKey: "memoryStatus") + } + if UserDefaults.standard.object(forKey: "diskStatus") != nil { + diskStatus << defaults.bool(forKey: "diskStatus") + } + if UserDefaults.standard.object(forKey: "colors") != nil { + colors << defaults.bool(forKey: "colors") + } + + cpuStatus.subscribe(observer: self) { (newValue, _) in + self.defaults.set(newValue, forKey: "cpuStatus") + } + memoryStatus.subscribe(observer: self) { (newValue, _) in + self.defaults.set(newValue, forKey: "memoryStatus") + } + diskStatus.subscribe(observer: self) { (newValue, _) in + self.defaults.set(newValue, forKey: "diskStatus") + } + + colors.subscribe(observer: self) { (newValue, _) in + self.defaults.set(newValue, forKey: "colors") + } + } +} + +var store = Store() diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 00000000..94e59813 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/128.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/128.png new file mode 100644 index 00000000..1eab4a64 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/128.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/16.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/16.png new file mode 100644 index 00000000..d8868afb Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/16.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256-1.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256-1.png new file mode 100644 index 00000000..2dc5066f Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256-1.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256.png new file mode 100644 index 00000000..2dc5066f Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/256.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32-1.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32-1.png new file mode 100644 index 00000000..36340595 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32-1.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32.png new file mode 100644 index 00000000..36340595 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/32.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512-1.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512-1.png new file mode 100644 index 00000000..dcca52bc Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512-1.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512.png new file mode 100644 index 00000000..dcca52bc Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/512.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/64.png b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/64.png new file mode 100644 index 00000000..9592bff9 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/64.png differ diff --git a/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..377279b3 --- /dev/null +++ b/Mini Stats/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "32-1.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "256-1.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "512-1.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Mini Stats/Supporting Files/Assets.xcassets/Contents.json b/Mini Stats/Supporting Files/Assets.xcassets/Contents.json new file mode 100755 index 00000000..da4a164c --- /dev/null +++ b/Mini Stats/Supporting Files/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/Contents.json b/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/Contents.json new file mode 100644 index 00000000..7d2238c2 --- /dev/null +++ b/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tray_icon.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/tray_icon.png b/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/tray_icon.png new file mode 100644 index 00000000..80d20c67 Binary files /dev/null and b/Mini Stats/Supporting Files/Assets.xcassets/tray_icon.imageset/tray_icon.png differ diff --git a/Mini Stats/Supporting Files/Base.lproj/Main.storyboard b/Mini Stats/Supporting Files/Base.lproj/Main.storyboard new file mode 100755 index 00000000..6a3c2bcc --- /dev/null +++ b/Mini Stats/Supporting Files/Base.lproj/Main.storyboard @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mini Stats/Supporting Files/Info.plist b/Mini Stats/Supporting Files/Info.plist new file mode 100755 index 00000000..d1fea60f --- /dev/null +++ b/Mini Stats/Supporting Files/Info.plist @@ -0,0 +1,36 @@ + + + + + LSUIElement + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Mini Stats/Supporting Files/Mini_Stats.entitlements b/Mini Stats/Supporting Files/Mini_Stats.entitlements new file mode 100755 index 00000000..f2ef3ae0 --- /dev/null +++ b/Mini Stats/Supporting Files/Mini_Stats.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Mini Stats/libs/Extensions.swift b/Mini Stats/libs/Extensions.swift new file mode 100755 index 00000000..a2d75924 --- /dev/null +++ b/Mini Stats/libs/Extensions.swift @@ -0,0 +1,34 @@ +// +// Extensions.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation +import Cocoa + +extension Float { + func roundTo(decimalPlaces: Int) -> String { + return NSString(format: "%.\(decimalPlaces)f" as NSString, self) as String + } + + func usageColor() -> NSColor { + switch self { + case 0.6...0.8: + return NSColor.orange + case 0.8...1: + return NSColor.red + default: + return NSColor.green + } + } +} + +public enum Unit : Double { + case byte = 1 + case kilobyte = 1024 + case megabyte = 1048576 + case gigabyte = 1073741824 +} diff --git a/Mini Stats/libs/NilLoadable.swift b/Mini Stats/libs/NilLoadable.swift new file mode 100755 index 00000000..8fa3c854 --- /dev/null +++ b/Mini Stats/libs/NilLoadable.swift @@ -0,0 +1,30 @@ +// +// NilLoadable.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Cocoa + +protocol NibLoadable { + static var nibName: String? { get } + static func createFromNib(in bundle: Bundle) -> Self? +} + +extension NibLoadable where Self: NSView { + + static var nibName: String? { + return String(describing: Self.self) + } + + static func createFromNib(in bundle: Bundle = Bundle.main) -> Self? { + guard let nibName = nibName else { return nil } + var topLevelArray: NSArray? = nil + bundle.loadNibNamed(NSNib.Name(nibName), owner: self, topLevelObjects: &topLevelArray) + guard let results = topLevelArray else { return nil } + let views = Array(results).filter { $0 is Self } + return views.last as? Self + } +} diff --git a/Mini Stats/libs/Observable.swift b/Mini Stats/libs/Observable.swift new file mode 100755 index 00000000..3e3843f8 --- /dev/null +++ b/Mini Stats/libs/Observable.swift @@ -0,0 +1,54 @@ +// +// Observable.swift +// Mini Stats +// +// Created by Serhiy Mytrovtsiy on 29/05/2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Foundation + +protocol ObservableProtocol { + associatedtype T + var value: T { get set } + func subscribe(observer: AnyObject, block: @escaping (_ newValue: T, _ oldValue: T) -> ()) + func unsubscribe(observer: AnyObject) +} + +public final class Observable: ObservableProtocol { + typealias ObserverBlock = (_ newValue: T, _ oldValue: T) -> () + typealias ObserversEntry = (observer: AnyObject, block: ObserverBlock) + private var observers: Array + + init(_ value: T) { + self.value = value + observers = [] + } + + var value: T { + didSet { + observers.forEach { (entry: ObserversEntry) in + let (_, block) = entry + block(value, oldValue) + } + } + } + + func subscribe(observer: AnyObject, block: @escaping ObserverBlock) { + let entry: ObserversEntry = (observer: observer, block: block) + observers.append(entry) + } + + func unsubscribe(observer: AnyObject) { + let filtered = observers.filter { entry in + let (owner, _) = entry + return owner !== observer + } + + observers = filtered + } +} + +func <<(observable: Observable, value: T) { + observable.value = value +}