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

Feature/viewmodel layer #4

Merged
merged 7 commits into from
Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ target 'ZarinPal-Challenge' do
use_frameworks!
pod 'Alamofire'
pod 'RxSwift'
pod 'Kingfisher'
pod 'Kingfisher/SwiftUI'
pod 'RxAlamofire'
pod 'KeychainAccess'
pod 'AutoGraph', :git => 'https://github.com/farshadmb/AutoGraph.git'
Expand Down
8 changes: 4 additions & 4 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ PODS:
- JSONValueRX (~> 7.0.0)
- JSONValueRX (7.0.0)
- KeychainAccess (4.2.0)
- Kingfisher (5.14.0):
- Kingfisher/Core (= 5.14.0)
- Kingfisher/Core (5.14.0)
- Kingfisher/SwiftUI (5.14.0):
- Kingfisher/Core
- RxAlamofire (5.3.2):
- RxAlamofire/Core (= 5.3.2)
- RxAlamofire/Core (5.3.2):
Expand All @@ -23,7 +23,7 @@ DEPENDENCIES:
- Alamofire
- AutoGraph (from `https://github.com/farshadmb/AutoGraph.git`)
- KeychainAccess
- Kingfisher
- Kingfisher/SwiftUI
- RxAlamofire
- RxBlocking
- RxSwift
Expand Down Expand Up @@ -60,6 +60,6 @@ SPEC CHECKSUMS:
RxSwift: 81470a2074fa8780320ea5fe4102807cb7118178
RxTest: 711632d5644dffbeb62c936a521b5b008a1e1faa

PODFILE CHECKSUM: 8c8454106c69153332fa9e0d04ba52fb91fec444
PODFILE CHECKSUM: 0ecdda1c6160f23eb1234f252627efb1eab92ee8

