Skip to content

Commit c5c9838

Browse files
aarashgoodarziArash Goodarzi
andauthored
Add response online validator (#23)
* response and toolbar in rtl languages issue fixed * body aligment in search mode fixed * body issue on dark mode fixed Co-authored-by: Arash Goodarzi <arash.goodarzi@divar.ir> Co-authored-by: Arash Goodarzi <arash.goodarzi@divar.ir>
1 parent 584abc1 commit c5c9838

4 files changed

Lines changed: 119 additions & 19 deletions

File tree

Sources/NetShears/UI/BodyDetailViewController.swift

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import UIKit
1010

1111
final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
12+
1213
@IBOutlet weak var bottomViewInputConstraint: NSLayoutConstraint!
1314
@IBOutlet weak var toolBar: UIToolbar!
1415
@IBOutlet weak var labelWordFinded: UILabel!
@@ -19,37 +20,85 @@ final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
1920
static let kPadding: CGFloat = 10.0
2021

2122
var bodyExportType: BodyExportType = .default
22-
23+
var textColor: UIColor {
24+
guard #available(iOS 13.0, *) else {
25+
return .black
26+
}
27+
return UIColor(dynamicProvider: { trait in
28+
switch trait.userInterfaceStyle {
29+
case .light:
30+
return .black
31+
case .dark:
32+
return .white
33+
case .unspecified:
34+
return .gray
35+
@unknown default:
36+
return .gray
37+
}
38+
})
39+
}
2340
var searchController: UISearchController?
2441
var highlightedWords: [NSTextCheckingResult] = []
2542
var data: Data?
2643
var indexOfWord: Int = 0
2744

45+
let jsonValidatorOnline = JSONValidatorOnline()
46+
2847
deinit {
2948
NotificationCenter.default.removeObserver(self)
3049
}
3150

3251
override func viewDidLoad() {
3352
super.viewDidLoad()
53+
54+
setupObservers()
55+
setupTextView()
56+
setupNavigationItems()
57+
setupNextPreviousButtons()
58+
addSearchController()
59+
hideViewInValidatorButtonIfNeeded()
60+
}
61+
62+
override func viewWillAppear(_ animated: Bool) {
63+
super.viewWillAppear(animated)
64+
setBody()
65+
}
66+
67+
private func setupObservers() {
3468
NotificationCenter.default.addObserver(self, selector: #selector(BodyDetailViewController.handleKeyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
3569
NotificationCenter.default.addObserver(self, selector: #selector(BodyDetailViewController.handleKeyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
70+
}
3671

72+
private func setupTextView() {
3773
textView.font = UIFont(name: "Courier", size: 14)
3874
textView.dataDetectorTypes = UIDataDetectorTypes.link
75+
setupAlignmentAndColor()
76+
}
77+
78+
private func setupAlignmentAndColor() {
79+
textView.textAlignment = .left
80+
textView.textColor = textColor
81+
}
3982

83+
private func setupNavigationItems() {
4084
let shareButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareContent(_:)))
4185
let searchButton = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(showSearch))
4286
navigationItem.rightBarButtonItems = [searchButton, shareButton]
87+
}
4388

89+
private func setupNextPreviousButtons() {
4490
buttonPrevious.isEnabled = false
4591
buttonNext.isEnabled = false
46-
addSearchController()
92+
guard UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft, var items = toolBar.items else {
93+
return
94+
}
95+
items.reverse()
96+
toolBar.items = items
4797
}
4898

