Skip to content

Commit 7a6f386

Browse files
authored
Merge pull request #2 from rcaos/feature-login
Feature login
2 parents 0e23279 + edea6e0 commit 7a6f386

File tree

82 files changed

+3321
-194
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+3321
-194
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
//
2+
// AccountFlow.swift
3+
// TVToday
4+
//
5+
// Created by Jeans Ruiz on 6/19/20.
6+
// Copyright © 2020 Jeans. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import RxFlow
11+
12+
public class AccountFlow: Flow {
13+
14+
public struct Dependencies {
15+
let apiDataTransferService: DataTransferService
16+
let appConfigurations: AppConfigurations
17+
}
18+
19+
private let dependencies: Dependencies
20+
21+
public var root: Presentable {
22+
return self.rootViewController
23+
}
24+
25+
private lazy var rootViewController: UINavigationController = {
26+
let navigationController = UINavigationController()
27+
return navigationController
28+
}()
29+
30+
// MARK: - Repositories
31+
32+
private lazy var showsRepository: TVShowsRepository = {
33+
return DefaultTVShowsRepository(
34+
dataTransferService: dependencies.apiDataTransferService,
35+
basePath: dependencies.appConfigurations.imagesBaseURL)
36+
}()
37+
38+
private lazy var authRepository: AuthRepository = {
39+
return DefaultAuthRepository(dataTransferService: dependencies.apiDataTransferService)
40+
}()
41+
42+
private lazy var accountRepository: AccountRepository = {
43+
return DefaultAccountRepository(dataTransferService: dependencies.apiDataTransferService)
44+
}()
45+
46+
private lazy var keychainRepository: KeychainRepository = {
47+
return DefaultKeychainRepository()
48+
}()
49+
50+
// MARK: - Life Cycle
51+
52+
public init(dependencies: Dependencies) {
53+
self.dependencies = dependencies
54+
}
55+
56+
// MARK: - Navigation
57+
58+
public func navigate(to step: Step) -> FlowContributors {
59+
switch step {
60+
case AccountStep.accountFeatureInit:
61+
return navigateToAccountFeature()
62+
63+
case AccountStep.signInIsPicked(let url, let delegate):
64+
return navigateToAuthPermission(url: url, delegate: delegate)
65+
66+
case AccountStep.authorizationIsComplete:
67+
self.rootViewController.presentedViewController?.dismiss(animated: true)
68+
return .none
69+
70+
case AccountStep.favoritesIsPicked:
71+
return navigateToFavorites()
72+
73+
case AccountStep.watchListIsPicked:
74+
return navigateToWatchList()
75+
76+
case SearchStep.showIsPicked(let id):
77+
return navigateToShowDetailScreen(with: id)
78+
79+
default:
80+
return .none
81+
}
82+
}
83+
84+
fileprivate func navigateToAccountFeature() -> FlowContributors {
85+
86+
let signViewModel = SignInViewModel()
87+
let signInViewController = SignInViewController.create(with: signViewModel)
88+
89+
let profileViewModel = ProfileViewModel()
90+
let profileViewController = ProfileViewController.create(with: profileViewModel)
91+
92+
let accountViewModel = AccountViewModel(requestToken: makeCreateTokenUseCase(),
93+
createNewSession: makeCreateSessionUseCase(),
94+
fetchAccountDetails: makeFetchAccountDetailsUseCase(),
95+
fetchLoggedUser: makeFetchLoggedUserUseCase(),
96+
deleteLoguedUser: makeDeleteLoguedUserUseCase(),
97+
signInViewModel: signViewModel,
98+
profileViewMoel: profileViewModel)
99+
signViewModel.delegate = accountViewModel
100+
profileViewModel.delegate = accountViewModel
101+
let accountViewController = AccountViewController.create(with: accountViewModel,
102+
signInViewController: signInViewController,
103+
profileViewController: profileViewController)
104+
105+
rootViewController.pushViewController(accountViewController, animated: true)
106+
107+
return .one(flowContributor: .contribute(
108+
withNextPresentable: accountViewController, withNextStepper: accountViewModel))
109+
}
110+
111+
fileprivate func navigateToAuthPermission(url: URL, delegate: AuthPermissionViewModelDelegate?) -> FlowContributors {
112+
let authViewModel = AuthPermissionViewModel(url: url)
113+
authViewModel.delegate = delegate
114+
let authViewController = AuthPermissionViewController.create(with: authViewModel)
115+
116+
let navController = UINavigationController(rootViewController: authViewController)
117+
118+
rootViewController.present(navController, animated: true)
119+
120+
return .none
121+
}
122+
123+
// MARK: - Navigate to Favorites User
124+
125+
fileprivate func navigateToFavorites() -> FlowContributors {
126+
let viewModel = TVShowListViewModel(filter: .favorites(userId: 0, sessionId: ""),
127+
fetchTVShowsUseCase: makeShowListUseCase())
128+
let showList = TVShowListViewController.create(with: viewModel)
129+
130+
rootViewController.pushViewController(showList, animated: true)
131+
132+
return .one(flowContributor: .contribute(
133+
withNextPresentable: showList, withNextStepper: viewModel))
134+
}
135+
136+
// MARK: - Navigate to WatchList User
137+
138+
fileprivate func navigateToWatchList() -> FlowContributors {
139+
let viewModel = TVShowListViewModel(filter: .watchList(userId: 0, sessionId: ""),
140+
fetchTVShowsUseCase: makeShowListUseCase())
141+
let showList = TVShowListViewController.create(with: viewModel)
142+
143+
rootViewController.pushViewController(showList, animated: true)
144+
145+
return .one(flowContributor: .contribute(
146+
withNextPresentable: showList, withNextStepper: viewModel))
147+
}
148+
149+
// MARK: - Navigate to Detail TVShow
150+
151+
fileprivate func navigateToShowDetailScreen(with id: Int) -> FlowContributors {
152+
let detailShowFlow = TVShowDetailFlow(rootViewController: rootViewController,
153+
dependencies: TVShowDetailFlow.Dependencies(
154+
apiDataTransferService: dependencies.apiDataTransferService,
155+
appConfigurations: dependencies.appConfigurations))
156+
157+
return .one(flowContributor: .contribute(
158+
withNextPresentable: detailShowFlow,
159+
withNextStepper:
160+
OneStepper(withSingleStep:
161+
ShowDetailsStep.showDetailsIsRequired(withId: id))))
162+
}
163+
164+
// MARK: - Uses Cases
165+
166+
private func makeCreateTokenUseCase() -> CreateTokenUseCase {
167+
return DefaultCreateTokenUseCase(authRepository: authRepository, keyChainRepository: keychainRepository)
168+
}
169+
170+
private func makeCreateSessionUseCase() -> CreateSessionUseCase {
171+
return DefaultCreateSessionUseCase(authRepository: authRepository, keyChainRepository: keychainRepository)
172+
}
173+
174+
private func makeFetchAccountDetailsUseCase() -> FetchAccountDetailsUseCase {
175+
return DefaultFetchAccountDetailsUseCase(accountRepository: accountRepository, keychainRepository: keychainRepository)
176+
}
177+
178+
private func makeFetchLoggedUserUseCase() -> FetchLoggedUser {
179+
return DefaultFetchLoggedUser(keychainRepository: keychainRepository)
180+
}
181+
182+
private func makeDeleteLoguedUserUseCase() -> DeleteLoguedUserUseCase {
183+
return DefaultDeleteLoguedUserUseCase(keychainRepository: keychainRepository)
184+
}
185+
186+
fileprivate func makeShowListUseCase() -> FetchTVShowsUseCase {
187+
return DefaultUserFetchShowsUserUseCase(tvShowsRepository: showsRepository,
188+
keychainRepository: keychainRepository)
189+
}
190+
191+
}
192+
193+
// MARK: - Steps
194+
195+
enum AccountStep: Step {
196+
197+
case
198+
199+
accountFeatureInit,
200+
201+
signIsShow,
202+
203+
profileIsShow,
204+
205+
signInIsPicked(url: URL, delegate: AuthPermissionViewModelDelegate?),
206+
207+
authorizationIsComplete,
208+
209+
favoritesIsPicked,
210+
211+
watchListIsPicked
212+
}

