Skip to content

Commit

Permalink
add NewsService
Browse files Browse the repository at this point in the history
  • Loading branch information
Macostik committed Jan 21, 2020
1 parent 80ea888 commit 69fec5d
Show file tree
Hide file tree
Showing 12 changed files with 412 additions and 20 deletions.
20 changes: 20 additions & 0 deletions FisherMan.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
56762AF423872025000E8501 /* SlimLoggerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56762AE223872025000E8501 /* SlimLoggerConfig.swift */; };
56762AF9238AF51E000E8501 /* NSLayoutConstraint+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56762AF8238AF51E000E8501 /* NSLayoutConstraint+Ext.swift */; };
56762AFB238AF5B3000E8501 /* UIView+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56762AFA238AF5B3000E8501 /* UIView+Ext.swift */; };
568659F123D6F92000FBB61C /* RealmService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568659F023D6F92000FBB61C /* RealmService.swift */; };
568659F323D75EED00FBB61C /* NewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568659F223D75EEC00FBB61C /* NewsService.swift */; };
568659F523D75F8400FBB61C /* LanguageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568659F423D75F8400FBB61C /* LanguageManager.swift */; };
568659F723D75FBA00FBB61C /* LanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568659F623D75FBA00FBB61C /* LanguageModel.swift */; };
568659F923D761E200FBB61C /* String+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568659F823D761E200FBB61C /* String+Ext.swift */; };
56B9F7E423D59BD200C03F5E /* DetailSceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56B9F7E023D59BD200C03F5E /* DetailSceneCoordinator.swift */; };
56B9F7E523D59BD200C03F5E /* DetailSceneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56B9F7E123D59BD200C03F5E /* DetailSceneViewController.swift */; };
56B9F7E623D59BD200C03F5E /* DetailSceneModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56B9F7E223D59BD200C03F5E /* DetailSceneModel.swift */; };
Expand Down Expand Up @@ -113,6 +118,11 @@
56762AE223872025000E8501 /* SlimLoggerConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlimLoggerConfig.swift; sourceTree = "<group>"; };
56762AF8238AF51E000E8501 /* NSLayoutConstraint+Ext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Ext.swift"; sourceTree = "<group>"; };
56762AFA238AF5B3000E8501 /* UIView+Ext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Ext.swift"; sourceTree = "<group>"; };
568659F023D6F92000FBB61C /* RealmService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealmService.swift; sourceTree = "<group>"; };
568659F223D75EEC00FBB61C /* NewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsService.swift; sourceTree = "<group>"; };
568659F423D75F8400FBB61C /* LanguageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageManager.swift; sourceTree = "<group>"; };
568659F623D75FBA00FBB61C /* LanguageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageModel.swift; sourceTree = "<group>"; };
568659F823D761E200FBB61C /* String+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Ext.swift"; sourceTree = "<group>"; };
56B9F7E023D59BD200C03F5E /* DetailSceneCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailSceneCoordinator.swift; sourceTree = "<group>"; };
56B9F7E123D59BD200C03F5E /* DetailSceneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailSceneViewController.swift; sourceTree = "<group>"; };
56B9F7E223D59BD200C03F5E /* DetailSceneModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailSceneModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -156,6 +166,8 @@
children = (
4363693823CC710D00A620F6 /* InteractionAnimation.swift */,
436160B823CF2CCB0045AB81 /* InteractionNavigationController.swift */,
568659F023D6F92000FBB61C /* RealmService.swift */,
568659F223D75EEC00FBB61C /* NewsService.swift */,
);
path = Services;
sourceTree = "<group>";
Expand Down Expand Up @@ -204,6 +216,7 @@
56762ACD23872024000E8501 /* Environment.swift */,
56762ACE23872024000E8501 /* ApiManager.swift */,
56762ACF23872024000E8501 /* Dependency.swift */,
568659F423D75F8400FBB61C /* LanguageManager.swift */,
);
path = CommonClasses;
sourceTree = "<group>";
Expand Down Expand Up @@ -257,6 +270,7 @@
436A8C5123C5DF5D00F0B44D /* NewsSceneModel.swift */,
56B9F7EA23D59D6600C03F5E /* SearchSceneModel.swift */,
43562C5E23C8CDAE00996D84 /* TabBarSceneModel.swift */,
568659F623D75FBA00FBB61C /* LanguageModel.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -296,6 +310,7 @@
children = (
56762AF8238AF51E000E8501 /* NSLayoutConstraint+Ext.swift */,
56762AFA238AF5B3000E8501 /* UIView+Ext.swift */,
568659F823D761E200FBB61C /* String+Ext.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -498,13 +513,18 @@
4363693723CC666000A620F6 /* CameraSceneCoordinator.swift in Sources */,
56762AF223872025000E8501 /* SlimLogglyDestination.swift in Sources */,
436160B923CF2CCB0045AB81 /* InteractionNavigationController.swift in Sources */,
568659F523D75F8400FBB61C /* LanguageManager.swift in Sources */,
56762AE923872025000E8501 /* SplashSceneViewModel.swift in Sources */,
568659F323D75EED00FBB61C /* NewsService.swift in Sources */,
56762AFB238AF5B3000E8501 /* UIView+Ext.swift in Sources */,
56B9F7EF23D59D6600C03F5E /* SearchSceneViewModel.swift in Sources */,
56762AF9238AF51E000E8501 /* NSLayoutConstraint+Ext.swift in Sources */,
56B9F80723D5A21300C03F5E /* ProfileSceneViewModel.swift in Sources */,
568659F923D761E200FBB61C /* String+Ext.swift in Sources */,
43F99C4823A3D4DD008F6CD4 /* MainSceneViewController.swift in Sources */,
568659F123D6F92000FBB61C /* RealmService.swift in Sources */,
43F99C5123A3DFA6008F6CD4 /* NewsSceneViewModel.swift in Sources */,
568659F723D75FBA00FBB61C /* LanguageModel.swift in Sources */,
56B9F7E723D59BD200C03F5E /* DetailSceneViewModel.swift in Sources */,
4363693923CC710D00A620F6 /* InteractionAnimation.swift in Sources */,
56762AEA23872025000E8501 /* AppCoordinator.swift in Sources */,
Expand Down
10 changes: 9 additions & 1 deletion FisherMan/CommonClasses/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
import UIKit
import Foundation

