@@ -0,0 +1,257 @@
1+//
2+// NewPostViewController.swift
3+// GDproject
4+//
5+// Created by cstore on 05/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import Cartography
11+import Marklight
12+import TinyConstraints
13+
14+class NewPostViewController: UIViewController, UITextViewDelegate {
15+
16+ @IBOutlet weak var view1: UIView!
17+ // Keep strong instance of the `NSTextStorage` subclass
18+ let textStorage = MarklightTextStorage()
19+
20+ weak var parentVC: NewsController?
21+
22+ static var draft: String = ""
23+ var textView: UITextView!
24+
25+ // buttons for attaching images
26+ var accessoryView: UIView = {
27+ let view = UIView()
28+ view.backgroundColor = .white
29+ return view
30+ }()
31+
32+ var addEquasion: UIButton = {
33+ var button = UIButton(type: .detailDisclosure)
34+ button.addTarget(self, action: #selector(addMathBrackets), for: .touchUpInside)
35+ return button
36+ }()
37+
38+ // stack view where buttons will be places
39+ var stackAccessoryView: UIStackView?
40+ // Connect the view1's bottom layout constraint to react to keyboard movements
41+
42+ @IBOutlet weak var bottomTextViewConstraint: NSLayoutConstraint!
43+
44+
45+ override func viewDidLoad()
46+ {
47+ super.viewDidLoad()
48+ setUpMD()
49+ setUpTextView()
50+ setUpAccessoryView()
51+ }
52+
53+ override func viewWillAppear(_ animated: Bool) {
54+ super.viewWillAppear(animated)
55+
56+ navigationController?.navigationBar.prefersLargeTitles = false
57+ navigationItem.title = "New post"
58+ textView.text = NewPostViewController.draft
59+ }
60+
61+ func setUpAccessoryView(){
62+ let views = [UIButton(type: .contactAdd),addEquasion]
63+ stackAccessoryView = UIStackView(arrangedSubviews: views)
64+
65+ stackAccessoryView?.alignment = .fill
66+ stackAccessoryView?.distribution = .equalSpacing
67+
68+ view1.addSubview(accessoryView)
69+ accessoryView.addSubview(stackAccessoryView!)
70+ accessoryView.height(40)
71+
72+ let separatorView = UIView()
73+ separatorView.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
74+ accessoryView.addSubview(separatorView)
75+ separatorView.height(1)
76+ separatorView.edgesToSuperview(excluding: .bottom)
77+
78+ accessoryView.edgesToSuperview(excluding: [.top])
79+ stackAccessoryView!.edgesToSuperview(insets: .left(16) + .right(16) + .top(1))
80+ }
81+
82+ func setUpTextView(){
83+ view.addConstraint(bottomTextViewConstraint)
84+ view1.addSubview(textView)
85+ textView.edgesToSuperview(insets: .top(8) + .left(8) + .bottom(40+8) + .right(8))
86+
87+ if #available(iOS 11.0, *) {
88+ textView.smartDashesType = .no
89+ textView.smartQuotesType = .no
90+ }
91+
92+ textView.isScrollEnabled = true
93+
94+ guard let bottomTextViewConstraint = bottomTextViewConstraint else { return }
95+ view.addConstraint(bottomTextViewConstraint)
96+
97+ // Add a beautiful padding to the `UITextView` content
98+ textView.textContainerInset = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
99+ textView.delegate = self
100+ magicForKeyboardChanges()
101+ }
102+
103+
104+ func magicForKeyboardChanges()
105+ {
106+ /////////////////////////////
107+ // We do some magic to resize the `UITextView` to react the the keyboard size change (appearance, disappearance, ecc)
108+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
109+
110+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
111+
112+ // Partial fixes to a long standing bug, to keep the caret inside the `UITextView` always visible
113+ NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: textView, queue: OperationQueue.main) { (notification) -> Void in
114+ if self.textView.textStorage.string.hasSuffix("\n") {
115+ CATransaction.setCompletionBlock({ () -> Void in
116+ self.scrollToCaret(self.textView, animated: false)
117+ })
118+ } else {
119+ self.scrollToCaret(self.textView, animated: false)
120+ }
121+ }
122+
123+ }
124+
125+ @objc func handleKeyboardNotifications(notification: NSNotification){
126+ if let userInfo = notification.userInfo{
127+ // UIKeyboardFrameEndUserInfoKey
128+ let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
129+ bottomTextViewConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? keyBoardFrame.height : 0
130+ print(bottomTextViewConstraint!.constant)
131+
132+ UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
133+ self.view.layoutIfNeeded()
134+ }) { (completed) in
135+
136+ }
137+ }
138+ }
139+
140+ @objc func attachPhoto(){
141+
142+ }
143+
144+
145+ @objc func addMathBrackets()
146+ {
147+ if textView.text.count != 0 && textView.text.last != "\n" {
148+ textView.insertText("\n\\[\n ")
149+ }
150+ else {
151+ textView.insertText("\\[\n ")
152+ }
153+
154+ if let selectedRange = textView.selectedTextRange
155+ {
156+ textView.insertText("\n\\]\n")
157+
158+ if let newPosition = textView.position(from: selectedRange.start, offset: 0)
159+ {
160+ // set the new position
161+ textView.selectedTextRange = textView.textRange(from: newPosition, to: newPosition)
162+ }
163+ }
164+ }
165+
166+ func setUpMD(){
167+ textStorage.marklightTextProcessor.codeColor = UIColor.orange
168+ textStorage.marklightTextProcessor.quoteColor = UIColor.darkGray
169+ textStorage.marklightTextProcessor.syntaxColor = UIColor.blue
170+ textStorage.marklightTextProcessor.codeFontName = "Courier"
171+ textStorage.marklightTextProcessor.fontTextStyle = UIFont.TextStyle.subheadline.rawValue
172+ textStorage.marklightTextProcessor.hideSyntax = false
173+
174+ let layoutManager = NSLayoutManager()
175+
176+ // Assign the `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass
177+ textStorage.addLayoutManager(layoutManager)
178+
179+ let textContainer = NSTextContainer()
180+ layoutManager.addTextContainer(textContainer)
181+
182+ textView = UITextView(frame: view.bounds, textContainer: textContainer)
183+ }
184+
185+ // MARK:- new post
186+ @objc func newPost(){
187+ let p = Post(dataArray: [.text(textView.text)], from: User(name: "Сева", id: 5, fullName: "Сева Леонидович"), date: "12.01.19")
188+
189+
190+ // adding row to uiTableView after adding new post
191+ guard let vc = parentVC else {return}
192+ vc.tableView.beginUpdates()
193+ let indexPath1: IndexPath = IndexPath(row: 0, section: 0)
194+ vc.dataSourse.insert(p, at: 0)
195+ vc.tableView.insertRows(at: [indexPath1], with: .fade)
196+ vc.tableView.endUpdates()
197+ moveBackToParentVC()
198+ // somewhere here i will be sending server notifications about new post arrival
199+ }
200+
201+ @objc func actionSaveDraft(){
202+ let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
203+
204+ let saveAction = UIAlertAction(title: "Save draft", style: .default)
205+ {
206+ _ in
207+ NewPostViewController.draft = self.textView.text
208+ self.moveBackToParentVC()
209+ }
210+
211+ let deleteAction = UIAlertAction(title: "Delete draft", style: .destructive)
212+ {
213+ (_)
214+ in
215+ NewPostViewController.draft = ""
216+ self.moveBackToParentVC()
217+ }
218+
219+ let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
220+
221+ optionMenu.addAction(saveAction)
222+ optionMenu.addAction(deleteAction)
223+ optionMenu.addAction(cancelAction)
224+
225+ self.present(optionMenu, animated: true, completion: nil)
226+ }
227+
228+ @objc func closeView()
229+ {
230+ actionSaveDraft()
231+ }
232+
233+ func moveBackToParentVC(){
234+ let transition = CATransition()
235+ transition.duration = 0.5
236+ transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
237+ transition.type = CATransitionType.reveal
238+ transition.subtype = CATransitionSubtype.fromBottom
239+ navigationController?.view.layer.add(transition, forKey: nil)
240+ navigationController?.popViewController(animated: false)
241+ textView!.resignFirstResponder()
242+ }
243+
244+
245+
246+
247+ func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
248+ print("Should interact with: \(URL)")
249+ return true
250+ }
251+
252+ func scrollToCaret(_ textView: UITextView, animated: Bool) {
253+ var rect = textView.caretRect(for: textView.selectedTextRange!.end)
254+ rect.size.height = rect.size.height + textView.textContainerInset.bottom
255+ textView.scrollRectToVisible(rect, animated: animated)
256+ }
257+}