MyMovies/Application/DIContainer/SearchFlow.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public class SearchFlow: Flow {
2727
return navigationController
2828
}()
2929

30-
// Repositories
30+
// MARK: - Repositories
31+
3132
private lazy var showsRepository: TVShowsRepository = {
3233
return DefaultTVShowsRepository(
3334
dataTransferService: dependencies.apiDataTransferService,
@@ -75,7 +76,8 @@ public class SearchFlow: Flow {
7576
}
7677

7778
fileprivate func navigateToGenreListScreen(with id: Int) -> FlowContributors {
78-
let viewModel = TVShowListViewModel(genreId: id, fetchTVShowsUseCase: makeShowListUseCase())
79+
let viewModel = TVShowListViewModel(filter: .byGenre(genreId: id),
80+
fetchTVShowsUseCase: makeShowListUseCase())
7981
let showList = TVShowListViewController.create(with: viewModel)
8082

8183
rootViewController.pushViewController(showList, animated: true)

MyMovies/Application/DIContainer/SignedFlow.swift

+23-13
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,29 @@ public class SignedFlow: Flow {
6060
apiDataTransferService: dependencies.apiDataTransferService,
6161
appConfigurations: dependencies.appConfigurations) )
6262

63+
let accountFlow = AccountFlow(dependencies:
64+
AccountFlow.Dependencies(apiDataTransferService: dependencies.apiDataTransferService,
65+
appConfigurations: dependencies.appConfigurations))
66+
6367
Flows.whenReady(
6468
flow1: airingTodayFlow,
6569
flow2: popularFlow,
66-
flow3: searchFlow) { (airingTodayRoot: UINavigationController, popularRoot: UINavigationController, searchRoot: UINavigationController) in
67-
68-
let airingTodayTabBarItem = UITabBarItem(title: "Today", image: UIImage(named: "calendar"), tag: 0)
69-
airingTodayRoot.tabBarItem = airingTodayTabBarItem
70-
71-
let popularTabBarItem = UITabBarItem(title: "Popular", image: UIImage(named: "popular"), tag: 1)
72-
popularRoot.tabBarItem = popularTabBarItem
73-
74-
let searchTabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 2)
75-
searchRoot.tabBarItem = searchTabBarItem
76-
77-
self.rootViewController.setViewControllers([airingTodayRoot, popularRoot, searchRoot], animated: true)
70+
flow3: searchFlow,
71+
flow4: accountFlow) { (airingTodayRoot: UINavigationController, popularRoot: UINavigationController, searchRoot: UINavigationController, accountRoot: UINavigationController) in
72+
73+
let airingTodayTabBarItem = UITabBarItem(title: "Today", image: UIImage(named: "calendar"), tag: 0)
74+
airingTodayRoot.tabBarItem = airingTodayTabBarItem
75+
76+
let popularTabBarItem = UITabBarItem(title: "Popular", image: UIImage(named: "popular"), tag: 1)
77+
popularRoot.tabBarItem = popularTabBarItem
78+
79+
let searchTabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 2)
80+
searchRoot.tabBarItem = searchTabBarItem
81+
82+
let accountTabBarItem = UITabBarItem(title: "Account", image: UIImage(named: "accountTab"), tag: 3)
83+
accountRoot.tabBarItem = accountTabBarItem
84+
85+
self.rootViewController.setViewControllers([airingTodayRoot, popularRoot, searchRoot, accountRoot], animated: true)
7886
}
7987

