version bump
[ShaarliOS.git] / swift4 / ShaarliOS / MainVC.swift
blobb2283053985d564d85012f5f1af68dd919bb578d
1 //
2 //  MainVC.swift
3 //  ShaarliOS
4 //
5 //  Created by Marcus Rohrmoser on 15.08.19.
6 //  Copyright © 2019-2022 Marcus Rohrmoser mobile Software http://mro.name/me. All rights reserved.
7 //
8 //  This program is free software: you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License as published by
10 //  the Free Software Foundation, either version 3 of the License, or
11 //  (at your option) any later version.
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 import UIKit
23 import AudioToolbox
25 private func play_sound_ok() {
26     // https://github.com/irccloud/ios/blob/6e3255eab82be047be141ced6e482ead5ac413f4/ShareExtension/ShareViewController.m#L155
27     AudioServicesPlaySystemSound(1001)
30 private func play_sound_err() {
31     AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)
34 // Reading from private effective user settings. https://stackoverflow.com/a/45280879/349514
35 class MainVC: UIViewController, UITextViewDelegate, UITextFieldDelegate {
37     @IBOutlet private var lblVersion    : UILabel!
38     @IBOutlet private var lblName       : UILabel!
39     @IBOutlet private var centerY       : NSLayoutConstraint!
40     @IBOutlet private var vContainer    : UIView!
41     @IBOutlet private var btnPetal      : UIButton!
42     @IBOutlet private var btnSafari     : UIBarButtonItem!
44     @IBOutlet private var viewShaare    : UIView!
45     @IBOutlet private var btnShaare     : UIButton!
46     @IBOutlet private var txtDescr      : UITextView!
47     @IBOutlet private var txtTitle      : UITextField!
48     @IBOutlet private var btnAudience   : UIButton!
50     // http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
51     @IBOutlet private var activeField   : UIView!
52     @IBOutlet private var scrollView    : UIScrollView!
54     @IBOutlet private var spiPost       : UIActivityIndicatorView!
56     var current                 : BlogM?
58     @IBAction func actionCancel(_ sender: Any) {
59         debugPrint("actionCancel \(type(of: self))")
60         guard let b = current else {
61             btnShaare.isEnabled = false
62             btnSafari.isEnabled = btnShaare.isEnabled
63             return
64         }
66         title = b.title
67         spiPost.stopAnimating()
68         btnShaare.isEnabled = true // b != nil
69         btnSafari.isEnabled = btnShaare.isEnabled
70         btnAudience.isSelected = b.privateDefault
71         txtTitle.text = ""
72         txtDescr.text = b.tagsDefault
73         // viewShaare.alpha = 1
74         txtTitle.becomeFirstResponder()
75     }
77     @IBAction func actionPost(_ sender: Any) {
78         debugPrint("actionPost \(type(of: self))")
80         view.bringSubviewToFront(spiPost)
81         spiPost.startAnimating()
82         btnShaare.isEnabled = !spiPost.isAnimating
83         txtDescr.resignFirstResponder()
84         txtTitle.resignFirstResponder()
86         guard let current = current else { return }
87         let srv = current.endpoint
88         let tim = current.timeout
89         let cre = current.credential
90         let tit = txtTitle.text ?? "-"
91         let dsc = txtDescr.text ?? "-"
92         let pri = btnAudience.isSelected
93         let c = ShaarliHtmlClient(AppDelegate.shared.semver)
94         c.get(srv, cre, tim, URLEmpty) { ses, act, ctx, ur_, ti_, de_, ta_, pr_, ts_, seti, err in
95             guard "" == err else {
96                 DispatchQueue.main.async {
97                     self.reportPostingError(err)
98                 }
99                 return
100             }
101             var ctx = ctx
102             ctx.removeValue(forKey: "cancel_edit")
103             let r = tagsNormalise(description:tit, extended:dsc, tags:ta_, known:[])
104             c.add(ses, act, ctx, ur_, r.description, r.extended, r.tags, pri) { err in
105                 DispatchQueue.main.async {
106                     guard "" == err else {
107                         play_sound_err()
108                         self.reportPostingError(err)
109                         return
110                     }
111                     print("set result: '\(ur_)'")
112                     play_sound_ok()
113                     self.actionCancel(self)
114                 }
115             }
116         }
117     }
119     private func reportPostingError(_ err:String) {
120         spiPost.stopAnimating()
121         btnShaare.isEnabled = !spiPost.isAnimating
122         let alert = UIAlertController(
123             title:NSLocalizedString("Sorry, couldn't post", comment:"MainVC"),
124             message:err,
125             preferredStyle:.alert
126         )
127         alert.addAction(UIAlertAction(title:NSLocalizedString("OK", comment:"MainVC"), style:.cancel, handler:nil))
128         present(alert, animated:true, completion:nil)
129     }
131     @IBAction func actionSafari(_ sender: Any) {
132         debugPrint("actionSafari \(type(of: self))")
133         guard let current = current else { return }
134         UIApplication.shared.openURL(current.endpointAnon)
135     }
137     @IBAction func btnAudience(_ sender: Any) {
138         debugPrint("btnAudience \(type(of: self))")
139         btnAudience.isSelected = !btnAudience.isSelected
140         btnAudience.isHighlighted = false
141     }
143     override func viewDidLoad() {
144         debugPrint("viewDidLoad \(type(of: self))")
145         super.viewDidLoad()
146         assert(txtTitle.delegate != nil)
147         assert(txtDescr.delegate != nil)
149         let ad = AppDelegate.shared
150         lblVersion.text = ad.semver
151         lblName.text = BUNDLE_NAME
153         [txtTitle].forEach {
154             $0.setValue($0.textColor?.withAlphaComponent(0.4), forKeyPath:"placeholderLabel.textColor")
155         }
157         view.addSubview(spiPost)
158         spiPost.frame = view.bounds
159         // view.addConstraint(NSLayoutConstraint(item:view, attribute:.centerX, relatedBy:.equal, toItem:spiPost, attribute:.centerX, multiplier:1.0, constant:0))
160         // view.addConstraint(NSLayoutConstraint(item:view, attribute:.centerY, relatedBy:.equal, toItem:spiPost, attribute:.centerY, multiplier:1.0, constant:0))
161     }
163     override func viewWillAppear(_ animated: Bool) {
164         debugPrint("viewWillAppear \(type(of: self))")
165         super.viewWillAppear(animated)
167         let sm = ShaarliM.shared
168         current = sm.loadBlog(sm.defaults)
169         btnSafari.isEnabled = current?.endpoint != nil
170         btnAudience.isSelected = current?.privateDefault ?? false
171         if nil == current {
172             title = NSLocalizedString("-", comment:"MainVC")
173         }
175         actionCancel(self)
176         viewShaare!.alpha = 0
177     }
179     override func viewDidAppear(_ animated: Bool) {
180         debugPrint("viewDidAppear \(type(of: self))")
181         super.viewDidAppear(animated)
182         UIView.setAnimationsEnabled(true)
184         let dt = 0.75
185         UIView.animate(withDuration:dt) {
186             self.vContainer.alpha = 0.5;
188             // logo to bottom
189             self.view.removeConstraint(self.centerY)
190             self.centerY = self.centerY.withMultiplier(0.75)
191             self.view.addConstraint(self.centerY)
192             // self.view.layoutIfNeeded()
193             self.viewShaare.alpha = 1
194         }
196         if current == nil {
197             performSegue(withIdentifier:String(describing:SettingsVC.self), sender:self)
198             return
199         }
201         // start with note form ready..
202         // [self actionShowShaare:nil];
203        // actionCancel(self)
204     }
206     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
207         guard let vc = segue.destination as? SettingsVC else { return }
208         vc.current = current
209     }
211     // MARK: - UITextFieldDelegate
213     func textFieldShouldReturn(_ textField: UITextField) -> Bool {
214         print("textFieldShouldReturn \(type(of: self))")
215         switch textField {
216         case txtTitle: txtDescr.becomeFirstResponder()
217         default: return false
218         }
219         return true
220     }
223 // visual form center http://stackoverflow.com/a/13148012/349514
224 extension NSLayoutConstraint {
225     func withMultiplier(_ mu : CGFloat) -> NSLayoutConstraint {
226         return NSLayoutConstraint(
227             item:firstItem!,
228             attribute:firstAttribute,
229             relatedBy:relation,
230             toItem:secondItem,
231             attribute:secondAttribute,
232             multiplier:mu,
233             constant:constant)
234     }