Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

138 debug mode #117

Merged
merged 25 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fc7045f
implemented debug mode enabling, log details view
NazarYavornytskyy Feb 22, 2021
62e7079
Merge branch 'master' into 138_debug_mode
NazarYavornytskyy Feb 22, 2021
12973ba
Fixed project
NazarYavornytskyy Feb 22, 2021
dc16241
Lint correction
NazarYavornytskyy Feb 22, 2021
7125fde
Corrected typealias usage
NazarYavornytskyy Feb 22, 2021
aee6995
Added typealias
NazarYavornytskyy Feb 23, 2021
9716bfa
Disabled new log usage, make it build success first
NazarYavornytskyy Feb 23, 2021
5878c0a
Make build success first
NazarYavornytskyy Feb 23, 2021
38a5264
Updated Tests scheme with latest updates
NazarYavornytskyy Feb 23, 2021
9b7e4b8
Enabled logs again
NazarYavornytskyy Feb 23, 2021
4e8630e
Fixed unit tests failing
NazarYavornytskyy Feb 23, 2021
8163272
Fixed PR comments
NazarYavornytskyy Feb 24, 2021
d04c2ee
Merge with 'master'
NazarYavornytskyy Mar 2, 2021
0077885
Merge branch 'master' into 138_debug_mode
NazarYavornytskyy Mar 2, 2021
b1ddf81
Fixed real-time/screenshots rest calls
NazarYavornytskyy Mar 2, 2021
be62e50
Added more logining
NazarYavornytskyy Mar 3, 2021
470966a
Moved all classes for Logining to corresponding submodule
NazarYavornytskyy Mar 5, 2021
4ed2404
Corrected Tests project
NazarYavornytskyy Mar 5, 2021
d4c9eb5
Added some additional improvements
NazarYavornytskyy Mar 15, 2021
b397840
Added more improvements for logging
NazarYavornytskyy Mar 17, 2021
953e4ee
Small URl correction for loggining
NazarYavornytskyy Mar 17, 2021
f1f425f
Added "Clear logs" button and functionality
NazarYavornytskyy Mar 18, 2021
2db2496
Added additional changes for URL logging
NazarYavornytskyy Mar 19, 2021
07b05b4
Last changes for url logging
NazarYavornytskyy Mar 19, 2021
163d451
Fixed NSNotification property location
NazarYavornytskyy Mar 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CrowdinSDK.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Pod::Spec.new do |spec|
subspec.source_files = 'CrowdinSDK/Classes/CrowdinAPI/**/*.swift'
subspec.dependency 'Starscream', '~> 3.1.0'
subspec.dependency 'BaseAPI', '~> 0.1.12'
subspec.dependency 'CrowdinSDK/Logs'
end

spec.test_spec 'CrowdinAPI_Tests' do |test_spec|
Expand Down Expand Up @@ -124,4 +125,9 @@ Pod::Spec.new do |spec|
settings.dependency 'CrowdinSDK/CrowdinAPI'
settings.dependency 'CrowdinSDK/LoginFeature'
end