49-
override func viewWillAppear(_ animated: Bool) {
50-
super.viewWillAppear(animated)
99+
private func setBody() {
51100
let hud = showLoader(view: view)
52-
RequestExporter.body(data, bodyExportType: bodyExportType ) { [weak self] (stringData) in
101+
RequestExporter.body(data, bodyExportType: bodyExportType) { [weak self] stringData in
53102
let formattedJSON = stringData
54103
DispatchQueue.main.async {
55104
self?.textView.text = formattedJSON
@@ -58,15 +107,6 @@ final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
58107
}
59108
}
60109

61-
override func viewDidAppear(_ animated: Bool) {
62-
super.viewDidAppear(animated)
63-
64-
}
65-
66-
override func didReceiveMemoryWarning() {
67-
super.didReceiveMemoryWarning()
68-
}
69-
70110
// MARK: - Search
71111
func addSearchController(){
72112
searchController = UISearchController(searchResultsController: nil)
@@ -87,6 +127,14 @@ final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
87127
definesPresentationContext = true
88128
}
89129

130+
func hideViewInValidatorButtonIfNeeded() {
131+
if #available(iOS 11.0, *) {
132+
return
133+
}
134+
let irRTL = view.semanticContentAttribute == .forceRightToLeft
135+
_ = irRTL ? toolBar.items?.removeLast() : toolBar.items?.removeFirst()
136+
}
137+
90138
@IBAction func previousStep(_ sender: UIBarButtonItem?) {
91139
indexOfWord -= 1
92140
if indexOfWord < 0 {
@@ -103,6 +151,10 @@ final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
103151
getCursor()
104152
}
105153

154+
@IBAction func openValidatorTapped(_ sender: Any) {
155+
jsonValidatorOnline.open(jsonString: textView.text, on: self)
156+
}
157+
106158
func getCursor() {
107159
let value = highlightedWords[indexOfWord]
108160
if let range = textView.convertRange(range: value.range) {
@@ -114,6 +166,7 @@ final class BodyDetailViewController: UIViewController, ShowLoaderProtocol {
114166
textView.setContentOffset(CGPoint(x: 0, y: rect.origin.y - BodyDetailViewController.kPadding), animated: true)
115167
}
116168
cursorAnimation(with: value.range)
169+
setupAlignmentAndColor()
117170
}
118171
}
119172

@@ -192,14 +245,16 @@ extension BodyDetailViewController: UISearchBarDelegate {
192245

193246
extension BodyDetailViewController {
194247
func resetSearchText() {
195-
let attributedString = NSMutableAttributedString(attributedString: self.textView.attributedText)
248+
let prettyString = textView.attributedText.string.prettyPrintedJSON ?? textView.attributedText.string
249+
let attributedString = NSMutableAttributedString(string: prettyString)
196250
attributedString.addAttribute(.backgroundColor, value: UIColor.clear, range: NSRange(location: 0, length: self.textView.attributedText.length))
197251
attributedString.addAttribute(.font, value: UIFont(name: "Courier", size: 14)!, range: NSRange(location: 0, length: self.textView.attributedText.length))
198252

199253
self.textView.attributedText = attributedString
200254
self.labelWordFinded.text = "0 of 0"
201255
self.buttonPrevious.isEnabled = false
202256
self.buttonNext.isEnabled = false
257+
setupAlignmentAndColor()
203258
}
204259

205260
func cursorAnimation(with range: NSRange) {

Sources/NetShears/UI/Flow.storyboard

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="B9l-eh-LuR">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="B9l-eh-LuR">
33
<device id="retina4_7" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
77
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
88
<capability name="System colors in document resources" minToolsVersion="11.0"/>
99
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -111,9 +111,14 @@
111111
<rect key="frame" x="0.0" y="623" width="375" height="44"/>
112112
<items>
113113
<barButtonItem style="plain" systemItem="flexibleSpace" id="RNb-pa-Z9b"/>
114+
<barButtonItem title="View in Validator" id="Xjg-eS-cAm">
115+
<connections>
116+
<action selector="openValidatorTapped:" destination="S40-LP-XSy" id="Bx9-e4-Egz"/>
117+
</connections>
118+
</barButtonItem>
114119
<barButtonItem style="plain" id="Dvu-s4-6n6">
115120
<view key="customView" contentMode="scaleToFill" id="wDm-Tn-1Yd">
116-
<rect key="frame" x="134" y="5.5" width="177" height="33"/>
121+
<rect key="frame" x="150" y="5.5" width="177" height="33"/>
117122
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
118123
<subviews>
119124
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0 of 0" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VxO-VX-XW4">
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Arash on 9/14/22.
6+
//
7+
8+
import UIKit
9+
import SafariServices
10+
11+
struct JSONValidatorOnline {
12+
13+
func open(jsonString: String?, on vc: UIViewController) {
14+
guard let jsonString = jsonString,
15+
let encodedJson = jsonString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
16+
else {
17+
print("NetShears - jsonString not received")
18+
return
19+
}
20+
let base = "https://jsoneditoronline.org/#left=json."
21+
let mode = "&mode=tree"
22+
let url = base + encodedJson + mode
23+
openBrowser(for: url, on: vc)
24+
}
25+
26+
private func openBrowser(for url: String, on vc: UIViewController) {
27+
guard #available(iOS 11.0, *) else {
28+
print("NetShears - iOS version not supported")
29+
return
30+
}
31+
let config = SFSafariViewController.Configuration()
32+
config.entersReaderIfAvailable = true
33+
guard let url = URL(string: url) else {
34+
print("NetShears - invalid url")
35+
return
36+
}
37+
let browserVc = SFSafariViewController(url: url, configuration: config)
38+
vc.present(browserVc, animated: true)
39+
}
40+
}

Sources/NetShears/Utils/RequestExporter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ final class RequestExporter: NSObject {
4747

4848
static func body(_ body: Data?, splitLength: Int? = nil, bodyExportType: BodyExportType) -> String {
4949
if case .custom(let text) = bodyExportType {
50-
return text
50+
return text.prettyPrintedJSON ?? text
5151
}
5252

5353
guard body != nil else {

0 commit comments

Comments
 (0)