The Write.as desktop (GUI) app for macOS.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
6.5 KiB

  1. //
  2. // ViewController.swift
  3. // writeas
  4. //
  5. // Created by Matt Baer on 12/29/15.
  6. // Copyright © 2015 A Bunch Tell. All rights reserved.
  7. //
  8. import Cocoa
  9. class ViewController: NSViewController, NSTextViewDelegate, NSUserNotificationCenterDelegate {
  10. @IBOutlet var writerText: NSTextView!
  11. @IBOutlet weak var writerScrollContainer: NSScrollView!
  12. var isNight = false
  13. override func viewDidLoad() {
  14. super.viewDidLoad()
  15. loadDocument()
  16. writerText.font = NSFont(name: Preferences.getFont().typeface, size: Preferences.getFontSize())
  17. writerText.isHorizontallyResizable = false
  18. writerText.textContainerInset = NSSize(width: 16, height: 16)
  19. writerText.isAutomaticQuoteSubstitutionEnabled = false
  20. writerText.isAutomaticDashSubstitutionEnabled = false
  21. NSUserNotificationCenter.default.delegate = self
  22. // Do any additional setup after loading the view.
  23. writerText.delegate = self
  24. }
  25. override func viewWillAppear() {
  26. super.viewWillAppear()
  27. self.view.window!.titlebarAppearsTransparent = true
  28. self.view.window!.isMovableByWindowBackground = true
  29. self.view.window!.titleVisibility = .hidden
  30. toggle(isNight: isNight)
  31. }
  32. override func viewDidAppear() {
  33. super.viewDidAppear()
  34. configureWindow()
  35. // Style the window
  36. self.view.window!.title = "Write.as"
  37. }
  38. func configureWindow() {
  39. // Fit textview to window size
  40. writerText.setFrameSize(NSSize(width: self.writerScrollContainer.frame.width - 20, height: self.writerScrollContainer.frame.height))
  41. }
  42. override var representedObject: Any? {
  43. didSet {
  44. // Update the view, if already loaded.
  45. }
  46. }
  47. fileprivate func getDraftPath() -> URL? {
  48. return URL(fileURLWithPath: Constants.draftFile)
  49. }
  50. func saveDocument() {
  51. // Save whatever's written
  52. let path = getDraftPath()
  53. if path == nil {
  54. return
  55. }
  56. //writing
  57. do {
  58. try writerText.textStorage!.string.write(to: path!, atomically: false, encoding: .utf8)
  59. } catch (let err) {
  60. print("ERROR writing: \(err)")
  61. }
  62. }
  63. func loadDocument() {
  64. let path = getDraftPath()
  65. if path == nil {
  66. return
  67. }
  68. do {
  69. let draftText = try String(contentsOf: path!, encoding: .utf8)
  70. writerText.string = draftText
  71. } catch (let err) {
  72. print("ERROR loading: \(err)")
  73. }
  74. }
  75. func embolden() {
  76. formatText(with: "**\(getSelectedText())**", offset: 2)
  77. }
  78. func emphasize() {
  79. formatText(with: "_\(getSelectedText())_", offset: 1)
  80. }
  81. func addLink() {
  82. let text = getSelectedText()
  83. formatText(with: "[\(text)](http://)", offset: text == "" ? 1 : (text.characters.count + 10), alwaysOffset: true)
  84. }
  85. fileprivate func getSelectedText() -> String {
  86. let selectedRange = writerText.selectedRange()
  87. return (self.writerText.textStorage?.string as! NSString).substring(with: selectedRange)
  88. }
  89. fileprivate func formatText(with: String, offset: Int) {
  90. formatText(with: with, offset: offset, alwaysOffset: false)
  91. }
  92. fileprivate func formatText(with: String, offset: Int, alwaysOffset: Bool) {
  93. let selectedRange = writerText.selectedRange()
  94. let selString = getSelectedText()
  95. if self.writerText.shouldChangeText(in: selectedRange, replacementString: with) {
  96. self.writerText.replaceCharacters(in: NSRange(location: selectedRange.location, length: selectedRange.length), with: with)
  97. self.writerText.didChangeText()
  98. if selString == "" || alwaysOffset {
  99. writerText.setSelectedRange(NSRange(location: selectedRange.location + offset, length: 0))
  100. }
  101. }
  102. }
  103. func publish() {
  104. saveDocument()
  105. DispatchQueue.global(qos: .background).async {
  106. let task = Process()
  107. task.launchPath = Bundle.main.resourcePath! + "/writeas"
  108. task.arguments = ["--font", Preferences.getFont().rawValue]
  109. let pipe = Pipe()
  110. task.standardInput = pipe
  111. task.launch()
  112. let fh: FileHandle = pipe.fileHandleForWriting
  113. fh.write(self.writerText.textStorage!.string.data(using: .utf8)!)
  114. fh.closeFile()
  115. task.waitUntilExit()
  116. DispatchQueue.main.async {
  117. if let ad = NSApplication.shared().delegate as? AppDelegate {
  118. ad.filePublishItem.isEnabled = true
  119. }
  120. var notification = NSUserNotification()
  121. if task.terminationStatus == 0 {
  122. // Successfully published
  123. notification.title = "Published!"
  124. notification.informativeText = "The link is copied — press ⌘+V to share it."
  125. } else {
  126. // Something went wrong
  127. notification.title = "Unable to publish."
  128. notification.informativeText = "There was a problem publishing. Please check your internet and try again."
  129. }
  130. notification.soundName = NSUserNotificationDefaultSoundName
  131. NSUserNotificationCenter.default.deliver(notification)
  132. }
  133. }
  134. }
  135. func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent notification: NSUserNotification) -> Bool {
  136. return true
  137. }
  138. func toggle(isNight: Bool) {
  139. let darkBG = NSColor(red:0.13, green:0.13, blue:0.13, alpha:1.0)
  140. if isNight {
  141. self.view.window!.backgroundColor = darkBG
  142. self.writerText.backgroundColor = darkBG
  143. self.writerText.textColor = NSColor.white
  144. } else {
  145. self.view.window!.backgroundColor = NSColor.white
  146. self.writerText.backgroundColor = NSColor.white
  147. self.writerText.textColor = NSColor.black
  148. }
  149. self.isNight = isNight
  150. }
  151. func adjustTextSize(increment: Bool) {
  152. var size = Preferences.getFontSize()
  153. if increment {
  154. size += 2
  155. } else {
  156. size -= 1
  157. }
  158. self.writerText.font = NSFont(name: Preferences.getFont().typeface, size: size)
  159. UserDefaults.standard.set(String(Int(size)), forKey: "editor_text_size")
  160. configureWindow()
  161. }
  162. func setFont(_ font: Preferences.PostFont) {
  163. self.writerText.font = NSFont(name: font.typeface, size: Preferences.getFontSize())
  164. }
  165. }