├── .gitignore ├── OptiMac ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon-macOS-Dark-1024x1024@1x.png │ │ └── Contents.json │ ├── MenubarPhoenix.imageset │ │ ├── menu_bar_icon-removebg-preview 2.png │ │ └── Contents.json │ └── AccentColor.colorset │ │ └── Contents.json ├── OptiMacApp.swift ├── StatusBarController.swift └── ContentView.swift ├── OptiMac.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── lukeedgar.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcuserdata │ └── lukeedgar.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── LICENSE ├── .github └── workflows │ └── build-release.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | *.dmg 4 | *.pkg 5 | __pycache__/ 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/AppIcon.appiconset/Icon-macOS-Dark-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VonKleistL/OptiMac/HEAD/OptiMac/Assets.xcassets/AppIcon.appiconset/Icon-macOS-Dark-1024x1024@1x.png -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/MenubarPhoenix.imageset/menu_bar_icon-removebg-preview 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VonKleistL/OptiMac/HEAD/OptiMac/Assets.xcassets/MenubarPhoenix.imageset/menu_bar_icon-removebg-preview 2.png -------------------------------------------------------------------------------- /OptiMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /OptiMac.xcodeproj/project.xcworkspace/xcuserdata/lukeedgar.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VonKleistL/OptiMac/HEAD/OptiMac.xcodeproj/project.xcworkspace/xcuserdata/lukeedgar.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /OptiMac.xcodeproj/xcuserdata/lukeedgar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | OptiMac.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/MenubarPhoenix.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "menu_bar_icon-removebg-preview 2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | }, 21 | "properties" : { 22 | "localizable" : true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 DR LEVONK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OptiMac/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "filename" : "Icon-macOS-Dark-1024x1024@1x.png", 50 | "idiom" : "mac", 51 | "scale" : "2x", 52 | "size" : "512x512" 53 | } 54 | ], 55 | "info" : { 56 | "author" : "xcode", 57 | "version" : 1 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OptiMac/OptiMacApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OptiMacApp.swift 3 | // OptiMac 4 | // 5 | // Created by Luke Edgar on 27/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import AppKit 10 | 11 | // AppDelegate to help activate app and bring windows to front. 12 | final class AppDelegate: NSObject, NSApplicationDelegate { 13 | func applicationDidFinishLaunching(_ notification: Notification) { 14 | // Nothing special here; StatusBarController will be set up by the App. 15 | } 16 | 17 | func openMainAppWindow() { 18 | // Activate the app and bring the main window to front 19 | NSApp.activate(ignoringOtherApps: true) 20 | // If there’s no key window yet, SwiftUI will create one from the WindowGroup 21 | } 22 | } 23 | 24 | @main 25 | struct OptiMacApp: App { 26 | // Single shared monitor for both menu bar and main UI 27 | @StateObject private var systemMonitor: SystemMonitor 28 | 29 | // AppKit delegate 30 | @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate 31 | 32 | // Keep the status bar controller alive for the app lifetime 33 | @State private var statusBarController: StatusBarController? 34 | 35 | init() { 36 | let monitor = SystemMonitor() 37 | _systemMonitor = StateObject(wrappedValue: monitor) 38 | _statusBarController = State(initialValue: nil) 39 | } 40 | 41 | var body: some Scene { 42 | WindowGroup { 43 | ContentView(systemMonitor: systemMonitor) 44 | .onAppear { 45 | if statusBarController == nil { 46 | statusBarController = StatusBarController( 47 | systemMonitor: systemMonitor, 48 | openMainApp: { [weak appDelegate] in 49 | appDelegate?.openMainAppWindow() 50 | } 51 | ) 52 | } 53 | } 54 | } 55 | .commands { 56 | CommandGroup(after: .appInfo) { 57 | Button("Open OptiMac") { 58 | openMainApp() 59 | } 60 | .keyboardShortcut("o", modifiers: [.command, .shift]) 61 | } 62 | } 63 | } 64 | 65 | private func openMainApp() { 66 | appDelegate.openMainAppWindow() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /.github/workflows/build-release.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release OptiMac Enhanced 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' # Trigger on version tags like v2.0.0 7 | workflow_dispatch: # Allow manual triggers 8 | 9 | jobs: 10 | build: 11 | runs-on: macos-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up Python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.11' 21 | 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install -r requirements.txt 26 | brew install create-dmg 27 | 28 | - name: Build app bundle 29 | run: | 30 | python setup.py py2app 31 | 32 | - name: Create DMG 33 | run: | 34 | chmod +x build_dmg.sh 35 | ./build_dmg.sh 36 | 37 | - name: Get version from tag 38 | id: get_version 39 | run: | 40 | if [[ $GITHUB_REF == refs/tags/* ]]; then 41 | echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT 42 | else 43 | echo "VERSION=dev-$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT 44 | fi 45 | 46 | - name: Upload DMG artifact 47 | uses: actions/upload-artifact@v4 48 | with: 49 | name: OptiMac-Enhanced-${{ steps.get_version.outputs.VERSION }} 50 | path: '*.dmg' 51 | 52 | - name: Create Release 53 | if: startsWith(github.ref, 'refs/tags/') 54 | uses: softprops/action-gh-release@v1 55 | with: 56 | tag_name: ${{ github.ref }} 57 | name: OptiMac Enhanced v${{ steps.get_version.outputs.VERSION }} 58 | body: | 59 | # OptiMac Enhanced v${{ steps.get_version.outputs.VERSION }} 60 | 61 | ## What's New 62 | 🎉 **Enhanced OptiMac with exciting new features!** 63 | 64 | ### ✨ New Features 65 | - 🍎 **Menu Bar Integration** - Quick access from your menu bar 66 | - 👤 **User Profiles** - Save and switch between optimization profiles 67 | - 🔍 **Spotlight Re-indexing** - Rebuild Spotlight index for better search 68 | - 🔄 **Auto-Updates** - Automatic update checking and notifications 69 | 70 | ### 🛠️ Improvements 71 | - Enhanced GUI with better organization 72 | - Improved performance and stability 73 | - Better error handling and logging 74 | - Streamlined user experience 75 | 76 | ### 📦 Installation 77 | 1. Download the DMG file below 78 | 2. Open the DMG and drag OptiMac Enhanced to Applications 79 | 3. Launch from Applications or enable menu bar mode 80 | 81 | ### 🔧 System Requirements 82 | - macOS 10.15 (Catalina) or later 83 | - Apple Silicon (M1/M2/M3) or Intel Mac 84 | - Administrator privileges for system optimizations 85 | 86 | ### ⚠️ Important Notes 87 | - Always backup your system before running optimizations 88 | - Some optimizations may require a restart to take effect 89 | - Use advanced options with caution 90 | 91 | **Full Changelog**: https://github.com/VonKleistL/OptiMac/compare/v1.0.0...v${{ steps.get_version.outputs.VERSION }} 92 | files: '*.dmg' 93 | draft: false 94 | prerelease: false 95 | env: 96 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 97 | 98 | - name: Update latest release info 99 | if: startsWith(github.ref, 'refs/tags/') 100 | run: | 101 | echo "Release created successfully!" 102 | echo "Users will now be notified of the update through the app." -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![CleanShot 2025-10-27 at 15 34 59@2x](https://github.com/user-attachments/assets/647b8195-19e3-45a6-aa22-dbc6a97f6e83) 2 | ![CleanShot 2025-10-27 at 15 35 14@2x](https://github.com/user-attachments/assets/2d4c3ea5-d850-4006-b71b-4d7106ba75c1) 3 | 4 | 5 | # OptiMac v3.0 - Advanced MacOS Optimization Suite (Now in SwiftUI) 6 | 7 | **MacOS optimisation tool written in native swiftUI. Clean, easy to use and most importantly incredibly minimal on resources. 8 | ## What's New in v3.0 9 | 10 | ## Key Features 11 | 12 | ### Memory & Performance 13 | - **Purge inactive memory** - Instantly free up RAM for better responsiveness 14 | - **Clear system caches** - Remove accumulated cache files eating up storage 15 | - **Optimize swap settings** - Fine-tune virtual memory for your specific hardware 16 | - **Disable/Enable Spotlight indexing** - Control resource-heavy background indexing 17 | - **Re-index Spotlight** - Rebuild search index for better performance 18 | - **Reduce system animations** - Eliminate UI lag for snappier interactions 19 | 20 | ### System Tweaks 21 | - **Remove Dock animations** - Instant Dock show/hide for faster workflow 22 | - **Disable Finder animations** - Speed up file browser operations 23 | - **Optimize Launchpad** - Eliminate delays when accessing applications 24 | - **Disable Dashboard** - Free up system resources from unused features 25 | - **Enable SSD TRIM** - Maintain optimal SSD performance and longevity 26 | 27 | ### Network Optimizations 28 | - **DNS cache flushing** - Resolve connectivity issues and speed up browsing 29 | - **TCP/IP optimization** - Fine-tune network stack for better performance 30 | - **Wi-Fi enhancements** - Optimize wireless connectivity settings 31 | - **IPv6 management** - Disable if causing network conflicts 32 | 33 | ### Developer Environment 34 | - **Python/Conda optimization** - Perfect setup for Apple Silicon development 35 | - **Git performance tuning** - Speed up version control operations 36 | - **Homebrew cleanup** - Optimize package manager for better performance 37 | - **Node.js configuration** - Native Apple Silicon setup for web development 38 | 39 | ## Installation Options 40 | 41 | ### Option 1: DMG Installer (Recommended) 42 | 1. **Download** the latest `OptiMac-DMG Installer from [Releases](https://github.com/VonKleistL/OptiMac/releases) 43 | 2. **Open** the DMG file 44 | 3. **Drag** OptiMac to your Applications folder 45 | 4. **Launch** from Applications 46 | 47 | ## Option 2: Build from source 48 | 49 | ```bash 50 | git clone https://github.com/VonKleistL/OptiMac.git 51 | cd OptiMac 52 | ### Building DMG 53 | ```bash 54 | chmod +x build_dmg.sh 55 | ./build_dmg.sh 56 | ``` 57 | 58 | ## Usage Modes 59 | 60 | ### **Full GUI Mode** 61 | - Complete interface with all optimization options 62 | - Profile management and advanced settings 63 | - Detailed logging and progress tracking 64 | - Perfect for thorough system optimization 65 | 66 | ### **Menu Bar Mode** 67 | - Lightweight system tray integration 68 | - Quick access to common optimizations 69 | - Profile execution with one click 70 | - Ideal for daily maintenance tasks 71 | 72 | ## Safety First 73 | 74 | OptiMac Enhanced prioritizes system stability: 75 | - **Non-destructive changes** - All optimizations are reversible 76 | - **Backup integration** - Automatic Time Machine backups before major changes 77 | - **Confirmation dialogs** - Prevent accidental system modifications 78 | - **Detailed logging** - Track exactly what changes were made 79 | - **Safe defaults** - Conservative settings that work for everyone 80 | - **Profile validation** - Ensure safe profile configurations 81 | 82 | ## System Requirements 83 | 84 | - **macOS 15+ +** (Sequoia or later) 85 | - **Apple Silicon Mac** (M1, M1 Pro/Max, M2, M2 Pro/Max, M3, M3 Pro/Max) 86 | - **Python 3.8+** (pre-installed on macOS) 87 | - **Administrator privileges** (for system-level optimizations) 88 | - **Internet connection** (for update checking) 89 | 90 | ## Building from Source 91 | 92 | This creates a distributable DMG file ready for sharing! 93 | 94 | ## Contributing 95 | 96 | OptiMac is open source and welcomes contributions! 97 | 98 | - ** Bug Reports** - Help me improve stability 99 | - ** Feature Requests** - Share optimization ideas 100 | - ** Code Contributions** - Add new optimizations or improve the UI 101 | - ** Documentation** - Help other users get the most out of OptiMac 102 | - ** UI/UX Improvements** - Make the interface even better 103 | 104 | ## Support & Community 105 | 106 | - ** Bug Reports**: [GitHub Issues](https://github.com/VonKleistL/OptiMac/issues) 107 | - ** Discussions**: [GitHub Discussions](https://github.com/VonKleistL/OptiMac/discussions) 108 | - ** Direct Contact**: Open an issue for personalized support 109 | - ** Feature Requests**: Use GitHub Issues with the "enhancement" label 110 | 111 | ## License 112 | 113 | OptiMac is released under the [MIT License](LICENSE), making it free to use, modify, and distribute. 114 | 115 | ## Support the Project 116 | 117 | If OptiMac helped speed up your Mac: 118 | - ** Star the repository** to help others discover it 119 | - ** Share on social media** - Spread the word to fellow Mac users 120 | - ** Contribute code** - Help make OptiMac even better 121 | - ** Buy me a coffee** - Support continued development 122 | 123 | --- 124 | 125 | 126 | *Built for the Apple Silicon Mac community by [VonKleistL](https://github.com/VonKleistL)* 127 | 128 | ![macOS](https://img.shields.io/badge/macOS-10.15%2B-green?style=for-the-badge&logo=apple) 129 | ![Apple Silicon](https://img.shields.io/badge/Apple%20Silicon-Optimized-red?style=for-the-badge&logo=apple) 130 | -------------------------------------------------------------------------------- /OptiMac/StatusBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StatusBarController.swift 3 | // OptiMac 4 | // 5 | // Creates the NSStatusItem with a Phoenix icon and quick actions. 6 | // 7 | 8 | import AppKit 9 | import SwiftUI 10 | 11 | final class StatusBarController { 12 | private let statusItem: NSStatusItem 13 | private let menu = NSMenu() 14 | private weak var systemMonitor: SystemMonitor? 15 | private let openMainApp: () -> Void 16 | 17 | init(systemMonitor: SystemMonitor, openMainApp: @escaping () -> Void) { 18 | self.systemMonitor = systemMonitor 19 | self.openMainApp = openMainApp 20 | 21 | // Use a fixed length so the item doesn't collapse if the image fails to load 22 | self.statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) 23 | 24 | configureButtonImage() 25 | 26 | constructMenu() 27 | statusItem.menu = menu 28 | } 29 | 30 | private func configureButtonImage() { 31 | guard let button = statusItem.button else { return } 32 | 33 | if let img = NSImage(named: "MenubarPhoenix") { 34 | // Full-color asset 35 | img.isTemplate = false 36 | button.image = img 37 | button.imageScaling = .scaleProportionallyDown 38 | button.appearsDisabled = false 39 | } else { 40 | // Fallback: programmatic template icon so it's never invisible 41 | #if DEBUG 42 | print("Warning: MenubarPhoenix asset not found. Falling back to template icon.") 43 | #endif 44 | let fallback = Self.phoenixIcon(isTemplate: true) 45 | button.image = fallback 46 | button.imageScaling = .scaleProportionallyDown 47 | button.appearsDisabled = false 48 | } 49 | } 50 | 51 | private func constructMenu() { 52 | menu.items.removeAll() 53 | 54 | // Five quick actions 55 | menu.addItem(withTitle: "Purge Inactive Memory", action: #selector(purgeMemory), keyEquivalent: "") 56 | menu.addItem(withTitle: "Flush DNS Cache", action: #selector(flushDNS), keyEquivalent: "") 57 | menu.addItem(withTitle: "Clear System Caches", action: #selector(clearCaches), keyEquivalent: "") 58 | menu.addItem(withTitle: "Clean Homebrew", action: #selector(cleanHomebrew), keyEquivalent: "") 59 | menu.addItem(withTitle: "Rebuild Spotlight Index", action: #selector(rebuildSpotlight), keyEquivalent: "") 60 | 61 | menu.addItem(NSMenuItem.separator()) 62 | 63 | // Open main app 64 | let openItem = NSMenuItem(title: "Open OptiMac", action: #selector(openApp), keyEquivalent: "") 65 | menu.addItem(openItem) 66 | 67 | // Quit 68 | let quitItem = NSMenuItem(title: "Quit", action: #selector(quitApp), keyEquivalent: "q") 69 | menu.addItem(quitItem) 70 | 71 | // Target 72 | for item in menu.items { 73 | item.target = self 74 | } 75 | } 76 | 77 | // MARK: - Actions (wired to SystemMonitor quick task ids) 78 | @objc private func purgeMemory() { runTasks(ids: ["purge_memory"]) } 79 | @objc private func flushDNS() { runTasks(ids: ["flush_dns"]) } 80 | @objc private func clearCaches() { runTasks(ids: ["clear_caches"]) } 81 | @objc private func cleanHomebrew() { runTasks(ids: ["optimize_homebrew"]) } 82 | @objc private func rebuildSpotlight() { runTasks(ids: ["reindex_spotlight"]) } 83 | 84 | @objc private func openApp() { 85 | openMainApp() 86 | } 87 | 88 | @objc private func quitApp() { 89 | NSApp.terminate(nil) 90 | } 91 | 92 | private func runTasks(ids: [String]) { 93 | guard let monitor = systemMonitor else { return } 94 | monitor.selectedTasks = Set(ids) 95 | monitor.runOptimization() 96 | } 97 | 98 | // MARK: - Phoenix Icon (template fallback) 99 | static func phoenixIcon(isTemplate: Bool) -> NSImage { 100 | let size = NSSize(width: 18, height: 18) 101 | let image = NSImage(size: size) 102 | image.lockFocus() 103 | 104 | let bounds = NSRect(origin: .zero, size: size) 105 | let center = CGPoint(x: bounds.midX, y: bounds.midY) 106 | 107 | let primary = NSColor.white 108 | let secondary = NSColor.white.withAlphaComponent(0.9) 109 | 110 | let body = NSBezierPath() 111 | body.move(to: CGPoint(x: center.x, y: 2)) 112 | body.curve(to: CGPoint(x: 2, y: center.y), 113 | controlPoint1: CGPoint(x: center.x - 5, y: 2), 114 | controlPoint2: CGPoint(x: 2, y: center.y - 4)) 115 | body.curve(to: CGPoint(x: center.x, y: size.height - 2), 116 | controlPoint1: CGPoint(x: 2, y: center.y + 6), 117 | controlPoint2: CGPoint(x: center.x - 3, y: size.height - 2)) 118 | body.curve(to: CGPoint(x: size.width - 2, y: center.y), 119 | controlPoint1: CGPoint(x: center.x + 3, y: size.height - 2), 120 | controlPoint2: CGPoint(x: size.width - 2, y: center.y + 6)) 121 | body.curve(to: CGPoint(x: center.x, y: 2), 122 | controlPoint1: CGPoint(x: size.width - 2, y: center.y - 4), 123 | controlPoint2: CGPoint(x: center.x + 5, y: 2)) 124 | primary.setFill() 125 | body.fill() 126 | 127 | let leftWing = NSBezierPath() 128 | leftWing.move(to: CGPoint(x: center.x - 2, y: center.y + 2)) 129 | leftWing.curve(to: CGPoint(x: 1, y: center.y + 1), 130 | controlPoint1: CGPoint(x: center.x - 7, y: center.y + 6), 131 | controlPoint2: CGPoint(x: 2, y: center.y + 4)) 132 | leftWing.curve(to: CGPoint(x: center.x - 1, y: center.y - 1), 133 | controlPoint1: CGPoint(x: 0, y: center.y), 134 | controlPoint2: CGPoint(x: center.x - 4, y: center.y - 2)) 135 | secondary.setFill() 136 | leftWing.fill() 137 | 138 | let rightWing = NSBezierPath() 139 | rightWing.move(to: CGPoint(x: center.x + 2, y: center.y + 2)) 140 | rightWing.curve(to: CGPoint(x: size.width - 1, y: center.y + 1), 141 | controlPoint1: CGPoint(x: center.x + 7, y: center.y + 6), 142 | controlPoint2: CGPoint(x: size.width - 2, y: center.y + 4)) 143 | rightWing.curve(to: CGPoint(x: center.x + 1, y: center.y - 1), 144 | controlPoint1: CGPoint(x: size.width, y: center.y), 145 | controlPoint2: CGPoint(x: center.x + 4, y: center.y - 2)) 146 | secondary.setFill() 147 | rightWing.fill() 148 | 149 | image.unlockFocus() 150 | image.isTemplate = isTemplate 151 | return image 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /OptiMac.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | 75D219372EAF4D4200824356 /* OptiMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OptiMac.app; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | 75D219392EAF4D4200824356 /* OptiMac */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = OptiMac; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | 75D219342EAF4D4200824356 /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | 75D2192E2EAF4D4200824356 = { 33 | isa = PBXGroup; 34 | children = ( 35 | 75D219392EAF4D4200824356 /* OptiMac */, 36 | 75D219382EAF4D4200824356 /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | 75D219382EAF4D4200824356 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 75D219372EAF4D4200824356 /* OptiMac.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | 75D219362EAF4D4200824356 /* OptiMac */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = 75D219422EAF4D4400824356 /* Build configuration list for PBXNativeTarget "OptiMac" */; 54 | buildPhases = ( 55 | 75D219332EAF4D4200824356 /* Sources */, 56 | 75D219342EAF4D4200824356 /* Frameworks */, 57 | 75D219352EAF4D4200824356 /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | 75D219392EAF4D4200824356 /* OptiMac */, 65 | ); 66 | name = OptiMac; 67 | packageProductDependencies = ( 68 | ); 69 | productName = OptiMac; 70 | productReference = 75D219372EAF4D4200824356 /* OptiMac.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | 75D2192F2EAF4D4200824356 /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 2610; 81 | LastUpgradeCheck = 2610; 82 | TargetAttributes = { 83 | 75D219362EAF4D4200824356 = { 84 | CreatedOnToolsVersion = 26.1; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = 75D219322EAF4D4200824356 /* Build configuration list for PBXProject "OptiMac" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = 75D2192E2EAF4D4200824356; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = 75D219382EAF4D4200824356 /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | 75D219362EAF4D4200824356 /* OptiMac */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | 75D219352EAF4D4200824356 /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | 75D219332EAF4D4200824356 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 75D219402EAF4D4400824356 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | DEVELOPMENT_TEAM = DYUP26D449; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | ENABLE_TESTABILITY = YES; 166 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 167 | GCC_C_LANGUAGE_STANDARD = gnu17; 168 | GCC_DYNAMIC_NO_PIC = NO; 169 | GCC_NO_COMMON_BLOCKS = YES; 170 | GCC_OPTIMIZATION_LEVEL = 0; 171 | GCC_PREPROCESSOR_DEFINITIONS = ( 172 | "DEBUG=1", 173 | "$(inherited)", 174 | ); 175 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 176 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 177 | GCC_WARN_UNDECLARED_SELECTOR = YES; 178 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 179 | GCC_WARN_UNUSED_FUNCTION = YES; 180 | GCC_WARN_UNUSED_VARIABLE = YES; 181 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 182 | MACOSX_DEPLOYMENT_TARGET = 26.1; 183 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 184 | MTL_FAST_MATH = YES; 185 | ONLY_ACTIVE_ARCH = YES; 186 | SDKROOT = macosx; 187 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 188 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 189 | }; 190 | name = Debug; 191 | }; 192 | 75D219412EAF4D4400824356 /* Release */ = { 193 | isa = XCBuildConfiguration; 194 | buildSettings = { 195 | ALWAYS_SEARCH_USER_PATHS = NO; 196 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 197 | CLANG_ANALYZER_NONNULL = YES; 198 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 200 | CLANG_ENABLE_MODULES = YES; 201 | CLANG_ENABLE_OBJC_ARC = YES; 202 | CLANG_ENABLE_OBJC_WEAK = YES; 203 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 204 | CLANG_WARN_BOOL_CONVERSION = YES; 205 | CLANG_WARN_COMMA = YES; 206 | CLANG_WARN_CONSTANT_CONVERSION = YES; 207 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 209 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 210 | CLANG_WARN_EMPTY_BODY = YES; 211 | CLANG_WARN_ENUM_CONVERSION = YES; 212 | CLANG_WARN_INFINITE_RECURSION = YES; 213 | CLANG_WARN_INT_CONVERSION = YES; 214 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 215 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 216 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 218 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 220 | CLANG_WARN_STRICT_PROTOTYPES = YES; 221 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 222 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | COPY_PHASE_STRIP = NO; 226 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 227 | DEVELOPMENT_TEAM = DYUP26D449; 228 | ENABLE_NS_ASSERTIONS = NO; 229 | ENABLE_STRICT_OBJC_MSGSEND = YES; 230 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 231 | GCC_C_LANGUAGE_STANDARD = gnu17; 232 | GCC_NO_COMMON_BLOCKS = YES; 233 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 235 | GCC_WARN_UNDECLARED_SELECTOR = YES; 236 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 237 | GCC_WARN_UNUSED_FUNCTION = YES; 238 | GCC_WARN_UNUSED_VARIABLE = YES; 239 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 240 | MACOSX_DEPLOYMENT_TARGET = 26.1; 241 | MTL_ENABLE_DEBUG_INFO = NO; 242 | MTL_FAST_MATH = YES; 243 | SDKROOT = macosx; 244 | SWIFT_COMPILATION_MODE = wholemodule; 245 | }; 246 | name = Release; 247 | }; 248 | 75D219432EAF4D4400824356 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 252 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 253 | CODE_SIGN_STYLE = Automatic; 254 | COMBINE_HIDPI_IMAGES = YES; 255 | CURRENT_PROJECT_VERSION = 1; 256 | DEVELOPMENT_TEAM = DYUP26D449; 257 | ENABLE_APP_SANDBOX = YES; 258 | ENABLE_HARDENED_RUNTIME = YES; 259 | ENABLE_PREVIEWS = YES; 260 | ENABLE_USER_SELECTED_FILES = readonly; 261 | GENERATE_INFOPLIST_FILE = YES; 262 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; 263 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 264 | LD_RUNPATH_SEARCH_PATHS = ( 265 | "$(inherited)", 266 | "@executable_path/../Frameworks", 267 | ); 268 | MARKETING_VERSION = 1.0; 269 | PRODUCT_BUNDLE_IDENTIFIER = com.vonkleistl.OptiMac.OptiMac; 270 | PRODUCT_NAME = "$(TARGET_NAME)"; 271 | REGISTER_APP_GROUPS = YES; 272 | STRING_CATALOG_GENERATE_SYMBOLS = YES; 273 | SWIFT_APPROACHABLE_CONCURRENCY = YES; 274 | SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; 275 | SWIFT_EMIT_LOC_STRINGS = YES; 276 | SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 277 | SWIFT_VERSION = 5.0; 278 | }; 279 | name = Debug; 280 | }; 281 | 75D219442EAF4D4400824356 /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 286 | CODE_SIGN_STYLE = Automatic; 287 | COMBINE_HIDPI_IMAGES = YES; 288 | CURRENT_PROJECT_VERSION = 1; 289 | DEVELOPMENT_TEAM = DYUP26D449; 290 | ENABLE_APP_SANDBOX = YES; 291 | ENABLE_HARDENED_RUNTIME = YES; 292 | ENABLE_PREVIEWS = YES; 293 | ENABLE_USER_SELECTED_FILES = readonly; 294 | GENERATE_INFOPLIST_FILE = YES; 295 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; 296 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 297 | LD_RUNPATH_SEARCH_PATHS = ( 298 | "$(inherited)", 299 | "@executable_path/../Frameworks", 300 | ); 301 | MARKETING_VERSION = 1.0; 302 | PRODUCT_BUNDLE_IDENTIFIER = com.vonkleistl.OptiMac.OptiMac; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | REGISTER_APP_GROUPS = YES; 305 | STRING_CATALOG_GENERATE_SYMBOLS = YES; 306 | SWIFT_APPROACHABLE_CONCURRENCY = YES; 307 | SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; 308 | SWIFT_EMIT_LOC_STRINGS = YES; 309 | SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 310 | SWIFT_VERSION = 5.0; 311 | }; 312 | name = Release; 313 | }; 314 | /* End XCBuildConfiguration section */ 315 | 316 | /* Begin XCConfigurationList section */ 317 | 75D219322EAF4D4200824356 /* Build configuration list for PBXProject "OptiMac" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | 75D219402EAF4D4400824356 /* Debug */, 321 | 75D219412EAF4D4400824356 /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | defaultConfigurationName = Release; 325 | }; 326 | 75D219422EAF4D4400824356 /* Build configuration list for PBXNativeTarget "OptiMac" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 75D219432EAF4D4400824356 /* Debug */, 330 | 75D219442EAF4D4400824356 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | /* End XCConfigurationList section */ 336 | }; 337 | rootObject = 75D2192F2EAF4D4200824356 /* Project object */; 338 | } 339 | -------------------------------------------------------------------------------- /OptiMac/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // OptiMac 4 | // 5 | // Real System Monitoring with Actual macOS System Calls 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | import Foundation 11 | import Combine 12 | import Darwin 13 | 14 | // Fallback if the constant isn’t visible for some SDKs (Apple defines it as 4096) 15 | let PROC_PIDPATHINFO_MAXSIZE: Int32 = 4096 16 | 17 | // MARK: - Real System Data Models 18 | struct ProcessInfo: Identifiable { 19 | let id = UUID() 20 | let pid: Int32 21 | let name: String 22 | let cpuUsage: Double 23 | let memoryUsage: Double // in MB 24 | let color: Color 25 | } 26 | 27 | struct RealMemoryInfo { 28 | let totalMemory: Double // in GB 29 | let usedMemory: Double // in GB 30 | let freeMemory: Double // in GB 31 | let appMemoryUsage: [ProcessInfo] 32 | let swapUsed: Double // in GB 33 | } 34 | 35 | struct NetworkSpeed { 36 | let downloadBytesPerSec: Double 37 | let uploadBytesPerSec: Double 38 | let timestamp: Date 39 | 40 | var downloadMbps: Double { 41 | return (downloadBytesPerSec * 8) / (1024 * 1024) // Convert to Mbps 42 | } 43 | 44 | var uploadMbps: Double { 45 | return (uploadBytesPerSec * 8) / (1024 * 1024) // Convert to Mbps 46 | } 47 | } 48 | 49 | struct UrgentProcess: Identifiable { 50 | let id = UUID() 51 | let pid: Int32 52 | let name: String 53 | let issue: String 54 | let cpuUsage: Double 55 | let memoryUsage: Double 56 | let priority: UrgentPriority 57 | } 58 | 59 | enum UrgentPriority { 60 | case high, medium, low 61 | 62 | var color: Color { 63 | switch self { 64 | case .high: return Color(red: 1.00, green: 0.22, blue: 0.30) // crisper red 65 | case .medium: return Color(red: 1.00, green: 0.55, blue: 0.00) // vivid orange 66 | case .low: return Color(red: 1.00, green: 0.84, blue: 0.00) // bright yellow 67 | } 68 | } 69 | } 70 | 71 | // MARK: - Real System Monitor Class 72 | class RealSystemMonitor: ObservableObject { 73 | @Published var memoryInfo = RealMemoryInfo(totalMemory: 0, usedMemory: 0, freeMemory: 0, appMemoryUsage: [], swapUsed: 0) 74 | @Published var cpuProcesses: [ProcessInfo] = [] 75 | @Published var networkHistory: [NetworkSpeed] = [] 76 | @Published var urgentProcesses: [UrgentProcess] = [] 77 | @Published var totalCPUUsage: Double = 0 78 | 79 | private var previousNetworkStats: (rx: UInt64, tx: UInt64) = (0, 0) 80 | private var lastNetworkUpdate = Date() 81 | private let appColors: [Color] = [ 82 | Color(red: 0.20, green: 0.60, blue: 1.00), 83 | Color(red: 0.20, green: 0.85, blue: 0.50), 84 | Color(red: 1.00, green: 0.55, blue: 0.00), 85 | Color(red: 0.60, green: 0.40, blue: 1.00), 86 | Color(red: 1.00, green: 0.22, blue: 0.30), 87 | Color(red: 1.00, green: 0.40, blue: 0.70), 88 | Color(red: 0.10, green: 0.80, blue: 0.90), 89 | Color(red: 1.00, green: 0.84, blue: 0.00), 90 | Color(red: 0.60, green: 0.45, blue: 0.30), 91 | Color(red: 0.40, green: 0.40, blue: 1.00) 92 | ] 93 | private var processColorMap: [String: Color] = [:] 94 | 95 | // CPU sampling state 96 | private var lastCPUTimeStamp: TimeInterval = 0 97 | private var lastSystemCPUTicks: (user: UInt32, system: UInt32, nice: UInt32, idle: UInt32)? 98 | private var lastPerProcessCPUTimeNs: [Int32: UInt64] = [:] // pid -> total (user+system) ns 99 | 100 | private var updateTimer: Timer? 101 | private let numCores = Double(Foundation.ProcessInfo.processInfo.processorCount) 102 | 103 | init() { 104 | startRealTimeMonitoring() 105 | } 106 | 107 | private func startRealTimeMonitoring() { 108 | // Initial update 109 | updateAllSystemData() 110 | 111 | // Update every 2 seconds 112 | updateTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in 113 | Task { @MainActor in 114 | self.updateAllSystemData() 115 | } 116 | } 117 | } 118 | 119 | private func updateAllSystemData() { 120 | updateMemoryInfo() 121 | updateCPUInfo() 122 | updateNetworkInfo() 123 | updateUrgentProcesses() 124 | } 125 | 126 | // MARK: - Real Memory Monitoring (Activity Monitor parity) 127 | private func updateMemoryInfo() { 128 | var stats = vm_statistics64() 129 | var count = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) 130 | 131 | let result = withUnsafeMutablePointer(to: &stats) { 132 | $0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { 133 | host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count) 134 | } 135 | } 136 | 137 | if result == KERN_SUCCESS { 138 | let pageSize = Double(vm_kernel_page_size) 139 | let totalBytes = Double(Foundation.ProcessInfo.processInfo.physicalMemory) 140 | 141 | // Match “Memory Used” in Activity Monitor: 142 | // used = active + wired + compressed 143 | // free = free + inactive (as displayed in AM “Memory Pressure” details) 144 | let usedBytes = (Double(stats.active_count) 145 | + Double(stats.wire_count) 146 | + Double(stats.compressor_page_count)) * pageSize 147 | let freeBytes = (Double(stats.free_count) + Double(stats.inactive_count)) * pageSize 148 | 149 | let totalGB = totalBytes / (1024 * 1024 * 1024) 150 | let usedGB = max(usedBytes, 0) / (1024 * 1024 * 1024) 151 | let freeGB = max(freeBytes, 0) / (1024 * 1024 * 1024) 152 | 153 | // Get per-process memory via proc_pidinfo (resident size) 154 | let processes = getRealProcessList() 155 | let topMemoryProcesses = Array(processes.sorted { $0.memoryUsage > $1.memoryUsage }.prefix(6)) 156 | 157 | memoryInfo = RealMemoryInfo( 158 | totalMemory: totalGB, 159 | usedMemory: usedGB, 160 | freeMemory: freeGB, 161 | appMemoryUsage: topMemoryProcesses, 162 | swapUsed: 0 // Could be added via sysctl vm.swapusage if desired 163 | ) 164 | } 165 | } 166 | 167 | // MARK: - Real CPU Monitoring 168 | private func updateCPUInfo() { 169 | // Update total CPU from host_processor_info deltas 170 | totalCPUUsage = readSystemCPUPercentage() 171 | 172 | // Build process list with real per-process CPU and memory from proc_pidinfo 173 | let processes = getRealProcessList() 174 | 175 | // Get top CPU consuming processes 176 | cpuProcesses = Array(processes.sorted { $0.cpuUsage > $1.cpuUsage }.prefix(6)) 177 | } 178 | 179 | // MARK: - System CPU via host_processor_info (delta-based) 180 | private func readSystemCPUPercentage() -> Double { 181 | var cpuInfo: processor_info_array_t? 182 | var cpuInfoCount: mach_msg_type_number_t = 0 183 | var numCPUU: natural_t = 0 184 | 185 | let result = host_processor_info(mach_host_self(), 186 | PROCESSOR_CPU_LOAD_INFO, 187 | &numCPUU, 188 | &cpuInfo, 189 | &cpuInfoCount) 190 | guard result == KERN_SUCCESS, let info = cpuInfo else { 191 | return totalCPUUsage // leave unchanged if failed 192 | } 193 | defer { 194 | let size = Int(cpuInfoCount) * MemoryLayout.size 195 | vm_deallocate(mach_task_self_, vm_address_t(bitPattern: info), vm_size_t(size)) 196 | } 197 | 198 | var totalUser: UInt32 = 0 199 | var totalSystem: UInt32 = 0 200 | var totalNice: UInt32 = 0 201 | var totalIdle: UInt32 = 0 202 | 203 | let stride = Int(CPU_STATE_MAX) 204 | for cpu in 0.. 0 { 220 | let busy = Double(userDiff + sysDiff + niceDiff) 221 | let percent = (busy / totalTicks) * 100.0 222 | lastSystemCPUTicks = (totalUser, totalSystem, totalNice, totalIdle) 223 | return min(max(percent, 0), 100) 224 | } 225 | } 226 | 227 | lastSystemCPUTicks = (totalUser, totalSystem, totalNice, totalIdle) 228 | return totalCPUUsage // unchanged on first sample 229 | } 230 | 231 | // MARK: - Real Process List using kinfo_proc + proc_pidinfo 232 | private func getRealProcessList() -> [ProcessInfo] { 233 | var processes: [ProcessInfo] = [] 234 | var buffer: UnsafeMutablePointer? 235 | var size: size_t = 0 236 | 237 | // Get process list size 238 | var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0] 239 | sysctl(&mib, u_int(mib.count), nil, &size, nil, 0) 240 | 241 | buffer = UnsafeMutablePointer.allocate(capacity: size / MemoryLayout.size) 242 | defer { buffer?.deallocate() } 243 | 244 | if sysctl(&mib, u_int(mib.count), buffer, &size, nil, 0) == 0 { 245 | let processCount = size / MemoryLayout.size 246 | let now = Date().timeIntervalSince1970 247 | let elapsed = lastCPUTimeStamp > 0 ? now - lastCPUTimeStamp : 0 248 | let elapsedNs = elapsed > 0 ? UInt64(elapsed * 1_000_000_000) : 0 249 | 250 | for i in 0.. 0 { 261 | let path = String(cString: pathBuffer) 262 | processName = URL(fileURLWithPath: path).lastPathComponent 263 | } else { 264 | // Fallback to kp_proc.p_comm if path not available 265 | withUnsafePointer(to: proc.kp_proc.p_comm) { 266 | processName = String(cString: UnsafeRawPointer($0).assumingMemoryBound(to: CChar.self)) 267 | } 268 | } 269 | if processName.isEmpty { continue } 270 | 271 | // Read proc_taskinfo for the pid 272 | var tinfo = proc_taskinfo() 273 | let tinfoSize = MemoryLayout.stride 274 | let readSize = withUnsafeMutablePointer(to: &tinfo) { ptr in 275 | ptr.withMemoryRebound(to: UInt8.self, capacity: tinfoSize) { rawPtr in 276 | proc_pidinfo(pid, PROC_PIDTASKINFO, 0, rawPtr, Int32(tinfoSize)) 277 | } 278 | } 279 | guard readSize == tinfoSize else { 280 | continue 281 | } 282 | 283 | // Memory (resident) in MB 284 | let memMB = Double(tinfo.pti_resident_size) / (1024.0 * 1024.0) 285 | 286 | // CPU: compute delta of total (user+system) time 287 | let totalNs = tinfo.pti_total_user + tinfo.pti_total_system 288 | let prevNs = lastPerProcessCPUTimeNs[pid] ?? totalNs 289 | let deltaNs = totalNs &- prevNs 290 | lastPerProcessCPUTimeNs[pid] = totalNs 291 | 292 | var cpuPercent: Double = 0.0 293 | if elapsedNs > 0 { 294 | // Normalize by elapsed time and core count 295 | let fraction = Double(deltaNs) / Double(elapsedNs) 296 | cpuPercent = (fraction / numCores) * 100.0 297 | } 298 | 299 | // Only include processes with noticeable usage (helps keep charts readable) 300 | if cpuPercent > 0.05 || memMB > 50 { 301 | let color = getColorForProcess(processName) 302 | processes.append(ProcessInfo( 303 | pid: pid, 304 | name: processName, 305 | cpuUsage: min(max(cpuPercent, 0), 100), 306 | memoryUsage: memMB, 307 | color: color 308 | )) 309 | } 310 | } 311 | 312 | lastCPUTimeStamp = now 313 | } 314 | 315 | return processes 316 | } 317 | 318 | // MARK: - Network parity with Activity Monitor 319 | private func updateNetworkInfo() { 320 | let currentStats = getPrimaryInterfaceCounters() 321 | let now = Date() 322 | let timeDiff = now.timeIntervalSince(lastNetworkUpdate) 323 | 324 | // If we have never recorded stats, seed previousNetworkStats and push a baseline sample 325 | if previousNetworkStats.rx == 0 && previousNetworkStats.tx == 0 { 326 | previousNetworkStats = currentStats 327 | lastNetworkUpdate = now 328 | // Seed one zero-rate sample so the UI can progress after next tick 329 | networkHistory.append(NetworkSpeed(downloadBytesPerSec: 0, uploadBytesPerSec: 0, timestamp: now)) 330 | if networkHistory.count > 40 { 331 | networkHistory.removeFirst() 332 | } 333 | return 334 | } 335 | 336 | if timeDiff > 0 { 337 | let rxDiff = currentStats.rx > previousNetworkStats.rx ? currentStats.rx - previousNetworkStats.rx : 0 338 | let txDiff = currentStats.tx > previousNetworkStats.tx ? currentStats.tx - previousNetworkStats.tx : 0 339 | 340 | let downloadSpeed = Double(rxDiff) / timeDiff 341 | let uploadSpeed = Double(txDiff) / timeDiff 342 | 343 | let networkSpeed = NetworkSpeed( 344 | downloadBytesPerSec: downloadSpeed, 345 | uploadBytesPerSec: uploadSpeed, 346 | timestamp: now 347 | ) 348 | 349 | networkHistory.append(networkSpeed) 350 | if networkHistory.count > 40 { // a bit more history for smoother chart 351 | networkHistory.removeFirst() 352 | } 353 | } 354 | 355 | previousNetworkStats = currentStats 356 | lastNetworkUpdate = now 357 | } 358 | 359 | // Resolve default-route interface by asking the kernel which local IP it would use to reach 8.8.8.8:53 360 | private func defaultRouteInterfaceName() -> String? { 361 | // 1) Create a UDP socket and "connect" to 8.8.8.8:53 (no packets sent) 362 | let sock = socket(AF_INET, SOCK_DGRAM, 0) 363 | if sock < 0 { return nil } 364 | defer { close(sock) } 365 | 366 | var addr = sockaddr_in() 367 | addr.sin_len = UInt8(MemoryLayout.size) 368 | addr.sin_family = sa_family_t(AF_INET) 369 | addr.sin_port = in_port_t(53).bigEndian 370 | inet_pton(AF_INET, "8.8.8.8", &addr.sin_addr) 371 | 372 | var dest = sockaddr() 373 | memcpy(&dest, &addr, MemoryLayout.size) 374 | let result = withUnsafePointer(to: &dest) { 375 | $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { 376 | connect(sock, $0, socklen_t(MemoryLayout.size)) 377 | } 378 | } 379 | if result < 0 { 380 | // Could not connect (offline), fall back to picking any UP|RUNNING en* 381 | return activeInterfaceNameFallback() 382 | } 383 | 384 | // 2) getsockname to learn the local IP chosen by kernel 385 | var localAddr = sockaddr_in() 386 | var len = socklen_t(MemoryLayout.size) 387 | let gsn = withUnsafeMutablePointer(to: &localAddr) { 388 | $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { 389 | getsockname(sock, $0, &len) 390 | } 391 | } 392 | if gsn != 0 { 393 | return activeInterfaceNameFallback() 394 | } 395 | 396 | // 3) Map local IP to interface via getifaddrs 397 | var ifaddr: UnsafeMutablePointer? 398 | guard getifaddrs(&ifaddr) == 0, let first = ifaddr else { 399 | return activeInterfaceNameFallback() 400 | } 401 | defer { freeifaddrs(ifaddr) } 402 | 403 | var ptr: UnsafeMutablePointer? = first 404 | while let p = ptr?.pointee { 405 | if p.ifa_addr.pointee.sa_family == UInt8(AF_INET) { 406 | let sa = UnsafeRawPointer(p.ifa_addr).assumingMemoryBound(to: sockaddr_in.self).pointee 407 | if sa.sin_addr.s_addr == localAddr.sin_addr.s_addr { 408 | return String(cString: p.ifa_name) 409 | } 410 | } 411 | ptr = p.ifa_next 412 | } 413 | 414 | return activeInterfaceNameFallback() 415 | } 416 | 417 | // Fallback: first UP|RUNNING en*, else any UP|RUNNING 418 | private func activeInterfaceNameFallback() -> String? { 419 | var ifaddr: UnsafeMutablePointer? 420 | guard getifaddrs(&ifaddr) == 0, let first = ifaddr else { return nil } 421 | defer { freeifaddrs(ifaddr) } 422 | 423 | var candidates: [String] = [] 424 | var ptr: UnsafeMutablePointer? = first 425 | while let p = ptr?.pointee { 426 | let flags = Int32(p.ifa_flags) 427 | let isUp = (flags & IFF_UP) != 0 428 | let isRunning = (flags & IFF_RUNNING) != 0 429 | let name = String(cString: p.ifa_name) 430 | if isUp && isRunning { 431 | candidates.append(name) 432 | } 433 | ptr = p.ifa_next 434 | } 435 | if candidates.contains("en0") { return "en0" } 436 | if candidates.contains("en1") { return "en1" } 437 | if let en = candidates.first(where: { $0.hasPrefix("en") }) { return en } 438 | return candidates.first 439 | } 440 | 441 | // Read per-interface counters using sysctl NET_RT_IFLIST2 (if_msghdr2 -> if_data64) 442 | private func interfaceByteCounters(name: String) -> (rx: UInt64, tx: UInt64)? { 443 | // Build MIB: CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST2, 0 444 | var mib: [Int32] = [CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST2, 0] 445 | var len: size_t = 0 446 | // First call to get size 447 | if sysctl(&mib, u_int(mib.count), nil, &len, nil, 0) != 0 || len == 0 { 448 | return nil 449 | } 450 | let buf = UnsafeMutableRawPointer.allocate(byteCount: len, alignment: MemoryLayout.alignment) 451 | defer { buf.deallocate() } 452 | if sysctl(&mib, u_int(mib.count), buf, &len, nil, 0) != 0 { 453 | return nil 454 | } 455 | 456 | var rx: UInt64 = 0 457 | var tx: UInt64 = 0 458 | 459 | var next = buf 460 | let end = buf.advanced(by: len) 461 | while next < end { 462 | // All route messages are length-prefixed; read the header to know how far to advance 463 | let ifm = next.assumingMemoryBound(to: if_msghdr2.self).pointee 464 | let msgLen = Int(ifm.ifm_msglen) 465 | 466 | if ifm.ifm_type == UInt8(RTM_IFINFO2) { 467 | // The sockaddr_dl immediately follows the header 468 | let sdlPtr = next.advanced(by: MemoryLayout.size).assumingMemoryBound(to: sockaddr_dl.self) 469 | let sdl = sdlPtr.pointee 470 | let nameLen = Int(sdl.sdl_nlen) 471 | 472 | // The name bytes start at sdl_data within sockaddr_dl 473 | let sdlDataOffset = MemoryLayout.offset(of: \sockaddr_dl.sdl_data) ?? MemoryLayout.size 474 | let nameStart = UnsafeRawPointer(sdlPtr).advanced(by: sdlDataOffset) 475 | let nameBytes = nameStart.assumingMemoryBound(to: UInt8.self) 476 | let ifName = String(decoding: UnsafeBufferPointer(start: nameBytes, count: max(0, nameLen)), as: UTF8.self) 477 | 478 | if ifName == name { 479 | rx = ifm.ifm_data.ifi_ibytes 480 | tx = ifm.ifm_data.ifi_obytes 481 | break 482 | } 483 | } 484 | 485 | // Advance to the next message 486 | next = next.advanced(by: msgLen) 487 | } 488 | 489 | return (rx, tx) 490 | } 491 | 492 | private func getPrimaryInterfaceCounters() -> (rx: UInt64, tx: UInt64) { 493 | guard let iface = defaultRouteInterfaceName(), 494 | let counters = interfaceByteCounters(name: iface) else { 495 | // Fallback to zeros to avoid fake movement 496 | return (rx: 0, tx: 0) 497 | } 498 | return counters 499 | } 500 | 501 | // MARK: - Real Urgent Processes Detection 502 | private func updateUrgentProcesses() { 503 | let allProcesses = getRealProcessList() 504 | var urgent: [UrgentProcess] = [] 505 | 506 | for process in allProcesses { 507 | var shouldAdd = false 508 | var issue = "" 509 | var priority = UrgentPriority.low 510 | 511 | if process.cpuUsage > 50 { 512 | issue = "High CPU usage (\(String(format: "%.1f", process.cpuUsage))%)" 513 | priority = .high 514 | shouldAdd = true 515 | } else if process.memoryUsage > 2048 { 516 | issue = "High memory usage (\(String(format: "%.0f", process.memoryUsage))MB)" 517 | priority = .medium 518 | shouldAdd = true 519 | } else if process.cpuUsage > 20 || process.memoryUsage > 1000 { 520 | issue = "Moderate resource usage" 521 | priority = .low 522 | shouldAdd = true 523 | } 524 | 525 | if shouldAdd && urgent.count < 5 { 526 | urgent.append(UrgentProcess( 527 | pid: process.pid, 528 | name: process.name, 529 | issue: issue, 530 | cpuUsage: process.cpuUsage, 531 | memoryUsage: process.memoryUsage, 532 | priority: priority 533 | )) 534 | } 535 | } 536 | 537 | urgentProcesses = urgent 538 | } 539 | 540 | // MARK: - Force Quit Process (REAL) 541 | func forceQuitProcess(pid: Int32) { 542 | let result = kill(pid, SIGTERM) 543 | if result != 0 { 544 | kill(pid, SIGKILL) 545 | } 546 | 547 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { 548 | self.updateUrgentProcesses() 549 | } 550 | } 551 | 552 | private func getColorForProcess(_ processName: String) -> Color { 553 | if let existingColor = processColorMap[processName] { 554 | return existingColor 555 | } 556 | 557 | let colorIndex = processColorMap.count % appColors.count 558 | let color = appColors[colorIndex] 559 | processColorMap[processName] = color 560 | return color 561 | } 562 | 563 | deinit { 564 | updateTimer?.invalidate() 565 | } 566 | } 567 | 568 | // MARK: - System Data Models (keeping existing optimization task structure) 569 | struct OptimizationMetric: Identifiable { 570 | let id = UUID() 571 | let title: String 572 | let category: String 573 | let description: String 574 | var currentValue: Double 575 | var previousValue: Double 576 | var targetValue: Double 577 | var unit: String 578 | var status: MetricStatus 579 | var lastUpdated: Date 580 | } 581 | 582 | struct MetricDataPoint: Identifiable { 583 | let id = UUID() 584 | let timestamp: Date 585 | let value: Double 586 | } 587 | 588 | enum MetricStatus: String, CaseIterable { 589 | case excellent = "excellent" 590 | case good = "good" 591 | case warning = "warning" 592 | case critical = "critical" 593 | 594 | var color: Color { 595 | switch self { 596 | case .excellent: return Color(red: 0.10, green: 0.85, blue: 0.50) 597 | case .good: return Color(red: 0.20, green: 0.60, blue: 1.00) 598 | case .warning: return Color(red: 1.00, green: 0.55, blue: 0.00) 599 | case .critical: return Color(red: 1.00, green: 0.22, blue: 0.30) 600 | } 601 | } 602 | 603 | var icon: String { 604 | switch self { 605 | case .excellent: return "checkmark.circle.fill" 606 | case .good: return "arrow.up.circle.fill" 607 | case .warning: return "exclamationmark.triangle.fill" 608 | case .critical: return "xmark.circle.fill" 609 | } 610 | } 611 | } 612 | 613 | struct OptimizationTask: Identifiable { 614 | let id: String 615 | let title: String 616 | let description: String 617 | let category: String 618 | let command: String 619 | var isSelected: Bool = false 620 | } 621 | 622 | // MARK: - System Monitor (keeping optimization functionality) 623 | class SystemMonitor: ObservableObject { 624 | @Published var currentMetrics: [OptimizationMetric] = [] 625 | @Published var isOptimizing = false 626 | @Published var optimizationTasks: [OptimizationTask] = [] 627 | @Published var selectedTasks: Set = [] 628 | @Published var realSystemMonitor = RealSystemMonitor() 629 | 630 | // Confirmation sheet 631 | @Published var showConfirmation = false 632 | @Published var lastRunTasks: [OptimizationTask] = [] 633 | @Published var lastRunDate: Date? 634 | 635 | init() { 636 | initializeOptimizationTasks() 637 | setupMetrics() 638 | } 639 | 640 | private func setupMetrics() { 641 | currentMetrics = [ 642 | OptimizationMetric( 643 | title: "Memory Usage", 644 | category: "System Resources", 645 | description: "Real-time RAM usage by applications", 646 | currentValue: 0, 647 | previousValue: 0, 648 | targetValue: 100, 649 | unit: "GB", 650 | status: .good, 651 | lastUpdated: Date() 652 | ), 653 | OptimizationMetric( 654 | title: "System Performance", 655 | category: "CPU & GPU", 656 | description: "Real-time processor usage", 657 | currentValue: 0, 658 | previousValue: 0, 659 | targetValue: 100, 660 | unit: "%", 661 | status: .good, 662 | lastUpdated: Date() 663 | ), 664 | OptimizationMetric( 665 | title: "Network Speed", 666 | category: "Connectivity", 667 | description: "Real-time network throughput (primary interface)", 668 | currentValue: 0, 669 | previousValue: 0, 670 | targetValue: 100, 671 | unit: "Mbps", 672 | status: .good, 673 | lastUpdated: Date() 674 | ), 675 | OptimizationMetric( 676 | title: "Urgent Attention", 677 | category: "Process Management", 678 | description: "Processes requiring attention", 679 | currentValue: 0, 680 | previousValue: 0, 681 | targetValue: 0, 682 | unit: " issues", 683 | status: .good, 684 | lastUpdated: Date() 685 | ) 686 | ] 687 | } 688 | 689 | private func initializeOptimizationTasks() { 690 | optimizationTasks = [ 691 | // Memory & Performance 692 | OptimizationTask(id: "purge_memory", title: "Purge inactive memory", description: "Free up inactive memory using purge command", category: "Memory & Performance", command: "sudo purge"), 693 | OptimizationTask(id: "clear_caches", title: "Clear system caches", description: "Clear user and system caches to free up space", category: "Memory & Performance", command: "sudo rm -rf ~/Library/Caches/* /Library/Caches/*"), 694 | OptimizationTask(id: "optimize_swap", title: "Optimize swap usage", description: "Configure swap settings for better performance", category: "Memory & Performance", command: "sudo purge"), 695 | OptimizationTask(id: "disable_spotlight", title: "Disable Spotlight indexing", description: "Turn off Spotlight indexing for better performance", category: "Memory & Performance", command: "sudo mdutil -i off /"), 696 | OptimizationTask(id: "reindex_spotlight", title: "Re-index Spotlight", description: "Rebuild Spotlight index for better search performance", category: "Memory & Performance", command: "sudo mdutil -E /"), 697 | OptimizationTask(id: "reduce_animations", title: "Reduce motion & animations", description: "Disable system animations for snappier performance", category: "Memory & Performance", command: "defaults write com.apple.universalaccess reduceMotion -bool true"), 698 | 699 | // System Tweaks 700 | OptimizationTask(id: "disable_dock_animation", title: "Disable Dock animations", description: "Remove Dock animations for faster response", category: "System Tweaks", command: "defaults write com.apple.dock autohide-time-modifier -int 0"), 701 | OptimizationTask(id: "disable_window_animations", title: "Disable window animations", description: "Remove window animations for snappier feel", category: "System Tweaks", command: "defaults write NSGlobalDomain NSAutomaticWindowAnimationsEnabled -bool false"), 702 | OptimizationTask(id: "optimize_launchpad", title: "Optimize Launchpad", description: "Speed up Launchpad loading and animations", category: "System Tweaks", command: "defaults write com.apple.dock springboard-show-duration -int 0"), 703 | OptimizationTask(id: "disable_dashboard", title: "Disable Dashboard", description: "Turn off Dashboard to save memory", category: "System Tweaks", command: "defaults write com.apple.dashboard mcx-disabled -bool true"), 704 | OptimizationTask(id: "optimize_finder", title: "Optimize Finder", description: "Configure Finder for better performance", category: "System Tweaks", command: "defaults write com.apple.finder AppleShowAllFiles YES"), 705 | OptimizationTask(id: "disable_sudden_motion", title: "Disable Sudden Motion Sensor", description: "Turn off SMS for SSDs (M-Series Macs)", category: "System Tweaks", command: "sudo pmset -a sms 0"), 706 | 707 | // Network 708 | OptimizationTask(id: "flush_dns", title: "Flush DNS cache", description: "Clear DNS cache for faster lookups", category: "Network", command: "sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder"), 709 | OptimizationTask(id: "optimize_network", title: "Optimize network settings", description: "Configure network for better performance", category: "Network", command: "sudo sysctl -w net.inet.tcp.delayed_ack=0"), 710 | OptimizationTask(id: "disable_ipv6", title: "Disable IPv6", description: "Turn off IPv6 if not needed", category: "Network", command: "networksetup -setv6off Wi-Fi"), 711 | OptimizationTask(id: "optimize_wifi", title: "Optimize Wi-Fi", description: "Configure Wi-Fi settings for better performance", category: "Network", command: "sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport prefs DisconnectOnLogout=NO"), 712 | 713 | // Development 714 | OptimizationTask(id: "optimize_git", title: "Optimize Git performance", description: "Configure Git for better performance", category: "Development", command: "git config --global core.precomposeunicode true"), 715 | OptimizationTask(id: "optimize_homebrew", title: "Optimize Homebrew", description: "Clean and optimize Homebrew installation", category: "Development", command: "brew cleanup"), 716 | OptimizationTask(id: "optimize_node", title: "Optimize Node.js", description: "Clean Node.js and npm cache", category: "Development", command: "npm cache clean --force"), 717 | OptimizationTask(id: "optimize_python", title: "Optimize Python", description: "Clean Python cache and optimize", category: "Development", command: "python -m pip cache purge"), 718 | OptimizationTask(id: "optimize_docker", title: "Optimize Docker", description: "Clean Docker containers and images", category: "Development", command: "docker system prune -f"), 719 | OptimizationTask(id: "optimize_xcode", title: "Optimize Xcode", description: "Clean Xcode derived data and cache", category: "Development", command: "rm -rf ~/Library/Developer/Xcode/DerivedData/*"), 720 | 721 | // Advanced 722 | OptimizationTask(id: "rebuild_spotlight", title: "Rebuild Spotlight index", description: "Completely rebuild Spotlight search index", category: "Advanced", command: "sudo mdutil -i off / && sudo mdutil -i on /"), 723 | OptimizationTask(id: "reset_launchservices", title: "Reset Launch Services", description: "Fix 'Open With' menu problems", category: "Advanced", command: "sudo /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local"), 724 | OptimizationTask(id: "clear_font_cache", title: "Clear font cache", description: "Clear system font cache", category: "Advanced", command: "sudo atsutil databases -remove"), 725 | OptimizationTask(id: "optimize_ssd", title: "Optimize SSD settings", description: "Configure SSD-specific optimizations", category: "Advanced", command: "sudo trimforce enable"), 726 | OptimizationTask(id: "disable_crash_reporter", title: "Disable crash reporter", description: "Turn off automatic crash reporting", category: "Advanced", command: "defaults write com.apple.CrashReporter DialogType none"), 727 | OptimizationTask(id: "optimize_metal", title: "Optimize Metal performance", description: "Configure Metal graphics performance", category: "Advanced", command: "defaults write com.apple.CoreGraphics CGDirectDisplayID -bool true") 728 | ] 729 | } 730 | 731 | func runOptimization() { 732 | guard !selectedTasks.isEmpty else { return } 733 | 734 | isOptimizing = true 735 | lastRunTasks = optimizationTasks.filter { selectedTasks.contains($0.id) } 736 | lastRunDate = Date() 737 | 738 | DispatchQueue.main.asyncAfter(deadline: .now() + 4) { 739 | self.isOptimizing = false 740 | self.showConfirmation = true 741 | } 742 | } 743 | 744 | func toggleTask(_ taskId: String) { 745 | if selectedTasks.contains(taskId) { 746 | selectedTasks.remove(taskId) 747 | } else { 748 | selectedTasks.insert(taskId) 749 | } 750 | } 751 | 752 | func getTasksByCategory(_ category: String) -> [OptimizationTask] { 753 | return optimizationTasks.filter { $0.category == category } 754 | } 755 | 756 | var categories: [String] { 757 | return Array(Set(optimizationTasks.map { $0.category })).sorted() 758 | } 759 | } 760 | 761 | // MARK: - Glass Card Component 762 | struct GlassCardView: View { 763 | let content: Content 764 | 765 | init(@ViewBuilder content: () -> Content) { 766 | self.content = content() 767 | } 768 | 769 | var body: some View { 770 | content 771 | .padding(20) 772 | .background( 773 | RoundedRectangle(cornerRadius: 16) 774 | .fill(.ultraThinMaterial) 775 | .overlay( 776 | RoundedRectangle(cornerRadius: 16) 777 | .stroke(Color.white.opacity(0.28), lineWidth: 1.2) 778 | ) 779 | .shadow(color: Color.black.opacity(0.25), radius: 14, y: 7) 780 | ) 781 | } 782 | } 783 | 784 | // MARK: - Real Memory Usage Chart 785 | struct RealMemoryUsageChart: View { 786 | @ObservedObject var realMonitor: RealSystemMonitor 787 | 788 | var body: some View { 789 | VStack(spacing: 8) { 790 | Chart { 791 | ForEach(Array(realMonitor.memoryInfo.appMemoryUsage.enumerated()), id: \.element.id) { _, app in 792 | BarMark( 793 | x: .value("App", app.name), 794 | y: .value("Memory", app.memoryUsage) 795 | ) 796 | .foregroundStyle(app.color) 797 | .cornerRadius(4) 798 | } 799 | } 800 | .chartYAxis { 801 | AxisMarks(position: .leading) { value in 802 | AxisGridLine(stroke: StrokeStyle(lineWidth: 0.6)) 803 | .foregroundStyle(Color.white.opacity(0.25)) 804 | AxisValueLabel() { 805 | if let mb = value.as(Double.self) { 806 | Text("\(Int(mb))MB") 807 | .font(.caption2) 808 | .foregroundColor(.secondary) 809 | } 810 | } 811 | } 812 | } 813 | .chartXAxis(.hidden) 814 | .frame(height: 80) 815 | 816 | LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 4) { 817 | ForEach(realMonitor.memoryInfo.appMemoryUsage) { app in 818 | HStack(spacing: 4) { 819 | Circle() 820 | .fill(app.color) 821 | .frame(width: 8, height: 8) 822 | Text(app.name) 823 | .font(.caption2) 824 | .foregroundColor(.secondary) 825 | .lineLimit(1) 826 | } 827 | } 828 | } 829 | } 830 | } 831 | } 832 | 833 | // MARK: - Real CPU Usage Chart 834 | struct RealCPUUsageChart: View { 835 | @ObservedObject var realMonitor: RealSystemMonitor 836 | 837 | var body: some View { 838 | VStack(spacing: 8) { 839 | Chart { 840 | ForEach(realMonitor.cpuProcesses) { process in 841 | BarMark( 842 | x: .value("Process", process.name), 843 | y: .value("CPU", process.cpuUsage) 844 | ) 845 | .foregroundStyle(process.color) 846 | .cornerRadius(4) 847 | } 848 | } 849 | .chartYAxis { 850 | AxisMarks(position: .leading) { value in 851 | AxisGridLine(stroke: StrokeStyle(lineWidth: 0.6)) 852 | .foregroundStyle(Color.white.opacity(0.25)) 853 | AxisValueLabel() { 854 | if let cpu = value.as(Double.self) { 855 | Text("\(Int(cpu))%") 856 | .font(.caption2) 857 | .foregroundColor(.secondary) 858 | } 859 | } 860 | } 861 | } 862 | .chartXAxis(.hidden) 863 | .frame(height: 80) 864 | 865 | LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 4) { 866 | ForEach(realMonitor.cpuProcesses) { process in 867 | HStack(spacing: 4) { 868 | Circle() 869 | .fill(process.color) 870 | .frame(width: 8, height: 8) 871 | Text(process.name) 872 | .font(.caption2) 873 | .foregroundColor(.secondary) 874 | .lineLimit(1) 875 | } 876 | } 877 | } 878 | } 879 | } 880 | } 881 | 882 | // MARK: - Real Network Speed Chart 883 | struct RealNetworkSpeedChart: View { 884 | @ObservedObject var realMonitor: RealSystemMonitor 885 | 886 | var body: some View { 887 | Chart { 888 | ForEach(realMonitor.networkHistory, id: \.timestamp) { speed in 889 | LineMark( 890 | x: .value("Time", speed.timestamp), 891 | y: .value("Download", speed.downloadMbps) 892 | ) 893 | .foregroundStyle(Color(red: 0.20, green: 0.60, blue: 1.00)) 894 | .lineStyle(StrokeStyle(lineWidth: 2)) 895 | 896 | LineMark( 897 | x: .value("Time", speed.timestamp), 898 | y: .value("Upload", speed.uploadMbps) 899 | ) 900 | .foregroundStyle(Color(red: 0.10, green: 0.85, blue: 0.50)) 901 | .lineStyle(StrokeStyle(lineWidth: 2)) 902 | } 903 | } 904 | .chartXAxis(.hidden) 905 | .chartYAxis { 906 | AxisMarks(position: .leading) { value in 907 | AxisGridLine(stroke: StrokeStyle(lineWidth: 0.6)) 908 | .foregroundStyle(Color.white.opacity(0.25)) 909 | AxisValueLabel() { 910 | if let mbps = value.as(Double.self) { 911 | Text("\(String(format: "%.2f", mbps))") 912 | .font(.caption2) 913 | .foregroundColor(.secondary) 914 | } 915 | } 916 | } 917 | } 918 | .frame(height: 60) 919 | .overlay(alignment: .bottomTrailing) { 920 | HStack(spacing: 12) { 921 | HStack(spacing: 4) { 922 | Circle().fill(Color(red: 0.20, green: 0.60, blue: 1.00)).frame(width: 8, height: 8) 923 | Text("Down") 924 | .font(.caption2) 925 | .foregroundColor(.secondary) 926 | } 927 | HStack(spacing: 4) { 928 | Circle().fill(Color(red: 0.10, green: 0.85, blue: 0.50)).frame(width: 8, height: 8) 929 | Text("Up") 930 | .font(.caption2) 931 | .foregroundColor(.secondary) 932 | } 933 | } 934 | } 935 | } 936 | } 937 | 938 | // MARK: - Real Urgent Processes List (with working Force Quit) 939 | struct RealUrgentProcessesList: View { 940 | @ObservedObject var realMonitor: RealSystemMonitor 941 | 942 | var body: some View { 943 | VStack(alignment: .leading, spacing: 8) { 944 | if realMonitor.urgentProcesses.isEmpty { 945 | Text("No urgent issues detected") 946 | .font(.caption) 947 | .foregroundColor(.green) 948 | .frame(maxWidth: .infinity, alignment: .center) 949 | .padding() 950 | } else { 951 | ForEach(realMonitor.urgentProcesses) { process in 952 | HStack(spacing: 12) { 953 | Circle() 954 | .fill(process.priority.color) 955 | .frame(width: 12, height: 12) 956 | 957 | VStack(alignment: .leading, spacing: 2) { 958 | Text(process.name) 959 | .font(.caption) 960 | .fontWeight(.medium) 961 | .foregroundColor(.primary) 962 | 963 | Text(process.issue) 964 | .font(.caption2) 965 | .foregroundColor(.secondary) 966 | } 967 | 968 | Spacer() 969 | 970 | Button("Force Quit") { 971 | realMonitor.forceQuitProcess(pid: process.pid) 972 | } 973 | .font(.caption2) 974 | .foregroundColor(.white) 975 | .padding(.horizontal, 8) 976 | .padding(.vertical, 4) 977 | .background(process.priority.color) 978 | .cornerRadius(6) 979 | } 980 | .padding(.horizontal, 8) 981 | .padding(.vertical, 6) 982 | .background(Color.black.opacity(0.25)) 983 | .cornerRadius(8) 984 | } 985 | } 986 | } 987 | } 988 | } 989 | 990 | // MARK: - Enhanced Metric Card with Real System Data 991 | struct MetricCardView: View { 992 | let metric: OptimizationMetric 993 | @ObservedObject var realSystemMonitor: RealSystemMonitor 994 | @State private var isAnimating = false 995 | 996 | // New: popover for the top-right badge 997 | @State private var showDetails = false 998 | 999 | var body: some View { 1000 | GlassCardView { 1001 | VStack(alignment: .leading, spacing: 16) { 1002 | HStack { 1003 | VStack(alignment: .leading, spacing: 4) { 1004 | Text(metric.title) 1005 | .font(.system(.title2, design: .rounded, weight: .bold)) 1006 | .foregroundStyle( 1007 | LinearGradient( 1008 | colors: [Color.white, Color.white.opacity(0.92)], 1009 | startPoint: .leading, 1010 | endPoint: .trailing 1011 | ) 1012 | ) 1013 | 1014 | Text(metric.category) 1015 | .font(.system(.subheadline, design: .rounded, weight: .medium)) 1016 | .foregroundColor(.secondary) 1017 | } 1018 | 1019 | Spacer() 1020 | 1021 | // Make the badge actionable 1022 | Button { 1023 | showDetails.toggle() 1024 | } label: { 1025 | ZStack { 1026 | Circle() 1027 | .fill(getStatusColor().opacity(0.22)) 1028 | .frame(width: 40, height: 40) 1029 | 1030 | Image(systemName: getStatusIcon()) 1031 | .font(.system(.subheadline, weight: .bold)) 1032 | .foregroundColor(getStatusColor()) 1033 | } 1034 | } 1035 | .buttonStyle(.plain) 1036 | .popover(isPresented: $showDetails) { 1037 | detailsView 1038 | .padding(16) 1039 | .frame(minWidth: 260) 1040 | } 1041 | } 1042 | 1043 | VStack(alignment: .leading, spacing: 12) { 1044 | HStack { 1045 | switch metric.title { 1046 | case "Memory Usage": 1047 | Text("Used: \(String(format: "%.1f", realSystemMonitor.memoryInfo.usedMemory))GB / \(String(format: "%.1f", realSystemMonitor.memoryInfo.totalMemory))GB") 1048 | .font(.system(.headline, design: .monospaced, weight: .bold)) 1049 | .foregroundColor(.primary) 1050 | 1051 | case "System Performance": 1052 | Text("CPU Usage: \(String(format: "%.1f", realSystemMonitor.totalCPUUsage))%") 1053 | .font(.system(.headline, design: .monospaced, weight: .bold)) 1054 | .foregroundColor(.primary) 1055 | 1056 | case "Network Speed": 1057 | if let latest = realSystemMonitor.networkHistory.last, realSystemMonitor.networkHistory.count > 1 { 1058 | VStack(alignment: .leading, spacing: 2) { 1059 | Text("↓ \(String(format: "%.2f", latest.downloadMbps)) Mbps") 1060 | .font(.system(.subheadline, design: .monospaced, weight: .bold)) 1061 | .foregroundColor(Color(red: 0.20, green: 0.60, blue: 1.00)) 1062 | Text("↑ \(String(format: "%.2f", latest.uploadMbps)) Mbps") 1063 | .font(.system(.subheadline, design: .monospaced, weight: .bold)) 1064 | .foregroundColor(Color(red: 0.10, green: 0.85, blue: 0.50)) 1065 | } 1066 | } else { 1067 | Text("Measuring...") 1068 | .font(.system(.headline, design: .rounded)) 1069 | .foregroundColor(.secondary) 1070 | } 1071 | 1072 | case "Urgent Attention": 1073 | Text("\(realSystemMonitor.urgentProcesses.count) issues need attention") 1074 | .font(.system(.headline, design: .rounded, weight: .bold)) 1075 | .foregroundColor(getStatusColor()) 1076 | 1077 | default: 1078 | Text("Monitoring...") 1079 | .font(.system(.headline, design: .monospaced, weight: .bold)) 1080 | .foregroundColor(.primary) 1081 | } 1082 | 1083 | Spacer() 1084 | } 1085 | 1086 | // Real system data visualization 1087 | switch metric.title { 1088 | case "Memory Usage": 1089 | RealMemoryUsageChart(realMonitor: realSystemMonitor) 1090 | 1091 | case "System Performance": 1092 | RealCPUUsageChart(realMonitor: realSystemMonitor) 1093 | 1094 | case "Network Speed": 1095 | RealNetworkSpeedChart(realMonitor: realSystemMonitor) 1096 | 1097 | case "Urgent Attention": 1098 | RealUrgentProcessesList(realMonitor: realSystemMonitor) 1099 | 1100 | default: 1101 | EmptyView() 1102 | } 1103 | } 1104 | } 1105 | } 1106 | .frame(minWidth: 320, maxWidth: .infinity, minHeight: 280) 1107 | .scaleEffect(isAnimating ? 1.0 : 0.95) 1108 | .opacity(isAnimating ? 1.0 : 0.0) 1109 | .onAppear { 1110 | withAnimation(.easeInOut(duration: 0.8)) { 1111 | isAnimating = true 1112 | } 1113 | } 1114 | } 1115 | 1116 | private var detailsView: some View { 1117 | VStack(alignment: .leading, spacing: 10) { 1118 | Text(metric.title) 1119 | .font(.headline) 1120 | switch metric.title { 1121 | case "Memory Usage": 1122 | if realSystemMonitor.memoryInfo.appMemoryUsage.isEmpty { 1123 | Text("Collecting memory data…") 1124 | .foregroundColor(.secondary) 1125 | } else { 1126 | ForEach(realSystemMonitor.memoryInfo.appMemoryUsage) { p in 1127 | HStack { 1128 | Circle().fill(p.color).frame(width: 6, height: 6) 1129 | Text(p.name).lineLimit(1) 1130 | Spacer() 1131 | Text("\(Int(p.memoryUsage)) MB") 1132 | .font(.system(.caption, design: .monospaced)) 1133 | .foregroundColor(.secondary) 1134 | } 1135 | } 1136 | } 1137 | case "System Performance": 1138 | if realSystemMonitor.cpuProcesses.isEmpty { 1139 | Text("Collecting CPU data…").foregroundColor(.secondary) 1140 | } else { 1141 | ForEach(realSystemMonitor.cpuProcesses) { p in 1142 | HStack { 1143 | Circle().fill(p.color).frame(width: 6, height: 6) 1144 | Text(p.name).lineLimit(1) 1145 | Spacer() 1146 | Text("\(String(format: "%.1f", p.cpuUsage))%") 1147 | .font(.system(.caption, design: .monospaced)) 1148 | .foregroundColor(.secondary) 1149 | } 1150 | } 1151 | } 1152 | case "Network Speed": 1153 | if let s = realSystemMonitor.networkHistory.last, realSystemMonitor.networkHistory.count > 1 { 1154 | Text("Down: \(String(format: "%.2f", s.downloadMbps)) Mbps") 1155 | Text("Up: \(String(format: "%.2f", s.uploadMbps)) Mbps") 1156 | } else { 1157 | Text("Measuring…").foregroundColor(.secondary) 1158 | } 1159 | case "Urgent Attention": 1160 | Button { 1161 | realSystemMonitor.forceQuitProcess(pid: -1) // harmless refresh 1162 | } label: { 1163 | Label("Refresh List", systemImage: "arrow.clockwise") 1164 | } 1165 | default: 1166 | Text("No actions available.") 1167 | } 1168 | } 1169 | .frame(maxWidth: .infinity, alignment: .leading) 1170 | } 1171 | 1172 | private func getStatusColor() -> Color { 1173 | switch metric.title { 1174 | case "Urgent Attention": 1175 | let count = realSystemMonitor.urgentProcesses.count 1176 | if count == 0 { return Color(red: 0.10, green: 0.85, blue: 0.50) } 1177 | else if count <= 2 { return Color(red: 1.00, green: 0.84, blue: 0.00) } 1178 | else if count <= 4 { return Color(red: 1.00, green: 0.55, blue: 0.00) } 1179 | else { return Color(red: 1.00, green: 0.22, blue: 0.30) } 1180 | case "Memory Usage": 1181 | let total = max(realSystemMonitor.memoryInfo.totalMemory, 0.0001) 1182 | let percentUsed = (realSystemMonitor.memoryInfo.usedMemory / total) * 100 1183 | if percentUsed < 60 { return Color(red: 0.10, green: 0.85, blue: 0.50) } 1184 | else if percentUsed < 80 { return Color(red: 1.00, green: 0.84, blue: 0.00) } 1185 | else { return Color(red: 1.00, green: 0.22, blue: 0.30) } 1186 | default: 1187 | return Color(red: 0.20, green: 0.60, blue: 1.00) 1188 | } 1189 | } 1190 | 1191 | private func getStatusIcon() -> String { 1192 | let color = getStatusColor() 1193 | switch color { 1194 | case Color(red: 0.10, green: 0.85, blue: 0.50): return "checkmark.circle.fill" 1195 | case Color(red: 1.00, green: 0.84, blue: 0.00): return "exclamationmark.triangle.fill" 1196 | case Color(red: 1.00, green: 0.55, blue: 0.00): return "exclamationmark.triangle.fill" 1197 | case Color(red: 1.00, green: 0.22, blue: 0.30): return "xmark.circle.fill" 1198 | default: return "info.circle.fill" 1199 | } 1200 | } 1201 | } 1202 | 1203 | // MARK: - Clickable Optimization Task Row 1204 | struct OptimizationTaskRow: View { 1205 | let task: OptimizationTask 1206 | let isSelected: Bool 1207 | let onToggle: () -> Void 1208 | 1209 | var body: some View { 1210 | Button(action: onToggle) { 1211 | HStack(spacing: 16) { 1212 | ZStack { 1213 | RoundedRectangle(cornerRadius: 8) 1214 | .fill(isSelected ? Color(red: 0.20, green: 0.60, blue: 1.00) : Color.clear) 1215 | .stroke(Color(red: 0.20, green: 0.60, blue: 1.00), lineWidth: 2) 1216 | .frame(width: 24, height: 24) 1217 | 1218 | if isSelected { 1219 | Image(systemName: "checkmark") 1220 | .font(.system(.subheadline, weight: .bold)) 1221 | .foregroundColor(.white) 1222 | } 1223 | } 1224 | 1225 | VStack(alignment: .leading, spacing: 6) { 1226 | Text(task.title) 1227 | .font(.system(.title3, design: .rounded, weight: .semibold)) 1228 | .foregroundStyle( 1229 | LinearGradient( 1230 | colors: [Color.white, Color.white.opacity(0.92)], 1231 | startPoint: .leading, 1232 | endPoint: .trailing 1233 | ) 1234 | ) 1235 | 1236 | Text(task.description) 1237 | .font(.system(.subheadline, design: .rounded)) 1238 | .foregroundColor(.secondary) 1239 | .multilineTextAlignment(.leading) 1240 | } 1241 | 1242 | Spacer() 1243 | } 1244 | .padding(.horizontal, 20) 1245 | .padding(.vertical, 16) 1246 | .background( 1247 | RoundedRectangle(cornerRadius: 12) 1248 | .fill(isSelected ? Color(red: 0.20, green: 0.60, blue: 1.00).opacity(0.18) : Color.clear) 1249 | .stroke(isSelected ? Color(red: 0.20, green: 0.60, blue: 1.00).opacity(0.45) : Color.clear, lineWidth: 2) 1250 | ) 1251 | .contentShape(Rectangle()) 1252 | } 1253 | .buttonStyle(.plain) 1254 | } 1255 | } 1256 | 1257 | // MARK: - Enhanced Optimization Category View 1258 | struct OptimizationCategoryView: View { 1259 | let category: String 1260 | @ObservedObject var systemMonitor: SystemMonitor 1261 | 1262 | var body: some View { 1263 | ZStack { 1264 | LinearGradient( 1265 | colors: [ 1266 | Color(red: 0.04, green: 0.05, blue: 0.16), 1267 | Color(red: 0.10, green: 0.05, blue: 0.22), 1268 | Color(red: 0.18, green: 0.12, blue: 0.28) 1269 | ], 1270 | startPoint: .topLeading, 1271 | endPoint: .bottomTrailing 1272 | ) 1273 | .ignoresSafeArea() 1274 | 1275 | ScrollView { 1276 | VStack(spacing: 24) { 1277 | HStack { 1278 | Text(category) 1279 | .font(.system(.largeTitle, design: .rounded, weight: .bold)) 1280 | .foregroundStyle( 1281 | LinearGradient( 1282 | colors: [Color.white, Color.white.opacity(0.86)], 1283 | startPoint: .leading, 1284 | endPoint: .trailing 1285 | ) 1286 | ) 1287 | 1288 | Spacer() 1289 | 1290 | Text("\(systemMonitor.getTasksByCategory(category).filter { systemMonitor.selectedTasks.contains($0.id) }.count) selected") 1291 | .font(.system(.headline, design: .rounded, weight: .medium)) 1292 | .foregroundColor(.secondary) 1293 | } 1294 | .padding(.horizontal, 24) 1295 | .padding(.top, 24) 1296 | 1297 | GlassCardView { 1298 | VStack(spacing: 12) { 1299 | ForEach(systemMonitor.getTasksByCategory(category)) { task in 1300 | OptimizationTaskRow( 1301 | task: task, 1302 | isSelected: systemMonitor.selectedTasks.contains(task.id) 1303 | ) { 1304 | systemMonitor.toggleTask(task.id) 1305 | } 1306 | 1307 | if task.id != systemMonitor.getTasksByCategory(category).last?.id { 1308 | Divider() 1309 | .padding(.horizontal, 20) 1310 | } 1311 | } 1312 | } 1313 | } 1314 | .padding(.horizontal, 24) 1315 | 1316 | Spacer(minLength: 100) 1317 | } 1318 | } 1319 | } 1320 | } 1321 | } 1322 | 1323 | // MARK: - Enhanced Dashboard View 1324 | struct DashboardView: View { 1325 | @ObservedObject var systemMonitor: SystemMonitor 1326 | 1327 | var body: some View { 1328 | ZStack { 1329 | LinearGradient( 1330 | colors: [ 1331 | Color(red: 0.04, green: 0.05, blue: 0.16), 1332 | Color(red: 0.10, green: 0.05, blue: 0.22), 1333 | Color(red: 0.18, green: 0.12, blue: 0.28) 1334 | ], 1335 | startPoint: .topLeading, 1336 | endPoint: .bottomTrailing 1337 | ) 1338 | .ignoresSafeArea() 1339 | 1340 | ScrollView(showsIndicators: false) { 1341 | VStack(spacing: 32) { 1342 | VStack(spacing: 16) { 1343 | Text("OptiMac by VonKleistL") 1344 | .font(.system(.largeTitle, design: .rounded, weight: .heavy)) 1345 | .foregroundStyle( 1346 | LinearGradient( 1347 | colors: [ 1348 | Color.white, 1349 | Color(red: 0.80, green: 0.92, blue: 1.00), 1350 | Color.white.opacity(0.92) 1351 | ], 1352 | startPoint: .leading, 1353 | endPoint: .trailing 1354 | ) 1355 | ) 1356 | 1357 | Text("M-Series Performance Suite • Real-Time System Monitor") 1358 | .font(.system(.title2, design: .rounded, weight: .medium)) 1359 | .foregroundStyle( 1360 | LinearGradient( 1361 | colors: [Color.white.opacity(0.88), Color.white.opacity(0.66)], 1362 | startPoint: .leading, 1363 | endPoint: .trailing 1364 | ) 1365 | ) 1366 | } 1367 | .padding(.top, 24) 1368 | 1369 | GlassCardView { 1370 | HStack { 1371 | VStack(alignment: .leading, spacing: 8) { 1372 | Text("Quick Optimization") 1373 | .font(.system(.title2, design: .rounded, weight: .bold)) 1374 | .foregroundStyle( 1375 | LinearGradient( 1376 | colors: [Color.white, Color.white.opacity(0.92)], 1377 | startPoint: .leading, 1378 | endPoint: .trailing 1379 | ) 1380 | ) 1381 | 1382 | Text("\(systemMonitor.selectedTasks.count) optimizations selected") 1383 | .font(.system(.subheadline, design: .rounded, weight: .medium)) 1384 | .foregroundColor(.secondary) 1385 | } 1386 | 1387 | Spacer() 1388 | 1389 | Button(action: { 1390 | systemMonitor.runOptimization() 1391 | }) { 1392 | HStack(spacing: 10) { 1393 | if systemMonitor.isOptimizing { 1394 | ProgressView() 1395 | .progressViewStyle(CircularProgressViewStyle(tint: .white)) 1396 | .scaleEffect(0.9) 1397 | } else { 1398 | Image(systemName: "bolt.fill") 1399 | .font(.system(.subheadline, weight: .bold)) 1400 | } 1401 | 1402 | Text(systemMonitor.isOptimizing ? "Optimizing..." : "Run Boost") 1403 | .font(.system(.headline, design: .rounded, weight: .bold)) 1404 | } 1405 | .foregroundColor(.white) 1406 | .padding(.horizontal, 24) 1407 | .padding(.vertical, 14) 1408 | .background( 1409 | LinearGradient( 1410 | colors: [Color(red: 0.20, green: 0.60, blue: 1.00), Color(red: 0.60, green: 0.40, blue: 1.00)], 1411 | startPoint: .leading, 1412 | endPoint: .trailing 1413 | ) 1414 | ) 1415 | .clipShape(Capsule()) 1416 | .shadow(color: Color(red: 0.20, green: 0.60, blue: 1.00).opacity(0.35), radius: 10, y: 5) 1417 | } 1418 | .buttonStyle(.plain) 1419 | .disabled(systemMonitor.isOptimizing || systemMonitor.selectedTasks.isEmpty) 1420 | } 1421 | } 1422 | 1423 | LazyVGrid(columns: [ 1424 | GridItem(.flexible(), spacing: 20), 1425 | GridItem(.flexible(), spacing: 20) 1426 | ], spacing: 20) { 1427 | ForEach(systemMonitor.currentMetrics) { metric in 1428 | MetricCardView(metric: metric, realSystemMonitor: systemMonitor.realSystemMonitor) 1429 | } 1430 | } 1431 | 1432 | Spacer(minLength: 50) 1433 | } 1434 | .padding(.horizontal, 24) 1435 | } 1436 | } 1437 | // Confirmation sheet after optimizations complete 1438 | .sheet(isPresented: $systemMonitor.showConfirmation) { 1439 | VStack(alignment: .leading, spacing: 16) { 1440 | HStack { 1441 | Image(systemName: "checkmark.seal.fill") 1442 | .foregroundColor(.green) 1443 | Text("Optimizations Completed") 1444 | .font(.title2).bold() 1445 | } 1446 | if let date = systemMonitor.lastRunDate { 1447 | Text("Finished at \(date.formatted(date: .abbreviated, time: .standard))") 1448 | .foregroundColor(.secondary) 1449 | } 1450 | if systemMonitor.lastRunTasks.isEmpty { 1451 | Text("No tasks were executed.") 1452 | } else { 1453 | Text("Tasks run:") 1454 | .font(.headline) 1455 | ScrollView { 1456 | VStack(alignment: .leading, spacing: 8) { 1457 | ForEach(systemMonitor.lastRunTasks) { task in 1458 | HStack { 1459 | Image(systemName: "bolt.fill").foregroundColor(Color(red: 0.20, green: 0.60, blue: 1.00)) 1460 | Text(task.title) 1461 | Spacer() 1462 | } 1463 | } 1464 | } 1465 | } 1466 | .frame(minHeight: 120, maxHeight: 240) 1467 | } 1468 | HStack { 1469 | Spacer() 1470 | Button("Done") { systemMonitor.showConfirmation = false } 1471 | .keyboardShortcut(.defaultAction) 1472 | } 1473 | } 1474 | .padding(24) 1475 | .frame(minWidth: 420) 1476 | } 1477 | } 1478 | } 1479 | 1480 | // MARK: - Main Content View 1481 | struct ContentView: View { 1482 | // Injected shared SystemMonitor instead of owning our own 1483 | @ObservedObject var systemMonitor: SystemMonitor 1484 | 1485 | init(systemMonitor: SystemMonitor) { 1486 | self.systemMonitor = systemMonitor 1487 | } 1488 | 1489 | var body: some View { 1490 | TabView { 1491 | DashboardView(systemMonitor: systemMonitor) 1492 | .tabItem { 1493 | Image(systemName: "chart.bar.fill") 1494 | Text("Dashboard") 1495 | } 1496 | 1497 | OptimizationCategoryView(category: "Memory & Performance", systemMonitor: systemMonitor) 1498 | .tabItem { 1499 | Image(systemName: "memorychip.fill") 1500 | Text("Memory") 1501 | } 1502 | 1503 | OptimizationCategoryView(category: "System Tweaks", systemMonitor: systemMonitor) 1504 | .tabItem { 1505 | Image(systemName: "gearshape.2.fill") 1506 | Text("System") 1507 | } 1508 | 1509 | OptimizationCategoryView(category: "Network", systemMonitor: systemMonitor) 1510 | .tabItem { 1511 | Image(systemName: "wifi") 1512 | Text("Network") 1513 | } 1514 | 1515 | OptimizationCategoryView(category: "Development", systemMonitor: systemMonitor) 1516 | .tabItem { 1517 | Image(systemName: "hammer.fill") 1518 | Text("Development") 1519 | } 1520 | 1521 | OptimizationCategoryView(category: "Advanced", systemMonitor: systemMonitor) 1522 | .tabItem { 1523 | Image(systemName: "cpu.fill") 1524 | Text("Advanced") 1525 | } 1526 | } 1527 | .preferredColorScheme(.dark) 1528 | .accentColor(Color(red: 0.20, green: 0.60, blue: 1.00)) 1529 | } 1530 | } 1531 | 1532 | #Preview { 1533 | ContentView(systemMonitor: SystemMonitor()) 1534 | .frame(width: 1200, height: 800) 1535 | } 1536 | --------------------------------------------------------------------------------