Skip to content

Commit

Permalink
Add modern WiFi icons
Browse files Browse the repository at this point in the history
Closes #207, #251
Thanks @Zyvoxi for the fade transition animation
  • Loading branch information
williambj1 committed Aug 1, 2024
1 parent 43fcdad commit c5e2264
Show file tree
Hide file tree
Showing 71 changed files with 819 additions and 146 deletions.
24 changes: 20 additions & 4 deletions HeliPort.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
13AB3CA824DE47D10093D283 /* WiFiConfigWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13AB3CA724DE47D10093D283 /* WiFiConfigWindow.swift */; };
13AF73B624B25E170015867C /* StatusMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCA4DFAC243A307B002A862A /* StatusMenu.swift */; };
13C20DFA24D8B6D100B1E713 /* PrefsGeneralView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C20DF924D8B6D100B1E713 /* PrefsGeneralView.swift */; };
505EC11D2C5BD89400F4E4EA /* StatusBarIconManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505EC11C2C5BD89400F4E4EA /* StatusBarIconManager.swift */; };
505EC11F2C5BD8ED00F4E4EA /* StatusBarIconLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505EC11E2C5BD8ED00F4E4EA /* StatusBarIconLegacy.swift */; };
505EC1212C5BD95700F4E4EA /* StatusBarIconModern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505EC1202C5BD95700F4E4EA /* StatusBarIconModern.swift */; };
5088F70826BEA46F009E3A15 /* KextInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5088F70726BEA46F009E3A15 /* KextInfo.swift */; };
50B86ABA24B22E9B008E4FE4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 50B86AB824B22E9B008E4FE4 /* Localizable.strings */; };
50C5F2D027C23074009E3F68 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 50C5F2CF27C23074009E3F68 /* KeychainAccess */; };
Expand All @@ -28,7 +31,6 @@
75FDF38B2481D22000B2A601 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75FDF38A2481D22000B2A601 /* NetworkManager.swift */; };
75FDF38C2481D25A00B2A601 /* Api.c in Sources */ = {isa = PBXBuildFile; fileRef = F8F6CF0B243D675800965B43 /* Api.c */; };
BCCB2AA4243708090005BB82 /* WiFiMenuItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCCB2AA3243708090005BB82 /* WiFiMenuItemView.swift */; };
BCF712F9243C8BE800BE3C05 /* StatusBarIconManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCF712F8243C8BE800BE3C05 /* StatusBarIconManager.swift */; };
BCFA32EB2424D2BE00E23603 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCFA32EA2424D2BE00E23603 /* AppDelegate.swift */; };
BCFA32ED2424D2BF00E23603 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BCFA32EC2424D2BF00E23603 /* Assets.xcassets */; };
BCFA32F02424D2BF00E23603 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCFA32EE2424D2BF00E23603 /* MainMenu.xib */; };
Expand Down Expand Up @@ -70,6 +72,9 @@
2181E9B524C24FF600E3C73D /* cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
2A66531D24B6E172002F88EE /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
42979EFF24B3A27200F15FBD /* el */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = el; path = el.lproj/Localizable.strings; sourceTree = "<group>"; };
505EC11C2C5BD89400F4E4EA /* StatusBarIconManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarIconManager.swift; sourceTree = "<group>"; };
505EC11E2C5BD8ED00F4E4EA /* StatusBarIconLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarIconLegacy.swift; sourceTree = "<group>"; };
505EC1202C5BD95700F4E4EA /* StatusBarIconModern.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarIconModern.swift; sourceTree = "<group>"; };
5088F70726BEA46F009E3A15 /* KextInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KextInfo.swift; sourceTree = "<group>"; };
50B86AB924B22E9B008E4FE4 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
50B86ABC24B22F75008E4FE4 /* zh-Hans */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
Expand All @@ -90,7 +95,6 @@
A6B1F45424B9C60A00EBBE79 /* vi */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
BCA4DFAC243A307B002A862A /* StatusMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusMenu.swift; sourceTree = "<group>"; };
BCCB2AA3243708090005BB82 /* WiFiMenuItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WiFiMenuItemView.swift; sourceTree = "<group>"; wrapsLines = 0; };
BCF712F8243C8BE800BE3C05 /* StatusBarIconManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarIconManager.swift; sourceTree = "<group>"; };
BCFA32E72424D2BE00E23603 /* HeliPort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HeliPort.app; sourceTree = BUILT_PRODUCTS_DIR; };
BCFA32EA2424D2BE00E23603 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
BCFA32EC2424D2BF00E23603 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -145,6 +149,16 @@
path = Preferences;
sourceTree = "<group>";
};
505EC11B2C5BD85300F4E4EA /* StatusBarIcon */ = {
isa = PBXGroup;
children = (
505EC11C2C5BD89400F4E4EA /* StatusBarIconManager.swift */,
505EC11E2C5BD8ED00F4E4EA /* StatusBarIconLegacy.swift */,
505EC1202C5BD95700F4E4EA /* StatusBarIconModern.swift */,
);
path = StatusBarIcon;
sourceTree = "<group>";
};
50F4959E24BDEB6500AE4C08 /* HeliPort Launcher */ = {
isa = PBXGroup;
children = (
Expand All @@ -158,9 +172,9 @@
BCF712FA243C9EB100BE3C05 /* Appearance */ = {
isa = PBXGroup;
children = (
505EC11B2C5BD85300F4E4EA /* StatusBarIcon */,
50B86AB824B22E9B008E4FE4 /* Localizable.strings */,
BCFA32EE2424D2BF00E23603 /* MainMenu.xib */,
BCF712F8243C8BE800BE3C05 /* StatusBarIconManager.swift */,
BCA4DFAC243A307B002A862A /* StatusMenu.swift */,
BCCB2AA3243708090005BB82 /* WiFiMenuItemView.swift */,
13AB3CA724DE47D10093D283 /* WiFiConfigWindow.swift */,
Expand Down Expand Up @@ -400,12 +414,13 @@
F336D63C24B497B6004C98C4 /* NetworkManager+Data.swift in Sources */,
F33A1F3F24C8347F008ED2BD /* NSLocalizedString+Extensions.swift in Sources */,
F379277124A0A52E0087FF2B /* Log.swift in Sources */,
505EC11F2C5BD8ED00F4E4EA /* StatusBarIconLegacy.swift in Sources */,
F336D63E24B4986C004C98C4 /* itl_phy_mode+Description.swift in Sources */,
BCF712F9243C8BE800BE3C05 /* StatusBarIconManager.swift in Sources */,
F336D64024B7B7D8004C98C4 /* itl80211_security+Description.swift in Sources */,
F3915F0724AB1A1B00E6614D /* itl_80211_state+Extensions.swift in Sources */,
5088F70826BEA46F009E3A15 /* KextInfo.swift in Sources */,
F33A1F3B24C83016008ED2BD /* Alert.swift in Sources */,
505EC1212C5BD95700F4E4EA /* StatusBarIconModern.swift in Sources */,
BCFA32EB2424D2BE00E23603 /* AppDelegate.swift in Sources */,
BCCB2AA4243708090005BB82 /* WiFiMenuItemView.swift in Sources */,
1380C36124D54BFD00A448CF /* PrefsSavedNetworksView.swift in Sources */,
Expand All @@ -415,6 +430,7 @@
138D3CC824CE635800793AC1 /* Commands.swift in Sources */,
13C20DFA24D8B6D100B1E713 /* PrefsGeneralView.swift in Sources */,
13AB3CA824DE47D10093D283 /* WiFiConfigWindow.swift in Sources */,
505EC11D2C5BD89400F4E4EA /* StatusBarIconManager.swift in Sources */,
1380C36524D5580200A448CF /* PrefsWindow.swift in Sources */,
50F4959824BDD26D00AE4C08 /* LoginItemManager.swift in Sources */,
F34B2B8D24AA4C1E009AB1BB /* NSMenuItem+Extensions.swift in Sources */,
Expand Down
13 changes: 9 additions & 4 deletions HeliPort/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
checkAPI()

let statusBar = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusBar.button?.image = #imageLiteral(resourceName: "WiFiStateOff")
statusBar.button?.image?.isTemplate = true
statusBar.menu = StatusMenu()

StatusBarIcon.statusBar = statusBar
let iconProvider: StatusBarIconProvider = {
if #available(macOS 11, *) {
return StatusBarIconModern()
}
return StatusBarIconLegacy()
}()
_ = StatusBarIcon.shared(statusBar: statusBar, icons: iconProvider)

statusBar.menu = StatusMenu()
}

private var drv_info = ioctl_driver_info()
Expand Down
41 changes: 41 additions & 0 deletions HeliPort/Appearance/StatusBarIcon/StatusBarIconLegacy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// StatusBarIconLegacy.swift
// HeliPort
//
// Created by Bat.bat on 25/6/2024.
// Copyright © 2020 OpenIntelWireless. All rights reserved.
//

/*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the The 3-Clause BSD License
* which accompanies this distribution. The full text of the license may be found at
* https://opensource.org/licenses/BSD-3-Clause
*/

import Cocoa

class StatusBarIconLegacy: StatusBarIconProvider {
var transition: CATransition? { return nil }
var off: NSImage { return #imageLiteral(resourceName: "LegacyStateOff") }
var connected: NSImage { return #imageLiteral(resourceName: "LegacyStateOn") }
var disconnected: NSImage { return #imageLiteral(resourceName: "LegacyStateDisconnected") }
var warning: NSImage { return #imageLiteral(resourceName: "LegacyStateWarning") }
var scanning: [NSImage] {
return [
#imageLiteral(resourceName: "LegacyStateScanning1"),
#imageLiteral(resourceName: "LegacyStateScanning2"),
#imageLiteral(resourceName: "LegacyStateScanning3"),
#imageLiteral(resourceName: "LegacyStateScanning4")
]
}

func getRssiImage(_ RSSI: Int16) -> NSImage? {
switch RSSI {
case ..<(-100): return #imageLiteral(resourceName: "LegacySignalStrengthPoor")
case ..<(-80): return #imageLiteral(resourceName: "LegacySignalStrengthFair")
case ..<(-60): return #imageLiteral(resourceName: "LegacySignalStrengthGood")
default: return #imageLiteral(resourceName: "LegacySignalStrengthExcellent")
}
}
}
128 changes: 128 additions & 0 deletions HeliPort/Appearance/StatusBarIcon/StatusBarIconManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// StatusBarIconManager.swift
// HeliPort
//
// Created by 梁怀宇 on 2020/4/7.
// Copyright © 2020 OpenIntelWireless. All rights reserved.
//

/*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the The 3-Clause BSD License
* which accompanies this distribution. The full text of the license may be found at
* https://opensource.org/licenses/BSD-3-Clause
*/

import Cocoa

protocol StatusBarIconProvider {
var transition: CATransition? { get }
var off: NSImage { get }
var connected: NSImage { get }
var disconnected: NSImage { get }
var warning: NSImage { get }
var scanning: [NSImage] { get }
func getRssiImage(_ RSSI: Int16) -> NSImage?
}

class StatusBarIcon {
private static var instance: StatusBarIcon?

private let statusBar: NSStatusItem
private let icons: StatusBarIconProvider
private var timer: Timer?
private var tickIndex: Int = 0
private var tickDirection: Int = 1

private init(_ statusBar: NSStatusItem, _ icons: StatusBarIconProvider) {
self.statusBar = statusBar
self.icons = icons
}

static func shared(statusBar: NSStatusItem? = nil, icons: StatusBarIconProvider? = nil) -> StatusBarIcon {
if let instance {
return instance
}
guard let statusBar, let icons else {
fatalError("Must provide statusBar and iconProvider for the first initialization.")
}
instance = StatusBarIcon(statusBar, icons)
return instance!
}

func on() {
stopTimer()
disconnected()
}

func off() {
stopTimer()
statusBar.button?.image = icons.off
}

func connected() {
stopTimer()
statusBar.button?.image = icons.connected
}

func disconnected() {
stopTimer()
statusBar.button?.image = icons.disconnected
}

func connecting() {
guard timer == nil else { return }
tickIndex = 0
tickDirection = 1
DispatchQueue.global(qos: .default).async {
self.timer = Timer.scheduledTimer(
timeInterval: 0.3,
target: self,
selector: #selector(self.tick),
userInfo: nil,
repeats: true
)
self.timer?.fire()
RunLoop.current.add(self.timer!, forMode: .common)
RunLoop.current.run()
}
}

func warning() {
stopTimer()
statusBar.button?.image = icons.warning
}

func error() {
stopTimer()
statusBar.button?.image = #imageLiteral(resourceName: "WiFiStateError")
}

func signalStrength(rssi: Int16) {
stopTimer()
statusBar.button?.image = icons.getRssiImage(rssi)
}

func getRssiImage(rssi: Int16) -> NSImage? {
return icons.getRssiImage(rssi)
}

@objc private func tick() {
DispatchQueue.main.async {
if let transition = self.icons.transition {
self.statusBar.button?.layer?.add(transition, forKey: kCATransition)
}
self.statusBar.button?.image = self.icons.scanning[self.tickIndex]

self.tickIndex += self.tickDirection
if self.tickIndex == 0 || self.tickIndex == self.icons.scanning.endIndex - 1 {
self.tickDirection *= -1
}
}
}

private func stopTimer() {
timer?.invalidate()
timer = nil
}
}
44 changes: 44 additions & 0 deletions HeliPort/Appearance/StatusBarIcon/StatusBarIconModern.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// StatusBarIconModern.swift
// HeliPort
//
// Created by Bat.bat on 25/6/2024.
// Copyright © 2024 OpenIntelWireless. All rights reserved.
//

/*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the The 3-Clause BSD License
* which accompanies this distribution. The full text of the license may be found at
* https://opensource.org/licenses/BSD-3-Clause
*/

import Cocoa

class StatusBarIconModern: StatusBarIconProvider {
var transition: CATransition? {
let transition = CATransition()
transition.type = .fade
transition.duration = 0.2
return transition
}
var off: NSImage { return #imageLiteral(resourceName: "ModernStateOff") }
var connected: NSImage { return #imageLiteral(resourceName: "ModernStateOn") }
var disconnected: NSImage { return #imageLiteral(resourceName: "ModernStateDisconnected") }
var warning: NSImage { return #imageLiteral(resourceName: "ModernStateWarning") }
var scanning: [NSImage] {
return [
#imageLiteral(resourceName: "ModernStateScanning1"),
#imageLiteral(resourceName: "ModernStateScanning2"),
#imageLiteral(resourceName: "ModernStateScanning3")
]
}

func getRssiImage(_ RSSI: Int16) -> NSImage? {
switch RSSI {
case ..<(-90): return #imageLiteral(resourceName: "ModernSignalStrengthPoor")
case ..<(-70): return #imageLiteral(resourceName: "ModernSignalStrengthFair")
default: return #imageLiteral(resourceName: "ModernSignalStrengthGood")
}
}
}
Loading

0 comments on commit c5e2264

Please sign in to comment.