Skip to content

Commit

Permalink
Region menu refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
marcingajda committed Apr 1, 2020
1 parent e0bce8d commit 18d5b6b
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 66 deletions.
4 changes: 4 additions & 0 deletions Covid-19 Status.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
D30A829024345C9F0023B9C3 /* RegionsMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30A828F24345C9F0023B9C3 /* RegionsMenu.swift */; };
D30B91F02433373E00E21774 /* showError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30B91EF2433373E00E21774 /* showError.swift */; };
D3C1A3552427BF8900B69DCB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C1A3542427BF8900B69DCB /* AppDelegate.swift */; };
D3C1A3592427BF8B00B69DCB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D3C1A3582427BF8B00B69DCB /* Assets.xcassets */; };
Expand All @@ -22,6 +23,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
D30A828F24345C9F0023B9C3 /* RegionsMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegionsMenu.swift; sourceTree = "<group>"; };
D30B91EF2433373E00E21774 /* showError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = showError.swift; sourceTree = "<group>"; };
D3C1A3512427BF8900B69DCB /* Covid-19 Status.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Covid-19 Status.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D3C1A3542427BF8900B69DCB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -95,6 +97,7 @@
D3C1A3682429908300B69DCB /* StatsFormatter.swift */,
D3C1A36A2429921800B69DCB /* fetchData.swift */,
D3C1A36D2429942200B69DCB /* Notificator.swift */,
D30A828F24345C9F0023B9C3 /* RegionsMenu.swift */,
);
path = src;
sourceTree = "<group>";
Expand Down Expand Up @@ -194,6 +197,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D30A829024345C9F0023B9C3 /* RegionsMenu.swift in Sources */,
D3C1A36E2429942200B69DCB /* Notificator.swift in Sources */,
D3C1A3692429908300B69DCB /* StatsFormatter.swift in Sources */,
D3C1A36B2429921800B69DCB /* fetchData.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Covid-19 Status/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<menuItem isSeparatorItem="YES" title="sdfsdf" id="VOq-y0-SEH"/>
<menuItem title="Select region" id="MAg-rl-DVH">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Select region" systemMenu="apple" autoenablesItems="NO" id="URq-Fm-ggV">
<menu key="submenu" title="Select region" systemMenu="apple" autoenablesItems="NO" id="URq-Fm-ggV" customClass="RegionsMenu" customModule="Covid_19_Status" customModuleProvider="target">
<items>
<menuItem title="None" enabled="NO" id="i8c-sB-7Tp">
<modifierMask key="keyEquivalentModifierMask"/>
Expand Down Expand Up @@ -73,7 +73,7 @@
<outlet property="alertsMenuItem" destination="ljG-1J-Upa" id="6En-cd-cZ3"/>
<outlet property="deltaMenuItem" destination="5kV-Vb-QxS" id="WJ5-eC-Ydj"/>
<outlet property="menu" destination="uQy-DD-JDr" id="J7Q-go-iQk"/>
<outlet property="regionMenu" destination="URq-Fm-ggV" id="SeA-ks-eI3"/>
<outlet property="regionsMenu" destination="URq-Fm-ggV" id="SeA-ks-eI3"/>
<outlet property="retryMenuItem" destination="6jx-Ii-JOn" id="3vl-jR-B9e"/>
</connections>
</customObject>
Expand Down
87 changes: 23 additions & 64 deletions Covid-19 Status/src/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
var timer: Timer?

@IBOutlet weak var menu: NSMenu?
@IBOutlet weak var regionMenu: NSMenu?
@IBOutlet weak var regionsMenu: RegionsMenu?
@IBOutlet weak var retryMenuItem: NSMenuItem?
@IBOutlet weak var deltaMenuItem: NSMenuItem?
@IBOutlet weak var alertsMenuItem: NSMenuItem?

var currentRegion: String = WORLD
var alertsEnabled: Bool = false

func findRegionMenuItem(regionName: String) -> NSMenuItem? {
return regionMenu?.item(withTitle: NSLocalizedString(regionName, comment: ""))
}

func setCurrentRegion(newRegion: String) {
findRegionMenuItem(regionName: currentRegion)?.state = .off
findRegionMenuItem(regionName: newRegion)?.state = .on

currentRegion = newRegion
settings.set(newRegion, forKey: "country")
}

func setAlertsEnabled(enabled: Bool) {
alertsEnabled = enabled
notificator.isEnabled = enabled
Expand All @@ -63,38 +51,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}) ?? lastCoronaStats.worldStats
}

func sortCountries(data: [RegionStats]) -> [RegionStats] {
return data.sorted(by: {
let name1 = NSLocalizedString($0.country, comment: "")
let name2 = NSLocalizedString($1.country, comment: "")

return name1.localizedCompare(name2) == .orderedAscending
})
}

func updateRegionMenu(coronaStats: CoronaStats) {
self.regionMenu?.removeAllItems()

let worldItem = NSMenuItem()
worldItem.title = NSLocalizedString(WORLD, comment: "menu")
worldItem.action = #selector(self.changeRegionHandler(sender:))
worldItem.representedObject = WORLD
self.regionMenu?.addItem(worldItem)

self.regionMenu?.addItem(NSMenuItem.separator())

for countryStats in sortCountries(data: coronaStats.data) {
//print(countryStats.country)
let countryItem = NSMenuItem()
countryItem.title = NSLocalizedString(countryStats.country, comment: "menu")
countryItem.action = #selector(self.changeRegionHandler(sender:))
countryItem.representedObject = countryStats.country
self.regionMenu?.addItem(countryItem)
}

findRegionMenuItem(regionName: currentRegion)?.state = .on
}

func refreshView(stats: RegionStats) {
let formatter = StatsFormatter(stats: stats)

Expand All @@ -119,22 +75,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
setAlertsEnabled(enabled: !alertsEnabled)
}

@objc func changeRegionHandler(sender: NSMenuItem) {
guard let region = sender.representedObject as? String else {
showError(text: "Button returned not a string")
return
}

setCurrentRegion(newRegion: region)

guard let currentStats = self.getCurrentRegionStats() else {
print("No stats data available")
return
}

refreshView(stats: currentStats)
}

func showErrorState(message: String) {
DispatchQueue.main.async {
guard let deltaMenuItem = self.deltaMenuItem else {
Expand Down Expand Up @@ -166,9 +106,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return
}

if self.regionMenu?.items.count != coronaStats.data.count + 2 {
if self.regionsMenu?.items.count != coronaStats.data.count + 2 {
print("Updating region menu")
self.updateRegionMenu(coronaStats: coronaStats)
self.regionsMenu?.updateList(regionsStats: coronaStats.data)
}

self.retryMenuItem?.isHidden = true
Expand Down Expand Up @@ -206,10 +146,29 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return
}

guard let regionsMenu = regionsMenu else {
showError(text: "The app UI is broken (regions menu)")
NSApp.terminate(nil)
return
}

button = statusBarItem.button
statusBarItem.menu = menu

setCurrentRegion(newRegion: settings.string(forKey: "country") ?? WORLD)
regionsMenu.onRegionChange { region in
self.currentRegion = region

guard let stats = self.getCurrentRegionStats() else {
return
}

self.refreshView(stats: stats)
}

regionsMenu.setCurrent(
region: settings.string(forKey: "country") ?? WORLD
)

setAlertsEnabled(enabled: settings.bool(forKey: "alerts"))

doUpdate()
Expand Down
93 changes: 93 additions & 0 deletions Covid-19 Status/src/RegionsMenu.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// RegionsMenu.swift
// Covid-19 Status
//
// Created by Marcin Gajda on 01/04/2020.
// Copyright © 2020 Marcin Gajda. All rights reserved.
//

import Cocoa

class RegionsMenu: NSMenu {
var regions: [String] = []
var currentRegion: String = WORLD
let settings = UserDefaults.standard
var regionChangeCallback: ((String) -> Void)?

func onRegionChange(callback: @escaping (String) -> Void) {
regionChangeCallback = callback
}

func setCurrent(region: String) {
print("Changing region:", region)

findItem(name: currentRegion)?.state = .off
findItem(name: region)?.state = .on

currentRegion = region
settings.set(region, forKey: "country")
regionChangeCallback?(region)
}

func sortRegionsStats(data: [RegionStats]) -> [RegionStats] {
return data.sorted(by: {
let name1 = NSLocalizedString($0.country, comment: "")
let name2 = NSLocalizedString($1.country, comment: "")

return name1.localizedCompare(name2) == .orderedAscending
})
}

func updateList(regionsStats: [RegionStats]) {
regions.removeAll()

for region in sortRegionsStats(data: regionsStats) {
regions.append(region.country)
}

rebuildMenu()
}

@objc func changeRegionHandler(sender: NSMenuItem) {
guard let region = sender.representedObject as? String else {
showError(text: "Button returned not a string")
return
}

setCurrent(region: region)
}

func findItem(name: String) -> NSMenuItem? {
return item(withTitle: NSLocalizedString(name, comment: ""))
}

func rebuildMenu() {
self.removeAllItems()

let worldItem = NSMenuItem()
worldItem.title = NSLocalizedString(WORLD, comment: "menu")
worldItem.action = #selector(changeRegionHandler(sender:))
worldItem.target = self
worldItem.representedObject = WORLD
self.addItem(worldItem)

addItem(NSMenuItem.separator())

for region in regions {
let regionItem = NSMenuItem()
regionItem.title = NSLocalizedString(region, comment: "menu")
regionItem.action = #selector(changeRegionHandler(sender:))
regionItem.target = self
regionItem.representedObject = region
addItem(regionItem)

#if DEBUG
if Locale.current.languageCode != "en" && NSLocalizedString(region, comment: "menu") == region {
print("MISSING TRANS?", regionItem.title)
}
#endif
}

findItem(name: currentRegion)?.state = .on
}
}

0 comments on commit 18d5b6b

Please sign in to comment.