Skip to content

Commit

Permalink
Merge pull request #335 from roop/redesign_fixes_2
Browse files Browse the repository at this point in the history
More fixes to the redesigned macOS app
  • Loading branch information
roop authored Sep 14, 2020
2 parents efd43f9 + 73cf6b3 commit 3ddf675
Show file tree
Hide file tree
Showing 69 changed files with 704 additions and 73 deletions.
55 changes: 55 additions & 0 deletions EduVPN-redesign/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@ import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

var mainWindow: NSWindow?
var environment: Environment?
var statusItemController: StatusItemController?

func applicationWillFinishLaunching(_ notification: Notification) {
if UserDefaults.standard.showInDock {
NSApp.setActivationPolicy(.regular)
} else {
NSApp.setActivationPolicy(.accessory)
}
}

func applicationDidFinishLaunching(_ aNotification: Notification) {
let window = NSApp.windows[0]
Expand All @@ -44,7 +54,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

Self.replaceAppNameInMenuItems(in: NSApp.mainMenu)

self.statusItemController = StatusItemController()

setShowInStatusBarEnabled(UserDefaults.standard.showInStatusBar)
setShowInDockEnabled(UserDefaults.standard.showInDock)

NSApp.activate(ignoringOtherApps: true)
self.mainWindow = window
}

private static func replaceAppNameInMenuItems(in menu: NSMenu?) {
Expand Down Expand Up @@ -97,10 +114,24 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return !UserDefaults.standard.showInStatusBar
}

func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
setShowInDockEnabled(UserDefaults.standard.showInDock)
return true
}
}

extension AppDelegate {
@objc func showMainWindow(_ sender: Any?) {
mainWindow?.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
}

@objc func showPreferences(_ sender: Any) {
mainWindow?.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
environment?.navigationController?.presentPreferences()
}

Expand All @@ -112,6 +143,30 @@ class AppDelegate: NSObject, NSApplicationDelegate {
navigationController.toolbarLeftButtonClicked(self)
}
}

func setShowInStatusBarEnabled(_ isEnabled: Bool) {
statusItemController?.setShouldShowStatusItem(isEnabled)
}

func setShowInDockEnabled(_ isEnabled: Bool) {
if isEnabled {
if NSApp.activationPolicy() != .regular {
NSApp.setActivationPolicy(.regular)
}
} else {
if NSApp.activationPolicy() != .accessory {
NSApp.setActivationPolicy(.accessory)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
NSApp.unhide(nil)
NSApp.activate(ignoringOtherApps: true)
}
}
}
}

func setLaunchAtLoginEnabled(_ isEnabled: Bool) {
LaunchAtLoginHelper.setLaunchAtLoginEnabled(isEnabled)
}
}

extension AppDelegate: NSMenuItemValidation {
Expand Down
11 changes: 8 additions & 3 deletions EduVPN-redesign/Controllers/ConnectionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ final class ConnectionViewController: ViewController, ParametrizedViewController
private var profiles: [ProfileListResponse.Profile]?
private var selectedProfileId: String? {
didSet {
dataStore.selectedProfileId = selectedProfileId ?? ""
dataStore.setSelectedProfileId(
profileId: selectedProfileId,
for: parameters.server.apiBaseURLString)
}
}

Expand All @@ -76,7 +78,7 @@ final class ConnectionViewController: ViewController, ParametrizedViewController
@IBOutlet weak var renewSessionButton: NSButton!
@IBOutlet weak var spinner: NSProgressIndicator!

@IBOutlet weak var connectionInfoHeader: NSView!
@IBOutlet weak var connectionInfoHeader: ConnectionInfoHeaderView!
@IBOutlet weak var connectionInfoChevronButton: NSButton!

@IBOutlet weak var connectionInfoBody: NSView!
Expand Down Expand Up @@ -111,7 +113,7 @@ final class ConnectionViewController: ViewController, ParametrizedViewController
self.selectedProfileId = restoredPreConnectionState.selectedProfileId
self.isRestored = true
} else {
self.selectedProfileId = dataStore.selectedProfileId
self.selectedProfileId = dataStore.selectedProfileId(for: parameters.server.apiBaseURLString)
self.isRestored = false
}
}
Expand Down Expand Up @@ -393,20 +395,23 @@ extension ConnectionViewController: ConnectionViewModelDelegate {
bodyAlpha = 0
bodyHeight = 0
connectionInfoChevronButton.image = Image(named: "ChevronDownButton")
connectionInfoHeader.isPassthroughToButtonEnabled = false
case .collapsed:
controlAlpha = 1
controlHeight = Self.additionalControlContainerHeight
isHeaderHidden = false
bodyAlpha = 0
bodyHeight = 0
connectionInfoChevronButton.image = Image(named: "ChevronDownButton")
connectionInfoHeader.isPassthroughToButtonEnabled = true // Make whole "row" clickable
case .expanded(let connectionInfo):
controlAlpha = 0
controlHeight = 0
isHeaderHidden = false
bodyAlpha = 1
bodyHeight = Self.connectionInfoBodyHeight
connectionInfoChevronButton.image = Image(named: "CloseButton")
connectionInfoHeader.isPassthroughToButtonEnabled = false
durationLabel.stringValue = connectionInfo.duration
if let profileName = connectionInfo.profileName {
profileTitleLabel.isHidden = false
Expand Down
15 changes: 15 additions & 0 deletions EduVPN-redesign/Controllers/MainWindowController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// MainWindowController.swift
// EduVPN
//

// The window controller is used to enable frame auto saving

import AppKit

class MainWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
self.windowFrameAutosaveName = "Main"
}
}
115 changes: 113 additions & 2 deletions EduVPN-redesign/Controllers/PreferencesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,133 @@
//