COCOAPODS: 1.9.3
56 changes: 54 additions & 2 deletions ZarinPal-Challenge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@
F8D2FA03249E04F50029FD63 /* XCGitHubUserRepositoryTestes.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA02249E04F50029FD63 /* XCGitHubUserRepositoryTestes.swift */; };
F8D2FA05249E1B260029FD63 /* UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA04249E1B260029FD63 /* UserProfile.swift */; };
F8D2FA07249E1EBF0029FD63 /* XCGitHubProfileRepositoriy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA06249E1EBF0029FD63 /* XCGitHubProfileRepositoriy.swift */; };
F8D2FA0A249E20620029FD63 /* AppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA09249E20620029FD63 /* AppViewModel.swift */; };
F8D2FA0C249E271C0029FD63 /* AppDIContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA0B249E271C0029FD63 /* AppDIContainer.swift */; };
F8D2FA0E249E2C0A0029FD63 /* AppContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA0D249E2C0A0029FD63 /* AppContainerView.swift */; };
F8D2FA10249E2F180029FD63 /* AuthenticationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA0F249E2F180029FD63 /* AuthenticationViewModel.swift */; };
F8D2FA12249E31950029FD63 /* UserRepositoryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA11249E31950029FD63 /* UserRepositoryListViewModel.swift */; };
F8D2FA14249E31C30029FD63 /* UserRepositoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA13249E31C30029FD63 /* UserRepositoryViewModel.swift */; };
F8D2FA16249E33A50029FD63 /* UIColor+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA15249E33A50029FD63 /* UIColor+Hex.swift */; };
F8D2FA19249E382F0029FD63 /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA18249E382F0029FD63 /* ActivityIndicatorView.swift */; };
F8D2FA1B249E64CD0029FD63 /* UserProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D2FA1A249E64CD0029FD63 /* UserProfileViewModel.swift */; };
F8E5888C2499A3070083BD93 /* UserRepositoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E5888B2499A3070083BD93 /* UserRepositoryDetailView.swift */; };
F8E5888E2499B3130083BD93 /* UserRepositoryBranchListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E5888D2499B3130083BD93 /* UserRepositoryBranchListView.swift */; };
F8E588902499B3290083BD93 /* UserRepositoryIssueListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E5888F2499B3290083BD93 /* UserRepositoryIssueListView.swift */; };
Expand Down Expand Up @@ -135,6 +144,15 @@
F8D2FA02249E04F50029FD63 /* XCGitHubUserRepositoryTestes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCGitHubUserRepositoryTestes.swift; sourceTree = "<group>"; };
F8D2FA04249E1B260029FD63 /* UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfile.swift; sourceTree = "<group>"; };
F8D2FA06249E1EBF0029FD63 /* XCGitHubProfileRepositoriy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCGitHubProfileRepositoriy.swift; sourceTree = "<group>"; };
F8D2FA09249E20620029FD63 /* AppViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppViewModel.swift; sourceTree = "<group>"; };
F8D2FA0B249E271C0029FD63 /* AppDIContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDIContainer.swift; sourceTree = "<group>"; };
F8D2FA0D249E2C0A0029FD63 /* AppContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppContainerView.swift; sourceTree = "<group>"; };
F8D2FA0F249E2F180029FD63 /* AuthenticationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationViewModel.swift; sourceTree = "<group>"; };
F8D2FA11249E31950029FD63 /* UserRepositoryListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRepositoryListViewModel.swift; sourceTree = "<group>"; };
F8D2FA13249E31C30029FD63 /* UserRepositoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRepositoryViewModel.swift; sourceTree = "<group>"; };
F8D2FA15249E33A50029FD63 /* UIColor+Hex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Hex.swift"; sourceTree = "<group>"; };
F8D2FA18249E382F0029FD63 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = "<group>"; };
F8D2FA1A249E64CD0029FD63 /* UserProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileViewModel.swift; sourceTree = "<group>"; };
F8E5888B2499A3070083BD93 /* UserRepositoryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRepositoryDetailView.swift; sourceTree = "<group>"; };
F8E5888D2499B3130083BD93 /* UserRepositoryBranchListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRepositoryBranchListView.swift; sourceTree = "<group>"; };
F8E5888F2499B3290083BD93 /* UserRepositoryIssueListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRepositoryIssueListView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -226,12 +244,13 @@
F82103B92499697B00B1A211 /* ZarinPal-Challenge */ = {
isa = PBXGroup;
children = (
F8D2F9FE249DFADF0029FD63 /* Utitlies */,
F85513C22499ED50006F309D /* Constant */,
F875B8D024996B420052C1DC /* Views */,
F8D2FA08249E202F0029FD63 /* ViewModels */,
F85513B92499E069006F309D /* Models */,
F86A2115249A476900C8AE69 /* Repositories */,
F85513B82499D136006F309D /* Service */,
F8D2F9FE249DFADF0029FD63 /* Utitlies */,
F85513C22499ED50006F309D /* Constant */,
F82103BA2499697B00B1A211 /* AppDelegate.swift */,
F82103C02499697D00B1A211 /* Assets.xcassets */,
F82103C82499697D00B1A211 /* Info.plist */,
Expand Down Expand Up @@ -360,6 +379,7 @@
F875B8D024996B420052C1DC /* Views */ = {
isa = PBXGroup;
children = (
F8D2FA17249E381D0029FD63 /* CustomView */,
F87C13F324997779002170B9 /* AuthenticationView.swift */,
F8C97436249989F800D6C0EF /* UserRepositoryListView.swift */,
F8C9743824998A0600D6C0EF /* UserRepositoryRowView.swift */,
Expand All @@ -368,6 +388,7 @@
F8E5888F2499B3290083BD93 /* UserRepositoryIssueListView.swift */,
F8E588912499B33F0083BD93 /* UserRepositoryPullRequestListView.swift */,
F84D0AC52499BD0600B88CA0 /* UserProfileView.swift */,
F8D2FA0D249E2C0A0029FD63 /* AppContainerView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -400,6 +421,8 @@
isa = PBXGroup;
children = (
F8D2F9FF249DFAF30029FD63 /* GitHubGraphQLFactory.swift */,
F8D2FA0B249E271C0029FD63 /* AppDIContainer.swift */,
F8D2FA15249E33A50029FD63 /* UIColor+Hex.swift */,
);
path = Utitlies;
sourceTree = "<group>";
Expand All @@ -413,6 +436,26 @@
path = RepositoriesTestes;
sourceTree = "<group>";
};
F8D2FA08249E202F0029FD63 /* ViewModels */ = {
isa = PBXGroup;
children = (
F8D2FA09249E20620029FD63 /* AppViewModel.swift */,
F8D2FA0F249E2F180029FD63 /* AuthenticationViewModel.swift */,
F8D2FA11249E31950029FD63 /* UserRepositoryListViewModel.swift */,
F8D2FA13249E31C30029FD63 /* UserRepositoryViewModel.swift */,
F8D2FA1A249E64CD0029FD63 /* UserProfileViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
};
F8D2FA17249E381D0029FD63 /* CustomView */ = {
isa = PBXGroup;
children = (
F8D2FA18249E382F0029FD63 /* ActivityIndicatorView.swift */,
);
path = CustomView;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -678,15 +721,20 @@
F85513BF2499E5F6006F309D /* IGraphQLQueryRequest.swift in Sources */,
F8C9743924998A0600D6C0EF /* UserRepositoryRowView.swift in Sources */,
F86A211C249A4C4200C8AE69 /* AuthenticationStatus.swift in Sources */,
F8D2FA12249E31950029FD63 /* UserRepositoryListViewModel.swift in Sources */,
F8D2FA05249E1B260029FD63 /* UserProfile.swift in Sources */,
F8E5888C2499A3070083BD93 /* UserRepositoryDetailView.swift in Sources */,
F85513D3249A126D006F309D /* AuthenticationService+Authentictor.swift in Sources */,
F85513CB249A04FD006F309D /* Storage.swift in Sources */,
F8D2FA14249E31C30029FD63 /* UserRepositoryViewModel.swift in Sources */,
F85513C12499EC0C006F309D /* APIClientService.swift in Sources */,
F85513D5249A1436006F309D /* Authentication.swift in Sources */,
F85513C42499ED5B006F309D /* AppConfig.swift in Sources */,
F8D2FA1B249E64CD0029FD63 /* UserProfileViewModel.swift in Sources */,
F82103BB2499697B00B1A211 /* AppDelegate.swift in Sources */,
F8D2FA0C249E271C0029FD63 /* AppDIContainer.swift in Sources */,
F86A2119249A498C00C8AE69 /* AuthenticationRepository.swift in Sources */,
F8D2FA0E249E2C0A0029FD63 /* AppContainerView.swift in Sources */,
F85513D1249A1080006F309D /* OAuthCredential+AuthenticationCredential.swift in Sources */,
F80E3127249A54440092000F /* GitHubUserProfileRepository.swift in Sources */,
F8D2F9F7249DE3620029FD63 /* Respositories.swift in Sources */,
Expand All @@ -696,13 +744,17 @@
F85513D7249A162D006F309D /* AppClientCredential.swift in Sources */,
F8D2F9F5249DE30B0029FD63 /* Pagination.swift in Sources */,
F8D2FA00249DFAF30029FD63 /* GitHubGraphQLFactory.swift in Sources */,
F8D2FA16249E33A50029FD63 /* UIColor+Hex.swift in Sources */,
F8E5888E2499B3130083BD93 /* UserRepositoryBranchListView.swift in Sources */,
F87C13F424997779002170B9 /* AuthenticationView.swift in Sources */,
F85513CD249A06E9006F309D /* KeyChainStorage.swift in Sources */,
F85513C9249A04F4006F309D /* Storable.swift in Sources */,
F8D2FA0A249E20620029FD63 /* AppViewModel.swift in Sources */,
F85513CF249A0F7F006F309D /* OAuthCredential.swift in Sources */,
F85513C62499F71B006F309D /* INetworkServiceEndpoint.swift in Sources */,
F80E3125249A51040092000F /* GitHubUserRepository.swift in Sources */,
F8D2FA19249E382F0029FD63 /* ActivityIndicatorView.swift in Sources */,
F8D2FA10249E2F180029FD63 /* AuthenticationViewModel.swift in Sources */,
F85513BD2499E566006F309D /* NetworkService.swift in Sources */,
F86A2117249A480A00C8AE69 /* BaseRepository.swift in Sources */,
F8CF16C524998FBD00464F90 /* RepositoryData.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion ZarinPal-Challenge/Models/Pagination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

struct Pagination : Decodable {

let endCursor: String
let startCursor: String?
let hasNextPage: Bool
let hasPreviousPage: Bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import UIKit

/// <#Description#>
protocol AuthenticationUseCase : class {

func authorizeUser() -> Observable<URL?>

func fetchCredential(with code: String) -> Observable<Bool>

func authorizeStatus() -> Observable<AuthenticationStatus>

}

final class AuthenticationRepository : BaseRepository, AuthenticationUseCase {

var authorizeStatus: Observable<AuthenticationStatus> {
var currentAuthorizeStatus: Observable<AuthenticationStatus> {
return authenticator?
.isAuthenticated
.map({ $0 ? AuthenticationStatus.authorized : .notAuthorized}) ?? .just(.unknown)
Expand All @@ -39,6 +41,12 @@ final class AuthenticationRepository : BaseRepository, AuthenticationUseCase {
}


////////////////////////////////////////////////////////////////
//MARK:-
//MARK:UseCases implementation.
//MARK:-
////////////////////////////////////////////////////////////////

func fetchCredential(with code: String) -> Observable<Bool> {
guard let authenticator = authenticator else {
return .just(false)
Expand All @@ -55,5 +63,9 @@ final class AuthenticationRepository : BaseRepository, AuthenticationUseCase {

return authenticator.buildAuthentication(credential: clientCredential)
}


func authorizeStatus() -> Observable<AuthenticationStatus> {
return self.currentAuthorizeStatus
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ final class GitHubUserRepository : BaseRepository, GitHubUserRepositoryUseCases
self.pageSize = last

return fetchRespositories(last:pageSize,
cursor: lastPage?.endCursor,
cursor: lastPage?.startCursor,
networkService: network)

}
Expand All @@ -59,7 +59,7 @@ final class GitHubUserRepository : BaseRepository, GitHubUserRepositoryUseCases
}

return fetchRespositories(last:self.pageSize,
cursor: lastPage.endCursor,
cursor: lastPage.startCursor,
networkService: network)
}

Expand Down
27 changes: 7 additions & 20 deletions ZarinPal-Challenge/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

let authentication = AuthenticationService()


let appViewModel = AppViewModel(authentication: AppDIContainer.authenticationUseCases)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
Expand All @@ -24,22 +25,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {

print(#function,connectionOptions)

var items = [RepositoryData]()
let fakeBranche = RepositoryData.BranchData(title: "Branch", createdDate: Date(timeIntervalSinceNow: -100), updateDate: Date())
let fakeIssue = RepositoryData.IssueData(number: "1", title: "Issue", date: Date(timeIntervalSinceNow: -50), description: "Issue Description")
let fakePR = RepositoryData.PullRequestData(number: "#2", title: "Issue", date: Date(timeIntervalSinceNow: -40), description: "PR Description")

for i in 0...20 {

var respository = RepositoryData(title: "Repo Name \(i)", description: i % 2 == 0 ? nil : "Repo Desc")
respository.branches = i % 3 == 0 ? Array(repeating:fakeBranche , count: 5) : []
respository.pullRequests = i % 4 == 0 ? Array(repeating: fakePR, count: 5) : []
respository.issues = i % 5 == 0 ? Array(repeating: fakeIssue, count: 5) : []

items.append(respository)
}
// AppDIContainer.secureStorage.clearAll()

let contentView = UserRepositoryListView(items: items)

let contentView = AppContainerView(viewModel: appViewModel)

// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
Expand All @@ -49,9 +39,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window.makeKeyAndVisible()
}

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {
_ = self.authentication.buildAuthentication(credential: AppConfig.clientCredetianl)
}
}

func sceneDidDisconnect(_ scene: UIScene) {
Expand Down Expand Up @@ -100,7 +87,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
.rootViewController?.present(alert, animated: true, completion: nil)

}else if let code = queryItems?.first(where: { $0.name == "code"}), let codeValue = code.value {
print("accessCode =>",codeValue)
appViewModel.send(event: .recieved(code: codeValue))
}
}

Expand Down
12 changes: 12 additions & 0 deletions ZarinPal-Challenge/Service/Storage/KeyChainStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,16 @@ struct KeyChainStorage: SecureStorage {

}

@discardableResult
func clearAll() -> Bool {
do {
try keychain.synchronizable(true)
.removeAll()
return true
}catch let error {
print("error \(error)")
return false
}
}

}
3 changes: 3 additions & 0 deletions ZarinPal-Challenge/Service/Storage/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Foundation

protocol Storage {

@discardableResult
/// <#Description#>
/// - Parameters:
/// - object: <#object description#>
Expand All @@ -22,6 +23,8 @@ protocol Storage {
/// - forKey: <#forKey description#>
func retreive<T: Storable>(type:T.Type, forKey key: String) -> T?

@discardableResult
func clearAll() -> Bool
}

protocol SecureStorage: Storage {
Expand Down
Loading