@@ -11,32 +11,18 @@ import Cocoa
11
11
@NSApplicationMain
12
12
class AppDelegate : NSObject , NSApplicationDelegate {
13
13
14
- @IBOutlet var menu : NSMenu !
15
- @IBOutlet var quitMenuItem : NSMenuItem !
16
- @IBOutlet var item1 : NSMenuItem !
17
- @IBOutlet var item2 : NSMenuItem !
18
- @IBOutlet var item3 : NSMenuItem !
19
- @IBOutlet var item4 : NSMenuItem !
20
- @IBOutlet var item5 : NSMenuItem !
21
- @IBOutlet var item6 : NSMenuItem !
22
- @IBOutlet var item7 : NSMenuItem !
23
- @IBOutlet var item8 : NSMenuItem !
24
- @IBOutlet var item9 : NSMenuItem !
25
- @IBOutlet var item10 : NSMenuItem !
26
-
27
- lazy var menuItems : [ NSMenuItem ] = [
28
- item1, item2, item3, item4, item5, item6, item7, item8, item9, item10
29
- ]
30
-
14
+ let popover = NSPopover ( )
15
+ let netspeedViewController = NetSpeedViewController . freshController ( )
16
+
31
17
var processSpeeds : [ ( name: String , download: Double , upload: Double ) ] = [ ]
32
-
18
+
33
19
var uploadSpeed : Double = 0.0
34
20
var downloadSpeed : Double = 0.0
35
21
var uploadMetric : String = " KB "
36
22
var downloadMetric : String = " KB "
37
23
var statusItem = NSStatusBar . system. statusItem ( withLength: NSStatusItem . variableLength)
38
24
var timer : Timer !
39
-
25
+
40
26
var statusBarTextAttributes : [ NSAttributedString . Key : Any ] {
41
27
let paragraphStyle = NSMutableParagraphStyle ( )
42
28
paragraphStyle. maximumLineHeight = 10
@@ -55,65 +41,35 @@ class AppDelegate: NSObject, NSApplicationDelegate {
55
41
NSAttributedString . Key. paragraphStyle: paragraphStyle
56
42
] as [ NSAttributedString . Key : Any ]
57
43
}
58
-
44
+
59
45
func updateSpeed( ) {
60
- downloadSpeed = 0.0
61
- uploadSpeed = 0.0
62
- for speed in processSpeeds {
63
- downloadSpeed += speed. download
64
- uploadSpeed += speed. upload
65
- }
66
- downloadMetric = " KB "
67
- if ( downloadSpeed > 1024.0 ) {
68
- downloadSpeed /= 1024.0
69
- downloadMetric = " MB "
70
- }
71
- uploadMetric = " KB "
72
- if ( uploadSpeed > 1024.0 ) {
73
- uploadSpeed /= 1024.0
74
- uploadMetric = " MB "
75
- }
76
-
77
46
if let button = statusItem. button {
78
47
button. attributedTitle = NSAttributedString ( string: " \n \( String ( format: " %7.2lf " , uploadSpeed) ) \( uploadMetric) /s ↑ \n \( String ( format: " %7.2lf " , downloadSpeed) ) \( downloadMetric) /s ↓ " , attributes: statusBarTextAttributes)
79
48
}
80
- for i in 0 ..< menuItems. count {
81
- downloadMetric = " KB "
82
- if ( processSpeeds [ i] . download > 1024.0 ) {
83
- processSpeeds [ i] . download /= 1024.0
84
- downloadMetric = " MB "
85
- }
86
- uploadMetric = " KB "
87
- if ( processSpeeds [ i] . upload > 1024.0 ) {
88
- processSpeeds [ i] . upload /= 1024.0
89
- uploadMetric = " MB "
90
- }
91
- menuItems [ i] . isHidden = false
92
- menuItems [ i] . attributedTitle = NSAttributedString ( string: " \( processSpeeds [ i] . name) \( String ( format: " %7.2lf " , processSpeeds [ i] . download) ) \( downloadMetric) /s ↓ \( String ( format: " %7.2lf " , processSpeeds [ i] . upload) ) \( uploadMetric) /s ↑ " , attributes: menuItemTextAttributes)
93
- }
49
+
50
+ netspeedViewController. processes = processSpeeds
51
+ netspeedViewController. tableView. reloadData ( )
94
52
}
95
53
96
54
func applicationDidFinishLaunching( _ aNotification: Notification ) {
97
55
statusItem. length = 75
98
56
if let button = statusItem. button {
99
57
button. attributedTitle = NSAttributedString ( string: " \n \( String ( format: " %7.2lf " , 0.0 ) ) KB/s ↑ \n \( String ( format: " %7.2lf " , 0.0 ) ) KB/s ↓ " , attributes: statusBarTextAttributes)
58
+ button. action = #selector( togglePopover ( _: ) )
100
59
}
101
-
102
- quitMenuItem. action = #selector( NSApplication . terminate ( _: ) )
103
-
104
- statusItem. menu = menu
105
-
60
+ popover. contentViewController = netspeedViewController
61
+
106
62
timer = Timer . scheduledTimer ( withTimeInterval: 2 , repeats: true ) { timer in
107
63
DispatchQueue . global ( qos: . background) . async {
108
64
let topTask = Process ( )
109
65
topTask. launchPath = " /usr/bin/env "
110
66
topTask. arguments = [ " nettop " , " -d " , " -P " , " -J " , " bytes_in,bytes_out " , " -x " , " -L " , " 2 " , " -c " ]
111
-
67
+
112
68
let outpipe = Pipe ( )
113
69
topTask. standardOutput = outpipe
114
70
topTask. launch ( )
115
71
topTask. waitUntilExit ( )
116
-
72
+
117
73
if let outputString = String ( data: outpipe. fileHandleForReading. readDataToEndOfFile ( ) , encoding: . utf8) {
118
74
let splitStrings = outputString. split ( separator: " \n " )
119
75
let length = splitStrings. count / 2
@@ -124,14 +80,51 @@ class AppDelegate: NSObject, NSApplicationDelegate {
124
80
}
125
81
self . processSpeeds. sort ( by: { $0. download > $1. download} )
126
82
}
127
-
83
+
128
84
topTask. terminate ( )
129
-
85
+
86
+ self . downloadSpeed = 0.0
87
+ self . uploadSpeed = 0.0
88
+ for speed in self . processSpeeds {
89
+ self . downloadSpeed += speed. download
90
+ self . uploadSpeed += speed. upload
91
+ }
92
+ if ( self . downloadSpeed > 1024.0 ) {
93
+ self . downloadSpeed /= 1024.0
94
+ self . downloadMetric = " MB "
95
+ } else {
96
+ self . downloadMetric = " KB "
97
+ }
98
+ if ( self . uploadSpeed > 1024.0 ) {
99
+ self . uploadSpeed /= 1024.0
100
+ self . uploadMetric = " MB "
101
+ } else {
102
+ self . uploadMetric = " KB "
103
+ }
104
+
130
105
DispatchQueue . main. async {
131
106
self . updateSpeed ( )
132
107
}
133
108
}
134
109
}
135
110
RunLoop . current. add ( timer, forMode: . common)
136
111
}
112
+
113
+ @objc func togglePopover( _ sender: Any ? ) {
114
+ if popover. isShown {
115
+ closePopover ( sender: sender)
116
+ } else {
117
+ showPopover ( sender: sender)
118
+ }
119
+ }
120
+
121
+ func showPopover( sender: Any ? ) {
122
+ if let button = statusItem. button {
123
+ popover. show ( relativeTo: button. bounds, of: button, preferredEdge: NSRectEdge . minY)
124
+ }
125
+ }
126
+
127
+ func closePopover( sender: Any ? ) {
128
+ popover. performClose ( sender)
129
+ }
137
130
}
0 commit comments