import Foundation
import PromiseKit

class PreferencesViewController: ViewController {
enum PreferencesViewControllerError: Error {
case noLogAvailable
case cannotShowLog
}

extension PreferencesViewControllerError: AppError {
var summary: String {
switch self {
case .noLogAvailable: return NSLocalizedString("No log available", comment: "")
case .cannotShowLog: return NSLocalizedString("Unable to show log", comment: "")
}
}
}

class PreferencesViewController: ViewController, ParametrizedViewController {

struct Parameters {
let environment: Environment
}

private var parameters: Parameters!

@IBOutlet weak var useTCPOnlyCheckbox: NSButton!
@IBOutlet weak var showInStatusBarCheckbox: NSButton!
@IBOutlet weak var showInDockCheckbox: NSButton!
@IBOutlet weak var launchAtLoginCheckbox: NSButton!

func initializeParameters(_ parameters: Parameters) {
guard self.parameters == nil else {
fatalError("Can't initialize parameters twice")
}
self.parameters = parameters
}

override func viewDidLoad() {
let isForceTCPEnabled = UserDefaults.standard.forceTCP
let userDefaults = UserDefaults.standard
let isForceTCPEnabled = userDefaults.forceTCP
let isShowInStatusBarEnabled = userDefaults.showInStatusBar
let isShowInDockEnabled = userDefaults.showInDock
let isLaunchAtLoginEnabled = userDefaults.launchAtLogin

useTCPOnlyCheckbox.state = isForceTCPEnabled ? .on : .off
showInStatusBarCheckbox.state = isShowInStatusBarEnabled ? .on : .off
showInDockCheckbox.state = isShowInDockEnabled ? .on : .off
launchAtLoginCheckbox.state = isLaunchAtLoginEnabled ? .on : .off

// If one of "Show in status bar" or "Show in Dock" is off,
// disable editing the other
if !isShowInStatusBarEnabled {
showInDockCheckbox.isEnabled = false
}
if !isShowInDockEnabled {
showInStatusBarCheckbox.isEnabled = false
}
}

@IBAction func useTCPOnlyCheckboxClicked(_ sender: Any) {
let isUseTCPOnlyChecked = (useTCPOnlyCheckbox.state == .on)
UserDefaults.standard.forceTCP = isUseTCPOnlyChecked
}

@IBAction func viewLogClicked(_ sender: Any) {
let connectionService = parameters.environment.connectionService
guard connectionService.isInitialized else { return }
firstly {
connectionService.getConnectionLog()
}.map { log in
try self.showLog(log)
}.catch { error in
self.parameters.environment.navigationController?.showAlert(for: error)
}
}

@IBAction func doneClicked(_ sender: Any) {
self.presentingViewController?.dismiss(self)
}
}

#if os(macOS)
private extension PreferencesViewController {
@IBAction func showInStatusBarCheckboxClicked(_ sender: Any) {
guard let appDelegate = NSApp.delegate as? AppDelegate else { return }
let isChecked = (showInStatusBarCheckbox.state == .on)

// If "Show in status bar" is unchecked, disable changing "Show in dock"
showInDockCheckbox.isEnabled = isChecked

appDelegate.setShowInStatusBarEnabled(isChecked)
UserDefaults.standard.showInStatusBar = isChecked
}

@IBAction func showInDockCheckboxClicked(_ sender: Any) {
guard let appDelegate = NSApp.delegate as? AppDelegate else { return }
let isChecked = (showInDockCheckbox.state == .on)

// If "Show in dock" is unchecked, disable changing "Show in status bar"
showInStatusBarCheckbox.isEnabled = isChecked

appDelegate.setShowInDockEnabled(isChecked)
UserDefaults.standard.showInDock = isChecked
}

@IBAction func launchAtLoginCheckboxClicked(_ sender: Any) {
guard let appDelegate = NSApp.delegate as? AppDelegate else { return }
let isChecked = (launchAtLoginCheckbox.state == .on)

appDelegate.setLaunchAtLoginEnabled(isChecked)
UserDefaults.standard.launchAtLogin = isChecked
}
}

private extension PreferencesViewController {
private func showLog(_ log: String?) throws {
let fileManager = FileManager.default
guard let documentDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
throw PreferencesViewControllerError.cannotShowLog
}
guard let data = log?.data(using: .utf8) else {
throw PreferencesViewControllerError.noLogAvailable
}
let tmpDir = documentDir.appendingPathComponent("tmp")
let logPath = tmpDir.appendingPathComponent("connection.log")
try FileManager.default.createDirectory(at: tmpDir, withIntermediateDirectories: true)
try data.write(to: logPath, options: [.atomic])
NSWorkspace.shared.open(logPath)
}
}
#endif
Loading

0 comments on commit 3ddf675

Please sign in to comment.