//height controls
let keyWindow = UIApplication.shared.connectedScenes.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene}).compactMap({$0}).first?.windows.filter({$0.isKeyWindow}).first
let navigationBarHeight = 44 + (keyWindow?.safeAreaInsets.bottom ?? 0)
let tabBarHeight = 44 + (keyWindow?.safeAreaInsets.bottom ?? 0)

struct Constants {
static let baseURL = Environment.isProduction ? "http://nps-api-proxy.onespace.prod/api/v1/mobile/news" :
Environment.isDevelop ? "http://nps-api-proxy.onespace.devel/api/v1/mobile/news" :
Expand All @@ -18,5 +24,7 @@ struct Constants {
static let iOS13Version = ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 13
static let screenWidth = UIScreen.main.bounds.width
static let screenHeight = UIScreen.main.bounds.height
static let mainCollectionViewCell = "mainCollectionViewCell"
static let mainCollectionViewCell = "mainCollectionViewCell"
static let serviceID = "1fa7ce2d8fde588ac8fc"
static let localizeNames = "localizationsShortNames"
}
69 changes: 69 additions & 0 deletions FisherMan/CommonClasses/LanguageManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// LanguageManager.swift
// FisherMan
//
// Created by Yura Granchenko on 21.01.2020.
// Copyright © 2020 GYS. All rights reserved.
//

import UIKit
import RxSwift
import RealmSwift

enum Localable: String {
case en, ru
}

final class LanguageManager {

static let shared = LanguageManager()
fileprivate let disposeBag = DisposeBag()
public let notifyObservable = BehaviorSubject<Void>(value: ())

init() {
do {
let realm = try Realm()
guard let language = realm.objects(LanguageModel.self).first else {
let deviceLocale = Locale.preferredLanguages[0].prefix(2).toString()
let language = LanguageModel()
language.locale = deviceLocale
locale = Localable(rawValue: deviceLocale) ?? .en
try realm.write {
realm.add(language, update: .modified)
}
return
}
locale = Localable(rawValue: language.locale) ?? .en
} catch {}
}

public var bundle: Bundle {
return Bundle(path: Bundle.main.path(forResource: locale.rawValue, ofType: "lproj") ?? "")
?? Bundle.main
}

public var locale: Localable = .en {
didSet {
Logger.verbose("Set new locale: \(locale.rawValue)")
do {
let realm = try Realm()
let language = LanguageModel()
language.locale = locale.rawValue
try realm.write {
realm.add(language, update: .modified)
}
notifyObservable.onNext(())
} catch {}
}
}

public var language: String {
let language = locale == .en ? "English" : "Russian"
return language
}

public var isRussian: Bool {
return locale == .ru
}
}

1 change: 1 addition & 0 deletions FisherMan/Coordinators/TabBarSceneCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extension TabBarSceneCoordinator {
}

extension TabBarSceneModel {

func coordinator(window: UIWindow, dependencies: Dependency) -> BaseCoordinator<UINavigationController> {
switch self {
case .news:
Expand Down
214 changes: 214 additions & 0 deletions FisherMan/Extensions/String+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
//
// String+Ext.swift
// FisherMan
//
// Created by Yura Granchenko on 21.01.2020.
// Copyright © 2020 GYS. All rights reserved.
//

import Foundation
import UIKit

extension String {

public var URL: Foundation.URL? {
return Foundation.URL(string: self as String)
}

public var fileURL: Foundation.URL? {
return Foundation.URL(fileURLWithPath: self as String)
}

public var smartURL: Foundation.URL? {
if isExistingFilePath {
return fileURL
} else {
return URL
}
}

public var isExistingFilePath: Bool {
if hasPrefix("http") {
return false
}
return FileManager.default.fileExists(atPath: self as String)
}

public var trim: String {
return trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}

fileprivate static let emailRegex = "(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&" +
"'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|" +
"\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9]" +
"(?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4]" +
"[0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-" +
"\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"

public var isValidEmail: Bool {
guard let predicate = try? NSRegularExpression(pattern: String.emailRegex,
options: []) else { return false }
return predicate.firstMatch(in: self,
options: [],
range: NSMakeRange(0, count - 1)) != nil
}

public var isValidPhone: Bool {
let phoneNumber = NSTextCheckingResult.CheckingType.phoneNumber.rawValue
guard let detector = try? NSDataDetector(types: phoneNumber) else { return false }

if let match = detector.matches(in: self as String,
options: [],
range: NSMakeRange(0, (self as String).count)).first?.phoneNumber {
return match == self as String
} else {
return false
}
}

public var URLQuery: [String: String] {

var parameters = [String: String]()
for pair in components(separatedBy: "&") {
let components = pair.components(separatedBy: "=")
if components.count == 2 {
parameters[components[0]] = components[1].removingPercentEncoding
} else {
continue
}
}
return parameters
}

private func clearPhoneNumber() -> String {
var phone = ""
for character in (self as String) {
if character == "+" || "0"..."9" ~= character {
phone.append(character)
}
}
return phone
}

public var ls: String {
let string = self as String
return Bundle.main.localizedString(forKey: string, value: string, table: nil)
}

private func randomString(length: Int) -> String {
let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

var result = ""

for _ in 0..<length {
let randomIndex = Int(arc4random_uniform(UInt32(characters.count)))
let characterIndex = index(startIndex, offsetBy: randomIndex)
result += String(characters[characterIndex])
}
return result
}

private var urlEscaped: String {
return self.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""
}

public func heightWithFont(_ font: UIFont, width: CGFloat) -> CGFloat {
if isEmpty { return 0.0 }
let size = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
let height = self.boundingRect(with: size,
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil).height
return ceil(height)
}

public var localized: String {
return localized(for: LanguageManager.shared.bundle)
}

public func localized(for bundle: Bundle) -> String {
return NSLocalizedString(self, bundle: bundle, comment: "")
}

public var numbers: String {
return String(filter { "0"..."9" ~= $0 })
}

public func removeWhitespacesPattern() -> String {
return components(separatedBy: .whitespaces).joined()
}

public func subString(by pattern: String) -> String? {
let regex = try? NSRegularExpression(pattern: pattern, options: [])
return regex?.matches(in: self, options: [], range: NSRange(location: 0, length: count)).map({
self[Range($0.range, in: self)!].toString()
}).first
}

public func removeSubstring(by pattern: String) -> String {
let regex = try? NSRegularExpression(pattern: pattern, options: [])
let output = regex?.stringByReplacingMatches(in: self,
options: [],
range: NSRange(location: 0, length: count),
withTemplate: "")
return output ?? ""
}

public func applyPatternOnNumbers(pattern: String, replacmentCharacter: Character) -> String {
var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
for index in 0 ..< pattern.count {
guard index < pureNumber.count else { return pureNumber }
let stringIndex = String.Index(encodedOffset: index)
let patternCharacter = pattern[stringIndex]
guard patternCharacter != replacmentCharacter else { continue }
pureNumber.insert(patternCharacter, at: stringIndex)
}
return pureNumber
}

public func applyPattern() -> String {
return applyPatternOnNumbers(pattern: "## ### ####",
replacmentCharacter: "#")
}

private func findIndexes(in string: String, isSearhing: Bool) -> [Int] {
var indexes = [Int]()
var searchStartIndex = startIndex
while startIndex < endIndex, let range = range(of: string,
options: .caseInsensitive,
range: searchStartIndex..<endIndex),
!range.isEmpty {
if !isSearhing && string.contains("Bit") {
let _index = index(range.upperBound, offsetBy: 0)
if _index.encodedOffset < self.count, self[_index] == "b" {
let index = distance(from: startIndex, to: range.lowerBound)
indexes.append(index)
}
} else {
let index = distance(from: startIndex, to: range.lowerBound)
indexes.append(index)
}
searchStartIndex = range.upperBound
}
return indexes
}

private var utfData: Data? {
return data(using: .utf8)
}

public var attributedHtmlString: NSAttributedString? {
guard let data = utfData else { return nil }
do { return try NSAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue ],
documentAttributes: nil)
} catch { return nil }
}
}

extension Hashable {
public func toString() -> String {
return "\(self)"
}
}
Loading

0 comments on commit 69fec5d

Please sign in to comment.