spec.subspec 'Logs' do |feature|
feature.name = 'Logs'
feature.source_files = 'CrowdinSDK/Classes/Features/Logs/**/*.swift'
end
end
49 changes: 46 additions & 3 deletions CrowdinSDK/Assets/Settings/CrowdinLogsVC.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<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">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -14,7 +16,7 @@
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="UN4-wK-dC2">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="CrowdinLogCell" rowHeight="88" id="H0Z-3O-qUA" customClass="CrowdinLogCell" customModule="CrowdinSDK" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="414" height="88"/>
Expand Down Expand Up @@ -71,5 +73,46 @@
</objects>
<point key="canvasLocation" x="31.884057971014496" y="108.48214285714285"/>
</scene>
<!--Crowdin Log DetailsVC-->
<scene sceneID="0o6-ye-BcY">
<objects>
<viewController storyboardIdentifier="CrowdinLogDetailsVC" id="d1o-fh-5qt" customClass="CrowdinLogDetailsVC" customModule="CrowdinSDK" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="OW4-fx-5ft">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DYT-uD-DVG">
<rect key="frame" x="16" y="60" width="382" height="786"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<viewLayoutGuide key="safeArea" id="SOZ-VY-d96"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="SOZ-VY-d96" firstAttribute="bottom" secondItem="DYT-uD-DVG" secondAttribute="bottom" constant="16" id="0GE-Tr-SPY"/>
<constraint firstItem="SOZ-VY-d96" firstAttribute="trailing" secondItem="DYT-uD-DVG" secondAttribute="trailing" constant="16" id="FFv-7R-dOw"/>
<constraint firstItem="DYT-uD-DVG" firstAttribute="leading" secondItem="SOZ-VY-d96" secondAttribute="leading" constant="16" id="PGj-ey-4FP"/>
<constraint firstItem="DYT-uD-DVG" firstAttribute="top" secondItem="SOZ-VY-d96" secondAttribute="top" constant="16" id="YZR-0K-FSX"/>
</constraints>
</view>
<connections>
<outlet property="textView" destination="DYT-uD-DVG" id="uNK-HH-Jsb"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Hgg-6h-jri" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="767" y="113"/>
</scene>
</scenes>
<resources>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typealias CrowdinAPIStringsMappingCompletion = (([String: String]?, Error?) -> V
typealias CrowdinAPIPluralsMappingCompletion = (([AnyHashable: Any]?, Error?) -> Void)
typealias CrowdinAPIXliffMappingCompletion = (([AnyHashable: Any]?, Error?) -> Void)

typealias CrowdinAPIManifestCompletion = ((ManifestResponse?, Error?) -> Void)
typealias CrowdinAPIManifestCompletion = ((ManifestResponse?, String?, Error?) -> Void)

class CrowdinContentDeliveryAPI: BaseAPI {
enum FileType: String {
Expand Down Expand Up @@ -61,7 +61,18 @@ class CrowdinContentDeliveryAPI: BaseAPI {
if let etag = etag {
headers = [Strings.ifNoneMatch.rawValue: etag]
}
super.get(url: stringURL, headers: headers, completion: completion)
super.get(url: stringURL, headers: headers) { data, response, error in
completion(data, response, error)
CrowdinAPILog.logRequest(
method: .GET,
url: stringURL,
parameters: nil,
headers: headers,
body: nil,
responseData: data,
error: error
)
}
}

// MARK - Localization download methods:
Expand Down Expand Up @@ -175,12 +186,12 @@ class CrowdinContentDeliveryAPI: BaseAPI {
if let data = data {
do {
let response = try JSONDecoder().decode(ManifestResponse.self, from: data)
completion(response, nil)
completion(response, stringURL, nil)
} catch {
completion(nil, error)
completion(nil, nil, error)
}
} else {
completion(nil, error)
completion(nil, nil, error)
}
}
}
Expand All @@ -191,6 +202,7 @@ class CrowdinContentDeliveryAPI: BaseAPI {
if let data = result.data {
do {
let response = try JSONDecoder().decode(ManifestResponse.self, from: data)
CrowdinAPILog.logRequest(response: response, stringURL: stringURL, message: "Download manifest for hash - \(hash) for sync")
return (response, nil)
} catch {
return (nil, error)
Expand Down
22 changes: 17 additions & 5 deletions CrowdinSDK/Classes/CrowdinAPI/CrowdinAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ class CrowdinAPI: BaseAPI {
}

var apiPath: String {
return ""
""
}

var fullPath: String {
return baseURL + apiPath
baseURL + apiPath
}

init(organizationName: String? = nil, auth: CrowdinAuth? = nil, session: URLSession = .shared) {
Expand All @@ -45,12 +45,15 @@ class CrowdinAPI: BaseAPI {
self.post(url: url, parameters: parameters, headers: addDefaultHeaders(to: headers), body: body, completion: { data, response, error in
if self.isUnautorized(response: response) {
NotificationCenter.default.post(name: .CrowdinAPIUnautorizedNotification, object: nil)
return;
return
}
guard let data = data else {
completion(nil, error)
return
}

CrowdinAPILog.logRequest(method: .POST, url: url, parameters: parameters, headers: self.addDefaultHeaders(to: headers), body: body, responseData: data)

do {
let response = try JSONDecoder().decode(T.self, from: data)
completion(response, error)
Expand All @@ -70,6 +73,9 @@ class CrowdinAPI: BaseAPI {
guard let data = result.data else {
return (nil, result.error)
}

CrowdinAPILog.logRequest(method: .POST, url: url, parameters: parameters, headers: addDefaultHeaders(to: headers), body: body, responseData: data)

do {
let response = try JSONDecoder().decode(T.self, from: data)
return (response, result.error)
Expand All @@ -89,6 +95,9 @@ class CrowdinAPI: BaseAPI {
completion(nil, error)
return
}

CrowdinAPILog.logRequest(method: .GET, url: url, parameters: parameters, headers: self.addDefaultHeaders(to: headers), responseData: data)

do {
let response = try JSONDecoder().decode(T.self, from: data)
completion(response, error)
Expand All @@ -101,13 +110,16 @@ class CrowdinAPI: BaseAPI {

func cw_getSync<T: Decodable>(url: String, parameters: [String: String]? = nil, headers: [String: String]? = nil) -> (T?, Error?) {
let result = self.get(url: url, parameters: parameters, headers: addDefaultHeaders(to: headers))
if self.isUnautorized(response: result.response) {
if isUnautorized(response: result.response) {
NotificationCenter.default.post(name: .CrowdinAPIUnautorizedNotification, object: nil)
return (nil, nil);
return (nil, nil)
}
guard let data = result.data else {
return (nil, result.error)
}

CrowdinAPILog.logRequest(method: .GET, url: url, parameters: parameters, headers: addDefaultHeaders(to: headers), responseData: data)

do {
let response = try JSONDecoder().decode(T.self, from: data)
return (response, result.error)
Expand Down
2 changes: 1 addition & 1 deletion CrowdinSDK/Classes/CrowdinAPI/SocketAPI/SocketAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class SocketAPI: NSObject {

extension SocketAPI: WebSocketDelegate {
func websocketDidConnect(socket: WebSocketClient) {
self.onConnect?()
onConnect?()
}

func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
Expand Down
4 changes: 4 additions & 0 deletions CrowdinSDK/Classes/CrowdinSDK/Extensions/Dictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ extension Dictionary {
}
return result
}

mutating func trim(header key: Key, placeholder: Value) {
updateValue(placeholder, forKey: key)
}
}
18 changes: 18 additions & 0 deletions CrowdinSDK/Classes/CrowdinSDK/Extensions/UIViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,22 @@ public extension UIViewController {
self.topWindow?.makeKeyAndVisible()
self.topWindow = nil
}

@objc func cw_askToClearLogsAlert() {
let alert = UIAlertController(title: "CrowdinSDK", message: "Are you sure you want to remove all logs?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
alert.cw_dismiss()
CrowdinLogsCollector.shared.clear()
NotificationCenter.default.post(name: NSNotification.Name.refreshLogsName, object: nil)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .destructive, handler: { _ in
alert.cw_dismiss()
}))
alert.cw_present()
}
}

extension NSNotification.Name {

static let refreshLogsName = NSNotification.Name(rawValue: "RefreshLogsNotificationName")
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ class LocalizationUpdateObserver {

func notifyDownload() {
downloadHandlerContainer.handlers.values.forEach({ $0() })
CrowdinLogsCollector.shared.add(log: CrowdinLog(type: .info, message: "Localization downloaded"))
}

func notifyError(with errors: [Error]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class LocalizationProvider: NSObject, LocalizationProviderProtocol {
}

func refreshLocalization() {
self.loadLocalLocalization()
self.fetchRemoteLocalization()
loadLocalLocalization()
fetchRemoteLocalization()
}

// Private method
Expand All @@ -97,6 +97,7 @@ class LocalizationProvider: NSObject, LocalizationProviderProtocol {
guard let self = self else { return }
guard localization == self.localization else { return }
self.setup(with: localizations, strings: strings, plurals: plurals)
CrowdinLogsCollector.shared.add(log: CrowdinLog(type: .info, message: "Localization fetched from local storage"))
}, errorHandler: errorHandler)
}

Expand Down
10 changes: 10 additions & 0 deletions CrowdinSDK/Classes/CrowdinSDK/Typealias.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// Typealias.swift
// BaseAPI
//
// Created by Nazar Yavornytskyy on 2/15/21.
//

import Foundation

typealias VoidCallback = (() -> Void)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// AttributeFactory.swift
// CrowdinSDK
//
// Created by Nazar Yavornytskyy on 2/19/21.
//

import Foundation

struct AttributeFactory {

static func make(_ attribute: LogAttribute) -> NSAttributedString {
let empty = "Empty"
let title = attribute.title

switch attribute {
case let .url(url), let .path(url):
let text = url.isEmpty ? empty : url

return AttributeFactory.attributeWithTitle(title, text)
case let .method(method):
let text = method.isEmpty ? empty : method

return AttributeFactory.attributeWithTitle(title, text)
case let .parameters(dictionary), let .headers(dictionary):
var finalDictionary = dictionary
finalDictionary?.trim(header: "Authorization", placeholder: "Bearer <token>")
let text = finalDictionary?.isEmpty == true ? empty : finalDictionary?.description ?? empty

return AttributeFactory.attributeWithTitle(title, text)
case let .requestBody(body), let .responseBody(body):
var bodyText = empty
if let bodyData = body {
bodyText = bodyData.prettyJSONString ?? empty
}

return AttributeFactory.attributeWithTitle(title, bodyText)
case let .error(error):
let text = error.isEmpty ? empty : error

return AttributeFactory.attributeWithTitle(title, text)
case .newLine:
return NSAttributedString(string: "\n")
case .separator:
return NSAttributedString(string: "\n\n\n")
}
}

static func attributeWithTitle(_ title: String, _ text: String) -> NSAttributedString {
let titleAttribute: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.blue]

let attribute = NSAttributedString(string: text)
let attributes = NSMutableAttributedString(string: title, attributes: titleAttribute)
attributes.append(AttributeFactory.make(.newLine))
attributes.append(attribute)
attributes.append(AttributeFactory.make(.newLine))

return attributes
}
}
Loading