mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 20:10:08 +02:00
192 lines
5.5 KiB
Swift
192 lines
5.5 KiB
Swift
//
|
|
// SiteListVC.swift
|
|
// PHP Monitor
|
|
//
|
|
// Created by Nico Verbruggen on 30/03/2021.
|
|
// Copyright © 2021 Nico Verbruggen. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
import HotKey
|
|
import Carbon
|
|
|
|
class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|
|
|
// MARK: - Outlets
|
|
|
|
@IBOutlet weak var tableView: NSTableView!
|
|
@IBOutlet weak var progressIndicator: NSProgressIndicator!
|
|
|
|
// MARK: - Variables
|
|
|
|
/// List of sites that will be displayed in this view. Originates from the `Valet` object.
|
|
var sites: [Valet.Site] = []
|
|
|
|
/// Array that contains various apps that might open a particular site directory.
|
|
var applications: [Application] {
|
|
return App.shared.detectedApplications
|
|
}
|
|
|
|
/// String that was last searched for. Empty by default.
|
|
var lastSearchedFor = ""
|
|
|
|
// MARK: - Helper Variables
|
|
|
|
var selectedSite: Valet.Site? {
|
|
if tableView.selectedRow == -1 {
|
|
return nil
|
|
}
|
|
return sites[tableView.selectedRow]
|
|
}
|
|
|
|
// MARK: - Display
|
|
|
|
public static func create(delegate: NSWindowDelegate?) {
|
|
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
|
|
|
|
let windowController = storyboard.instantiateController(
|
|
withIdentifier: "siteListWindow"
|
|
) as! SiteListWC
|
|
|
|
windowController.window!.title = "site_list.title".localized
|
|
windowController.window!.subtitle = "site_list.subtitle".localized
|
|
windowController.window!.delegate = delegate
|
|
windowController.window!.styleMask = [
|
|
.titled, .closable, .resizable, .miniaturizable
|
|
]
|
|
windowController.window!.minSize = NSSize(width: 550, height: 200)
|
|
windowController.window!.delegate = windowController
|
|
windowController.positionWindowInTopLeftCorner()
|
|
|
|
App.shared.siteListWindowController = windowController
|
|
}
|
|
|
|
public static func show(delegate: NSWindowDelegate? = nil) {
|
|
if (App.shared.siteListWindowController == nil) {
|
|
Self.create(delegate: delegate)
|
|
}
|
|
|
|
App.shared.siteListWindowController!.showWindow(self)
|
|
NSApp.activate(ignoringOtherApps: true)
|
|
}
|
|
|
|
// MARK: - Lifecycle
|
|
|
|
override func viewDidLoad() {
|
|
tableView.doubleAction = #selector(self.doubleClicked(sender:))
|
|
if !Valet.shared.sites.isEmpty {
|
|
// Preloaded list
|
|
sites = Valet.shared.sites
|
|
searchedFor(text: lastSearchedFor)
|
|
} else {
|
|
reloadSites()
|
|
}
|
|
}
|
|
|
|
// MARK: - Async Operations
|
|
|
|
/**
|
|
Disables the UI so the user cannot interact with it.
|
|
Also shows a spinner to indicate that we're busy.
|
|
*/
|
|
private func setUIBusy() {
|
|
progressIndicator.startAnimation(nil)
|
|
tableView.alphaValue = 0.3
|
|
tableView.isEnabled = false
|
|
}
|
|
|
|
/**
|
|
Re-enables the UI so the user can interact with it.
|
|
*/
|
|
private func setUINotBusy() {
|
|
progressIndicator.stopAnimation(nil)
|
|
tableView.alphaValue = 1.0
|
|
tableView.isEnabled = true
|
|
}
|
|
|
|
/**
|
|
Executes a specific callback and fires the completion callback,
|
|
while updating the UI as required. As long as the completion callback
|
|
does not fire, the app is presumed to be busy and the UI reflects this.
|
|
|
|
- Parameter execute: Callback of the work that needs to happen.
|
|
- Parameter completion: Callback that is fired when the work is done.
|
|
*/
|
|
internal func waitAndExecute(_ execute: @escaping () -> Void, completion: @escaping () -> Void = {})
|
|
{
|
|
setUIBusy()
|
|
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
|
execute()
|
|
DispatchQueue.main.async { [self] in
|
|
completion()
|
|
setUINotBusy()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Site Data Loading
|
|
|
|
func reloadSites() {
|
|
waitAndExecute {
|
|
Valet.shared.reloadSites()
|
|
} completion: { [self] in
|
|
sites = Valet.shared.sites
|
|
searchedFor(text: lastSearchedFor)
|
|
}
|
|
}
|
|
|
|
// MARK: - Table View Delegate
|
|
|
|
func numberOfRows(in tableView: NSTableView) -> Int {
|
|
return sites.count
|
|
}
|
|
|
|
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
|
guard let userCell = tableView.makeView(
|
|
withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "siteItem"), owner: self
|
|
) as? SiteListCell else { return nil }
|
|
|
|
userCell.populateCell(with: sites[row])
|
|
|
|
return userCell
|
|
}
|
|
|
|
func tableViewSelectionDidChange(_ notification: Notification) {
|
|
reloadContextMenu()
|
|
}
|
|
|
|
@objc func doubleClicked(sender: Any) {
|
|
guard self.selectedSite != nil else {
|
|
return
|
|
}
|
|
|
|
self.openInBrowser()
|
|
}
|
|
|
|
// MARK: - (Search) Text Field Delegate
|
|
|
|
func searchedFor(text: String) {
|
|
lastSearchedFor = text
|
|
|
|
let searchString = text.lowercased()
|
|
|
|
if searchString.isEmpty {
|
|
sites = Valet.shared.sites
|
|
tableView.reloadData()
|
|
return
|
|
}
|
|
|
|
sites = Valet.shared.sites.filter({ site in
|
|
return site.name.lowercased().contains(searchString)
|
|
})
|
|
|
|
tableView.reloadData()
|
|
}
|
|
|
|
// MARK: - Deinitialization
|
|
|
|
deinit {
|
|
print("VC deallocated")
|
|
}
|
|
}
|