8088
return .multiple(flowContributors: [
@@ -83,7 +91,9 @@ public class SignedFlow: Flow {
8391
.contribute(withNextPresentable: popularFlow, withNextStepper:
8492
OneStepper(withSingleStep: PopularStep.popularFeatureInit)),
8593
.contribute(withNextPresentable: searchFlow, withNextStepper:
86-
OneStepper(withSingleStep: SearchStep.searchFeatureInit))
94+
OneStepper(withSingleStep: SearchStep.searchFeatureInit)),
95+
.contribute(withNextPresentable: accountFlow, withNextStepper:
96+
OneStepper(withSingleStep: AccountStep.accountFeatureInit))
8797
])
8898

8999
}

MyMovies/Application/DIContainer/TVShowDetailFlow.swift

+38-5
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ public class TVShowDetailFlow: Flow {
2424

2525
private var rootViewController: UIViewController!
2626

27-
// Repositories
28-
private lazy var showDetailsRepository: TVShowDetailsRepository = {
29-
return DefaultTVShowDetailsRepository(
27+
// MARK: - Repositories
28+
29+
private lazy var tvShowsRepository: TVShowsRepository = {
30+
return DefaultTVShowsRepository(
3031
dataTransferService: dependencies.apiDataTransferService,
3132
basePath: dependencies.appConfigurations.imagesBaseURL)
3233
}()
@@ -37,6 +38,14 @@ public class TVShowDetailFlow: Flow {
3738
basePath: dependencies.appConfigurations.imagesBaseURL)
3839
}()
3940

41+
private lazy var accountRepository: AccountRepository = {
42+
return DefaultAccountRepository(dataTransferService: dependencies.apiDataTransferService)
43+
}()
44+
45+
private lazy var keychainRepository: KeychainRepository = {
46+
return DefaultKeychainRepository()
47+
}()
48+
4049
// MARK: - Life Cycle
4150

4251
public init(rootViewController: UIViewController, dependencies: Dependencies) {
@@ -61,7 +70,12 @@ public class TVShowDetailFlow: Flow {
6170
}
6271

6372
fileprivate func showDetailsFeature(with id: Int) -> FlowContributors {
64-
let viewModel = TVShowDetailViewModel(id, fetchDetailShowUseCase: makeFetchShowDetailsUseCase())
73+
let viewModel = TVShowDetailViewModel(id,
74+
fetchLoggedUser: makeFetchLoggedUserUseCase(),
75+
fetchDetailShowUseCase: makeFetchShowDetailsUseCase(),
76+
fetchTvShowState: makeTVAccountStatesUseCase(),
77+
markAsFavoriteUseCase: makeMarkAsFavoriteUseCase(),
78+
saveToWatchListUseCase: makeSaveToWatchListUseCase())
6579
let detailVC = TVShowDetailViewController.create(with: viewModel)
6680

6781
if let navigationVC = rootViewController as? UINavigationController {
@@ -94,12 +108,31 @@ public class TVShowDetailFlow: Flow {
94108
// MARK: - Uses Cases
95109

96110
private func makeFetchShowDetailsUseCase() -> FetchTVShowDetailsUseCase {
97-
return DefaultFetchTVShowDetailsUseCase(tvShowDetailsRepository: showDetailsRepository)
111+
return DefaultFetchTVShowDetailsUseCase(tvShowsRepository: tvShowsRepository)
98112
}
99113

100114
private func makeFetchEpisodesUseCase() -> FetchEpisodesUseCase {
101115
return DefaultFetchEpisodesUseCase(episodesRepository: episodesRepository)
102116
}
117+
118+
private func makeMarkAsFavoriteUseCase() -> MarkAsFavoriteUseCase {
119+
return DefaultMarkAsFavoriteUseCase(accountRepository: accountRepository,
120+
keychainRepository: keychainRepository)
121+
}
122+
123+
private func makeSaveToWatchListUseCase() -> SaveToWatchListUseCase {
124+
return DefaultSaveToWatchListUseCase(accountRepository: accountRepository,
125+
keychainRepository: keychainRepository)
126+
}
127+
128+
private func makeTVAccountStatesUseCase() -> FetchTVAccountStates {
129+
return DefaultFetchTVAccountStates(tvShowsRepository: tvShowsRepository,
130+
keychainRepository: keychainRepository)
131+
}
132+
133+
private func makeFetchLoggedUserUseCase() -> FetchLoggedUser {
134+
return DefaultFetchLoggedUser(keychainRepository: keychainRepository)
135+
}
103136
}
104137

105138
public enum ShowDetailsStep: Step {

0 commit comments

Comments
 (0)