Skip to content

Instantly share code, notes, and snippets.

@jhoughjr
Created November 30, 2019 22:39
Show Gist options
  • Save jhoughjr/26234618d8e547f3d7351e3fe972840e to your computer and use it in GitHub Desktop.
Save jhoughjr/26234618d8e547f3d7351e3fe972840e to your computer and use it in GitHub Desktop.
//
// ViewController.swift
// Ghostnote2
//
// Created by Jimmy Hough Jr on 11/14/17.
// Copyright © 2017 Jimmy Hough Jr. All rights reserved.
//
class Menus {
static func themeMenu() -> NSMenu {
let m = NSMenu()
GNTheme.allThemes().forEach { (t) in
m.addItem(t.menuItem())
}
m.showsStateColumn = false
return m
}
}
import AppKit
import WebKit
import FileKit
import SwiftyBeaver
class ContextViewController: NSViewController,
NSURLConnectionDelegate,
GhostEngineClientObserver,
NSMenuDelegate {
@IBOutlet var settingsMenu:NSMenu!
@IBOutlet var themeMenuItem:NSMenuItem!
@IBOutlet var dockMenuItems:NSMenuItem!
let log = SwiftyBeaver.self
var editor:GhostNoteEditor? = nil
var currentType:NoteType = .app {
didSet {
editor?.currentType = currentType
applyTheme()
updateUI()
}
}
var currentContext:GhostContext? = nil
@IBOutlet weak var titleView:GNTitleView?
@IBOutlet weak var settingsButton:FingerButton? {
didSet {
if let b = settingsButton {
b.addCursorRect(b.frame,
cursor: .pointingHand)
}
}
}
@IBOutlet var windowPassView: WindowPassView?
@IBOutlet weak var textView: WKWebView? {
didSet {
textView?.layer?.backgroundColor = .black
}
}
@objc func handleExternalChange(notif:Notification) {
if let d = notif.object as? [String:Any],
let c = d["context"] as? GhostContext,
let t = d["type"] as? NoteType {
if c.docResult.identifier == editor?.currentEditContext?.docResult.identifier {
loadNoteFor(context: c,
of: t)
}
}
}
@objc func enterAppMode() {
currentType = .app
}
@objc func enterDocMode() {
currentType = .document
}
func buttons() -> [NSButton?] {
return [settingsButton]
}
func contextChanged(to: GhostContext) {
func update() {
if GhostEngineClient.shared.docModeAvailable {
if currentType != .document {
enterDocMode()
}
}else {
if currentType != .app {
enterAppMode()
}
}
lockoutDocModeIfNeeded()
DispatchQueue.main.async {
self.loadNoteFor(context: to,
of: self.currentType)
self.updateUI()
}
}
if let w = view.window as? GhostNoteWindow {
if w.attached {
if let c = currentContext {
if to.appResult.identifier != c.appResult.identifier {
NotificationCenter.default.post(name: GNN.Shortcuts.hide,
object: nil)
}
}
}
}
if let current = currentContext {
if current.appResult.identifier == to.appResult.identifier {
// SwiftyBeaver.debug("SAME APP")
}else {
// SwiftyBeaver.debug("DIFF APP")
update()
}
if current.docResult.identifier == to.docResult.identifier {
// SwiftyBeaver.debug("SAME DOC")
}else {
// SwiftyBeaver.debug("DIFF DOC")
update()
}
}
currentContext = to
}
func lockoutDocModeIfNeeded() {
let type = currentType
if (type == .document) && !GhostEngineClient.shared.docModeAvailable {
SwiftyBeaver.debug("locking out doc mode for context \(GhostEngineClient.shared._ghostContext)")
currentType = .app
}
}
func loadNoteFor(context:GhostContext, of type:NoteType) {
// loads page then sets ops
if context.appResult.identifier == GhostEngineKeys.unknown {
return
}
editor?.currentEditContext = context
// find or create
if let n = Storage.shared.ghostNote(for: context,
of: type) {
editor?.ops = n.contents!
if n.hasNote() {
GNStatusItemController.hasNote()
if n.hasTodos() {
GNStatusItemController.hasPendingTodos()
}
}else {
GNStatusItemController.hasNoNote()
}
}else {
GNStatusItemController.hasNoNote()
editor?.ops = Storage.shared.noteSeed()
}
}
override func viewWillAppear() {
super.viewWillAppear()
applyTheme()
SwiftyBeaver.info("")
guard let num = view.window?.windowNumber else {return}
GhostEngineClient.shared.ignoreWindow(number: num)
}
override func viewDidDisappear() {
super.viewDidDisappear()
guard let num = view.window?.windowNumber else {return}
GhostEngineClient.shared.stopIgorningWindow(number: num)
}
override func viewDidAppear() {
super.viewDidAppear()
view.window?.level = .dock
SwiftyBeaver.info("")
}
fileprivate func registerForNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(handleExternalChange(notif:)),
name: GNN.Editing.browserEdited,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(applyTheme),
name:GNN.Theme.themeChangedNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(handleExpandCollapseToggle),
name: GhostNoteWindow.Notifications.collapsed,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(handleExpandCollapseToggle),
name: GhostNoteWindow.Notifications.expanded,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(enterAppMode),
name: GNN.ContextWindowUI.appModeRequested,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(enterDocMode),
name: GNN.ContextWindowUI.docModeRequested,
object: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
view.focusRingType = .none
GhostEngineClient.shared.addObserver(self)
view.wantsLayer = true
view.layer?.cornerRadius = 12
registerForNotifications()
editor = GhostNoteEditor()
editor?.textView = textView
editor?.editorID = "context"
// applyTheme()
settingsMenu.delegate = self
themeMenuItem.submenu = Menus.themeMenu()
SwiftyBeaver.info("LOADED CONTEXT VIEW \(view.frame)")
}
override func viewWillDisappear() {
super.viewWillDisappear()
guard let num = view.window?.windowNumber else {return}
SwiftyBeaver.debug("\(num)")
GhostEngineClient.shared.stopIgorningWindow(number: num)
}
// shuokd go in menu controller
@IBAction func handleDock(_ sender:Any?) {
if let w = view.window as? GhostNoteWindow {
w.attached = !w.attached
if w.attached {
dockMenuItems.title = "Un-dock"
}else {
dockMenuItems.title = "Dock"
}
}
}
@objc func updateUI() {
buttons().forEach { (b) in
b?.attributedTitle = NSAttributedString(string: b!.title,
attributes: [.foregroundColor:ThemeManager.currentTheme.textColor() ,
.font: NSFont.systemFont(ofSize: 24)])
}
updateTitleView()
}
@objc func handleExpandCollapseToggle() {
updateTitleView()
if let w = view.window as? GhostNoteWindow {
settingsButton?.isHidden = w.collapsed
}
}
@objc func updateTitleView() {
titleView?.update(type: currentType)
}
@IBAction func settingsTapped(_ sender:AnyObject?) {
if let event = NSApplication.shared.currentEvent {
NSMenu.popUpContextMenu(settingsMenu!,
with: event,
for: settingsButton!)
}
}
@IBAction func importTapped(_ sender:AnyObject?) {
// let sb = NSStoryboard(name: "Importer",
// bundle: nil)
// if let vc = sb.instantiateInitialController() as? ImportViewController {
// self.presentAsSheet(vc)
// }
SwiftyBeaver.info("inport depreacted")
}
func loadPageForTheme() {
//
// let r = ThemeManager.currentTheme.bundleURLForTemplate()
// var u = r
//
// if UserDefaults.standard.bool(forKey: "ToolBarEnabled") {
// u = ThemeManager.currentTheme.bundleURLForTemplateWithToolbar()
// }
//
// do {
//
// let s = try String(contentsOf:u)
// editor?.textView?.loadHTMLString(s,
// baseURL: Bundle.main.resourceURL)
// }catch {
// SwiftyBeaver.error(error)
// }
}
@objc func applyTheme() {
let t = ThemeManager.currentTheme
let c = t.bgColor()
view.layer?.backgroundColor = c.cgColor
view.layer?.borderColor = c.cgColor
textView?.layer?.backgroundColor = .clear
loadPageForTheme()
loadNoteFor(context: GhostEngineClient.shared.currentContext(),
of: currentType)
settingsButton?.image = ThemeManager.currentTheme.threeDots()
updateUI()
showSelectedTheme()
}
func showSelectedTheme() {
let onAttribs = [NSAttributedString.Key.font : NSFont.boldSystemFont(ofSize: 14)]
let offAttribs = [NSAttributedString.Key.font : NSFont.systemFont(ofSize: 14)]
if let menu = themeMenuItem.submenu {
let t = ThemeManager.currentTheme.rawValue
for item in menu.items {
if item.title == t {
item.state = .on
item.attributedTitle = NSAttributedString(string: t, attributes:onAttribs )
}else {
item.state = .off
item.attributedTitle = NSAttributedString(string: item.title, attributes:offAttribs )
}
}
}
}
@IBAction func showHotkeys(_ sender:Any?) {
NotificationCenter.default.post(name: GNN.Navigation.showHotkeys,
object: nil)
}
@IBAction func showBrowser(_ sender:Any?) {
NotificationCenter.default.post(name: GNN.Shortcuts.toggleBrowser,
object: nil)
}
@IBAction func logoutClicked(_ sender:Any?) {
//Logout
SwiftyBeaver.debug("Logout:")
}
@objc @IBAction func showSupport(_ sender:Any?) {
NotificationCenter.default.post(name: GNN.Navigation.showSupport,
object: nil)
}
@IBAction func setTheme(_ sender:Any?) {
if let item = sender as? NSMenuItem {
let s = item.title.trimmingCharacters(in: CharacterSet.whitespaces)
ThemeManager.currentTheme = GNTheme(rawValue:s)!
}else {
SwiftyBeaver.error("sender was \(String(describing: sender)). Must be a NSMenuItem")
}
}
@IBAction func checkForUpdates(sender:Any?) {
NotificationCenter.default.post(name: GNN.Shortcuts.hide, object: nil)
DispatchQueue.main.async {
Updater.shared.checkForUpdates()
}
}
/// <NSMenuDelegate>
func menuWillOpen(_ menu: NSMenu) {
let savedState = UserDefaults.standard.bool(forKey: "WindowAttachedState")
dockMenuItems.title = savedState ? "Un-dock" : "Dock"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment