Skip to content

Instantly share code, notes, and snippets.

@alin23
Last active January 5, 2024 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alin23/e15b6ffc62a85790096f0228c54fd31e to your computer and use it in GitHub Desktop.
Save alin23/e15b6ffc62a85790096f0228c54fd31e to your computer and use it in GitHub Desktop.
// swiftc -o /tmp/InternetReachable ~/Temp/InternetReachable.swift && /tmp/InternetReachable
import AppKit
import Cocoa
import Foundation
import Network
private var window: NSWindow = {
let w = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: NSScreen.main!.frame.width, height: 20),
styleMask: [.fullSizeContentView, .borderless],
backing: .buffered,
defer: false
)
w.backgroundColor = .clear
w.level = NSWindow.Level(Int(CGShieldingWindowLevel()))
w.isOpaque = false
w.hasShadow = false
w.hidesOnDeactivate = false
w.ignoresMouseEvents = true
w.isReleasedWhenClosed = false
w.isMovableByWindowBackground = false
w.sharingType = .none
w.setAccessibilityRole(.popover)
w.setAccessibilitySubrole(.unknown)
w.collectionBehavior = [.canJoinAllSpaces, .stationary, .ignoresCycle, .fullScreenDisallowsTiling]
return w
}()
private var windowController = NSWindowController(window: window)
private var fader: DispatchWorkItem? { didSet { oldValue?.cancel() } }
private var closer: DispatchWorkItem? { didSet { oldValue?.cancel() } }
private func mainAsyncAfter(_ duration: TimeInterval, _ action: @escaping () -> Void) -> DispatchWorkItem {
let workItem = DispatchWorkItem { action() }
DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: workItem)
return workItem
}
private func drawColoredTopLine(_ color: NSColor, hideAfter: TimeInterval = 5) {
DispatchQueue.main.async {
lastColor = color
lastHideAfter = hideAfter
let box = NSBox()
box.boxType = .custom
box.fillColor = color
box.frame = NSRect(x: 0, y: 10, width: NSScreen.main!.frame.width + 10, height: 3)
box.shadow = NSShadow()
box.shadow!.shadowColor = color
box.shadow!.shadowBlurRadius = 3
box.shadow!.shadowOffset = .init(width: 0, height: -2)
let containerView = NSView()
containerView.frame = NSRect(x: 0, y: 0, width: NSScreen.main!.frame.width + 10, height: 20)
containerView.addSubview(box)
window.contentView = containerView
window.setFrameOrigin(NSPoint(x: NSScreen.main!.frame.minX - 5, y: NSScreen.main!.frame.maxY - 12))
windowController.showWindow(nil)
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 1.0
window.animator().alphaValue = 0.5
}
fader?.cancel()
closer?.cancel()
guard hideAfter > 0 else { return }
fader = mainAsyncAfter(hideAfter) {
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 2.0
window.animator().alphaValue = 0.01
}
closer = mainAsyncAfter(2.0) {
window.alphaValue = 0.0
lastColor = nil
lastHideAfter = nil
}
}
}
}
private var lastColor: NSColor?
private var lastHideAfter: TimeInterval?
private var lastStatus: NWPath.Status?
NotificationCenter.default.addObserver(forName: NSApplication.didChangeScreenParametersNotification, object: nil, queue: nil) { n in
guard let color = lastColor, let hideAfter = lastHideAfter else {
return
}
drawColoredTopLine(color, hideAfter: hideAfter)
}
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
guard path.status != lastStatus else {
return
}
lastStatus = path.status
switch path.status {
case .satisfied:
print("Internet connection: ON")
drawColoredTopLine(.systemGreen, hideAfter: 5)
case .unsatisfied:
print("Internet connection: OFF")
drawColoredTopLine(.systemRed, hideAfter: 0)
case .requiresConnection:
print("Internet connection: MAYBE")
drawColoredTopLine(.systemOrange, hideAfter: 5)
@unknown default:
print("Internet connection: UNKNOWN")
drawColoredTopLine(.systemYellow, hideAfter: 5)
}
}
monitor.start(queue: DispatchQueue.global())
signal(SIGINT) { _ in
monitor.cancel()
exit(0)
}
RunLoop.main.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment