From 5b043b144565e5b514b7afe018091217d68ef13b Mon Sep 17 00:00:00 2001 From: Kristian Rusyn Date: Thu, 26 May 2022 17:58:37 +0200 Subject: [PATCH 1/2] Rework root flow to Coordinator patter, add base protocol/classes for that matter --- Trombi/Podfile.lock | 2 +- .../Differentiator/Differentiator-umbrella.h | 17 +---- .../Differentiator/Differentiator.modulemap | 7 +- .../Public/RxAtomic/RxAtomic-umbrella.h | 18 +---- .../Public/RxAtomic/RxAtomic.modulemap | 7 +- .../Headers/Public/RxCocoa/RxCocoa-umbrella.h | 23 +----- .../Headers/Public/RxCocoa/RxCocoa.modulemap | 7 +- .../RxDataSources/RxDataSources-umbrella.h | 17 +---- .../RxDataSources/RxDataSources.modulemap | 7 +- .../Headers/Public/RxSwift/RxSwift-umbrella.h | 17 +---- .../Headers/Public/RxSwift/RxSwift.modulemap | 7 +- .../Public/SDWebImage/SDWebImage-umbrella.h | 45 +----------- .../Public/SDWebImage/SDWebImage.modulemap | 7 +- Trombi/Pods/Manifest.lock | 2 +- Trombi/Pods/Pods.xcodeproj/project.pbxproj | 52 +++++++------ Trombi/Trombi.xcodeproj/project.pbxproj | 56 +++++++++++++- Trombi/Trombi/Application/AppDelegate.swift | 36 ++++++--- .../Application/ApplicationCoordinator.swift | 58 +++++++++++++++ .../Application/Base.lproj/Main.storyboard | 52 +------------ .../Application/CoordinatorFactory.swift | 13 ++++ .../Coordinator/MainTabbarCoordinator.swift | 13 ++++ .../MainTabBar/MainTabBarViewController.swift | 40 +++++----- .../Modules/Splash/SplashViewController.swift | 73 ++++++++++++------- .../Modules/Splash/SplashViewController.xib | 55 ++++++++++++++ .../Trombi/Common/Architecture/DeepLink.swift | 15 ++++ .../Common/Architecture/Resultable.swift | 15 ++++ .../Architecture/RxBaseCoordinator.swift | 70 ++++++++++++++++++ .../Common/Extenstions/NSObject+Bundle.swift | 23 ++++++ .../Extenstions/UIViewController+xib.swift | 26 +++++++ 29 files changed, 481 insertions(+), 299 deletions(-) mode change 100644 => 120000 Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap mode change 100644 => 120000 Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h mode change 100644 => 120000 Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap create mode 100644 Trombi/Trombi/Application/ApplicationCoordinator.swift create mode 100644 Trombi/Trombi/Application/CoordinatorFactory.swift create mode 100644 Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift create mode 100644 Trombi/Trombi/Application/Modules/Splash/SplashViewController.xib create mode 100644 Trombi/Trombi/Common/Architecture/DeepLink.swift create mode 100644 Trombi/Trombi/Common/Architecture/Resultable.swift create mode 100644 Trombi/Trombi/Common/Architecture/RxBaseCoordinator.swift create mode 100644 Trombi/Trombi/Common/Extenstions/NSObject+Bundle.swift create mode 100644 Trombi/Trombi/Common/Extenstions/UIViewController+xib.swift diff --git a/Trombi/Podfile.lock b/Trombi/Podfile.lock index 1eb7319..5244053 100644 --- a/Trombi/Podfile.lock +++ b/Trombi/Podfile.lock @@ -38,4 +38,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4ad74b65c368390ff918f6de599d4fb669cb597 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h b/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h deleted file mode 100644 index bd5fb2e..0000000 --- a/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double DifferentiatorVersionNumber; -FOUNDATION_EXPORT const unsigned char DifferentiatorVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h b/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h new file mode 120000 index 0000000..617302e --- /dev/null +++ b/Trombi/Pods/Headers/Public/Differentiator/Differentiator-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/Differentiator/Differentiator-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap b/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap deleted file mode 100644 index 12f77d0..0000000 --- a/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module Differentiator { - umbrella header "Differentiator-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap b/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap new file mode 120000 index 0000000..5db53ca --- /dev/null +++ b/Trombi/Pods/Headers/Public/Differentiator/Differentiator.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/Differentiator/Differentiator.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h deleted file mode 100644 index 2a01588..0000000 --- a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "RxAtomic.h" - -FOUNDATION_EXPORT double RxAtomicVersionNumber; -FOUNDATION_EXPORT const unsigned char RxAtomicVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h new file mode 120000 index 0000000..45a0b8f --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/RxAtomic/RxAtomic-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap deleted file mode 100644 index 1b161dc..0000000 --- a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module RxAtomic { - umbrella header "RxAtomic-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap new file mode 120000 index 0000000..aaf143e --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxAtomic/RxAtomic.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/RxAtomic/RxAtomic.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h deleted file mode 100644 index 26f89e6..0000000 --- a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "RxCocoaRuntime.h" -#import "_RX.h" -#import "_RXDelegateProxy.h" -#import "_RXKVOObserver.h" -#import "_RXObjCRuntime.h" -#import "RxCocoa.h" - -FOUNDATION_EXPORT double RxCocoaVersionNumber; -FOUNDATION_EXPORT const unsigned char RxCocoaVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h new file mode 120000 index 0000000..e4cad2b --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/RxCocoa/RxCocoa-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap deleted file mode 100644 index 08c9d38..0000000 --- a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module RxCocoa { - umbrella header "RxCocoa-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap new file mode 120000 index 0000000..112f0d8 --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxCocoa/RxCocoa.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/RxCocoa/RxCocoa.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h deleted file mode 100644 index d7d3eca..0000000 --- a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double RxDataSourcesVersionNumber; -FOUNDATION_EXPORT const unsigned char RxDataSourcesVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h new file mode 120000 index 0000000..1187f63 --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/RxDataSources/RxDataSources-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap deleted file mode 100644 index 969f5ab..0000000 --- a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module RxDataSources { - umbrella header "RxDataSources-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap new file mode 120000 index 0000000..3247387 --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxDataSources/RxDataSources.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/RxDataSources/RxDataSources.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h b/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h deleted file mode 100644 index 9a27211..0000000 --- a/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double RxSwiftVersionNumber; -FOUNDATION_EXPORT const unsigned char RxSwiftVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h b/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h new file mode 120000 index 0000000..889c027 --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxSwift/RxSwift-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/RxSwift/RxSwift-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap b/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap deleted file mode 100644 index 79ce0b2..0000000 --- a/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module RxSwift { - umbrella header "RxSwift-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap b/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap new file mode 120000 index 0000000..aacf559 --- /dev/null +++ b/Trombi/Pods/Headers/Public/RxSwift/RxSwift.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/RxSwift/RxSwift.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h deleted file mode 100644 index 270cd72..0000000 --- a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "NSButton+WebCache.h" -#import "NSData+ImageContentType.h" -#import "NSImage+WebCache.h" -#import "SDAnimatedImageRep.h" -#import "SDImageCache.h" -#import "SDImageCacheConfig.h" -#import "SDWebImageCoder.h" -#import "SDWebImageCoderHelper.h" -#import "SDWebImageCodersManager.h" -#import "SDWebImageCompat.h" -#import "SDWebImageDownloader.h" -#import "SDWebImageDownloaderOperation.h" -#import "SDWebImageFrame.h" -#import "SDWebImageGIFCoder.h" -#import "SDWebImageImageIOCoder.h" -#import "SDWebImageManager.h" -#import "SDWebImageOperation.h" -#import "SDWebImagePrefetcher.h" -#import "SDWebImageTransition.h" -#import "UIButton+WebCache.h" -#import "UIImage+ForceDecode.h" -#import "UIImage+GIF.h" -#import "UIImage+MemoryCacheCost.h" -#import "UIImage+MultiFormat.h" -#import "UIImageView+HighlightedWebCache.h" -#import "UIImageView+WebCache.h" -#import "UIView+WebCache.h" -#import "UIView+WebCacheOperation.h" - -FOUNDATION_EXPORT double SDWebImageVersionNumber; -FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[]; - diff --git a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h new file mode 120000 index 0000000..9d58120 --- /dev/null +++ b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage-umbrella.h @@ -0,0 +1 @@ +../../../Target Support Files/SDWebImage/SDWebImage-umbrella.h \ No newline at end of file diff --git a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap deleted file mode 100644 index 94f6a48..0000000 --- a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module SDWebImage { - umbrella header "SDWebImage-umbrella.h" - - export * - module * { export * } -} diff --git a/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap new file mode 120000 index 0000000..cf14e11 --- /dev/null +++ b/Trombi/Pods/Headers/Public/SDWebImage/SDWebImage.modulemap @@ -0,0 +1 @@ +../../../Target Support Files/SDWebImage/SDWebImage.modulemap \ No newline at end of file diff --git a/Trombi/Pods/Manifest.lock b/Trombi/Pods/Manifest.lock index 1eb7319..5244053 100644 --- a/Trombi/Pods/Manifest.lock +++ b/Trombi/Pods/Manifest.lock @@ -38,4 +38,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e4ad74b65c368390ff918f6de599d4fb669cb597 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/Trombi/Pods/Pods.xcodeproj/project.pbxproj b/Trombi/Pods/Pods.xcodeproj/project.pbxproj index ce4436e..c17ad0c 100644 --- a/Trombi/Pods/Pods.xcodeproj/project.pbxproj +++ b/Trombi/Pods/Pods.xcodeproj/project.pbxproj @@ -473,7 +473,7 @@ 042CE40BC106E9CE84E4059BEA452FBD /* UIImage+ForceDecode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+ForceDecode.h"; path = "SDWebImage/UIImage+ForceDecode.h"; sourceTree = ""; }; 04F9EAB46A54BB6E2AA928550B91C518 /* HistoricalScheduler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HistoricalScheduler.swift; path = RxSwift/Schedulers/HistoricalScheduler.swift; sourceTree = ""; }; 05959645E6230ECDE06B35679A20EB1B /* Platform.Darwin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Platform.Darwin.swift; path = Platform/Platform.Darwin.swift; sourceTree = ""; }; - 05FD55CFBD31B3E24D1A29D060BEF8AB /* libPods-Trombi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Trombi.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 05FD55CFBD31B3E24D1A29D060BEF8AB /* Pods-Trombi */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "Pods-Trombi"; path = "libPods-Trombi.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 064B03C467068E49FC111532F7D0B197 /* Differentiator-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Differentiator-prefix.pch"; sourceTree = ""; }; 06CFF08C74EC73B5FE96DBA79D3A52F9 /* RxCollectionViewDelegateProxy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RxCollectionViewDelegateProxy.swift; path = RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift; sourceTree = ""; }; 077C9B1844B67B29BACAF6EB2DC2D605 /* Range.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Range.swift; path = RxSwift/Observables/Range.swift; sourceTree = ""; }; @@ -630,7 +630,7 @@ 662E056BEBCD5F6908506AF79A5D9B52 /* SwitchIfEmpty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwitchIfEmpty.swift; path = RxSwift/Observables/SwitchIfEmpty.swift; sourceTree = ""; }; 6685240ED81941C34C0E0FED4FABC10D /* Do.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Do.swift; path = RxSwift/Observables/Do.swift; sourceTree = ""; }; 66ED29CAA6A011F42290D61ABB65AE5B /* AddRef.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AddRef.swift; path = RxSwift/Observables/AddRef.swift; sourceTree = ""; }; - 692F92D73EC27270EA9CC9575C3E65B6 /* libRxDataSources.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRxDataSources.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 692F92D73EC27270EA9CC9575C3E65B6 /* RxDataSources */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = RxDataSources; path = libRxDataSources.a; sourceTree = BUILT_PRODUCTS_DIR; }; 6A8FC2442AA99B1F8FF286912C1B758A /* Debounce.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Debounce.swift; path = RxSwift/Observables/Debounce.swift; sourceTree = ""; }; 6B31A2D6A501BF8F5C828B6281C95184 /* Queue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = Platform/DataStructures/Queue.swift; sourceTree = ""; }; 6B683EE824B67DA041BEDB5DC2EE78C4 /* NSObject+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+Rx.swift"; path = "RxCocoa/Foundation/NSObject+Rx.swift"; sourceTree = ""; }; @@ -638,7 +638,7 @@ 6C7CB7825CA908010A56E40E96836D2A /* RxAtomic-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "RxAtomic-dummy.m"; sourceTree = ""; }; 6DFDDACD92C4E04AEC8BC40938F91E4E /* LockOwnerType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LockOwnerType.swift; path = RxSwift/Concurrency/LockOwnerType.swift; sourceTree = ""; }; 6E5F7890402232CC475DA1EABA73FEBC /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/SDImageCache.h; sourceTree = ""; }; - 6EA739CDE8B456E2241966AE0163BC75 /* RxAtomic.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = RxAtomic.c; path = RxAtomic/RxAtomic.c; sourceTree = ""; }; + 6EA739CDE8B456E2241966AE0163BC75 /* RxAtomic.c */ = {isa = PBXFileReference; includeInIndex = 1; name = RxAtomic.c; path = RxAtomic/RxAtomic.c; sourceTree = ""; }; 6F6FC7A363D83DEF0D00EE2D4CAF2687 /* UIRefreshControl+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIRefreshControl+Rx.swift"; path = "RxCocoa/iOS/UIRefreshControl+Rx.swift"; sourceTree = ""; }; 7028016FEBEAC24B08686B59916B45D0 /* Pods-Trombi-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Trombi-dummy.m"; sourceTree = ""; }; 70D3D0770F735870D7445F842EE76B89 /* VirtualTimeScheduler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VirtualTimeScheduler.swift; path = RxSwift/Schedulers/VirtualTimeScheduler.swift; sourceTree = ""; }; @@ -663,7 +663,7 @@ 7C301F9ED28A0896556E113958A63BE3 /* PriorityQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PriorityQueue.swift; path = Platform/DataStructures/PriorityQueue.swift; sourceTree = ""; }; 7C3AB381DD504D87E21FD6093F7238FB /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = RxSwift/Observables/Error.swift; sourceTree = ""; }; 7F563C3D678AA7C96250E466B5F15FCD /* RetryWhen.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RetryWhen.swift; path = RxSwift/Observables/RetryWhen.swift; sourceTree = ""; }; - 809C5FAB588354C9BA37DC3EAB8CB45C /* libRxSwift.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRxSwift.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 809C5FAB588354C9BA37DC3EAB8CB45C /* RxSwift */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = RxSwift; path = libRxSwift.a; sourceTree = BUILT_PRODUCTS_DIR; }; 81D58971BD2E12336252B8B14615E5A6 /* UIImageView+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIImageView+Rx.swift"; path = "RxCocoa/iOS/UIImageView+Rx.swift"; sourceTree = ""; }; 81D9C2D86FA62AD12EEEAAE2D201B21E /* String+IdentifiableType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+IdentifiableType.swift"; path = "Sources/RxDataSources/String+IdentifiableType.swift"; sourceTree = ""; }; 81FFDB12243C396A74475141911D89EB /* RefCountDisposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RefCountDisposable.swift; path = RxSwift/Disposables/RefCountDisposable.swift; sourceTree = ""; }; @@ -679,7 +679,7 @@ 880DC4BB96B233CF79271CF2B5046035 /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/SDWebImageDownloader.h; sourceTree = ""; }; 8922D59964E4C0871BE74DB61F78EE67 /* TakeUntil.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TakeUntil.swift; path = RxSwift/Observables/TakeUntil.swift; sourceTree = ""; }; 8ADBB4AC0775ABEAE5896A2231E15519 /* UILabel+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UILabel+Rx.swift"; path = "RxCocoa/iOS/UILabel+Rx.swift"; sourceTree = ""; }; - 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* libRxAtomic.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRxAtomic.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* RxAtomic */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = RxAtomic; path = libRxAtomic.a; sourceTree = BUILT_PRODUCTS_DIR; }; 8BF12E8235C562D04E924CF785838C2D /* UIImage+ForceDecode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+ForceDecode.m"; path = "SDWebImage/UIImage+ForceDecode.m"; sourceTree = ""; }; 8C255A2F3ECB49757D6DE964B2CB5AA9 /* Producer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Producer.swift; path = RxSwift/Observables/Producer.swift; sourceTree = ""; }; 8C52324A73D7CD0E3F36543FA020266C /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/UIImage+MultiFormat.m"; sourceTree = ""; }; @@ -705,7 +705,7 @@ 9C7C6C6016A55C122CA8513D32B4FE33 /* InfiniteSequence.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = InfiniteSequence.swift; path = Platform/DataStructures/InfiniteSequence.swift; sourceTree = ""; }; 9D3884B5F24C76B2E3EB49864D282F80 /* CurrentThreadScheduler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CurrentThreadScheduler.swift; path = RxSwift/Schedulers/CurrentThreadScheduler.swift; sourceTree = ""; }; 9D7EAE0BA7FC23095B238959C173F533 /* TailRecursiveSink.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TailRecursiveSink.swift; path = RxSwift/Observers/TailRecursiveSink.swift; sourceTree = ""; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9DBECBF9A57A0ED5545AD80B471E44F3 /* SwiftSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftSupport.swift; path = RxSwift/SwiftSupport/SwiftSupport.swift; sourceTree = ""; }; 9DDF79ECEA88D6A341A2D5F58BF961FB /* DisposeBag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DisposeBag.swift; path = RxSwift/Disposables/DisposeBag.swift; sourceTree = ""; }; 9F0F4B5D349045515073CF1EA231C79D /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/SDWebImageDownloader.m; sourceTree = ""; }; @@ -735,7 +735,7 @@ AE49BA4BB2B3737E0289E06DD8184697 /* Driver.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Driver.swift; path = RxCocoa/Traits/Driver/Driver.swift; sourceTree = ""; }; AE995D13217A4F3FB3CA9DABEE674A00 /* ScheduledDisposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScheduledDisposable.swift; path = RxSwift/Disposables/ScheduledDisposable.swift; sourceTree = ""; }; AFBF4B9895F4F1C25521D466DA26264D /* Concat.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Concat.swift; path = RxSwift/Observables/Concat.swift; sourceTree = ""; }; - B0B214D775196BA7CA8E17E53048A493 /* libSDWebImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDWebImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; + B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = SDWebImage; path = libSDWebImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; B10FAA358D2CA13315A7CC2E4BF0B815 /* AsyncLock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AsyncLock.swift; path = RxSwift/Concurrency/AsyncLock.swift; sourceTree = ""; }; B22F656D7823D76524CDE9DCC92434B0 /* NSView+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSView+Rx.swift"; path = "RxCocoa/macOS/NSView+Rx.swift"; sourceTree = ""; }; B2FF5D7A709B23268962D5AC6C9B56D7 /* RxCocoa-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "RxCocoa-dummy.m"; sourceTree = ""; }; @@ -760,7 +760,7 @@ BBD1FEF06520B7D662931D8F7A0231C8 /* ScheduledItemType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ScheduledItemType.swift; path = RxSwift/Schedulers/Internal/ScheduledItemType.swift; sourceTree = ""; }; BBFABCEB8E87CAA7528D9F54E232AC3C /* AtomicInt.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AtomicInt.swift; path = Platform/AtomicInt.swift; sourceTree = ""; }; BC214974955C5084D50F831AED07DD9C /* First.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = First.swift; path = RxSwift/Observables/First.swift; sourceTree = ""; }; - BC432FD48A5932251F1CAFBC4BF74894 /* libRxCocoa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRxCocoa.a; sourceTree = BUILT_PRODUCTS_DIR; }; + BC432FD48A5932251F1CAFBC4BF74894 /* RxCocoa */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = RxCocoa; path = libRxCocoa.a; sourceTree = BUILT_PRODUCTS_DIR; }; BCC91F368FB8436A8238957CB9FBCE03 /* Signal+Subscription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Signal+Subscription.swift"; path = "RxCocoa/Traits/Signal/Signal+Subscription.swift"; sourceTree = ""; }; BCDF513D34F232BB025FFCCB7C1EB088 /* DispatchQueue+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Extensions.swift"; path = "Platform/DispatchQueue+Extensions.swift"; sourceTree = ""; }; BCE77D71D618AAA1EE94D3B936B33985 /* TakeLast.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TakeLast.swift; path = RxSwift/Observables/TakeLast.swift; sourceTree = ""; }; @@ -810,7 +810,7 @@ D1B03E71B4900C5553977917E817F2F8 /* UITabBarController+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITabBarController+Rx.swift"; path = "RxCocoa/iOS/UITabBarController+Rx.swift"; sourceTree = ""; }; D1C715265D137952435CB9546409FF5F /* _RX.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = _RX.m; path = RxCocoa/Runtime/_RX.m; sourceTree = ""; }; D3C6EC620DBBCB67B16BAF156C407417 /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = RxSwift/Observables/Optional.swift; sourceTree = ""; }; - D51C3D0C53D23B97B032E3BDD4F82C82 /* libDifferentiator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDifferentiator.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D51C3D0C53D23B97B032E3BDD4F82C82 /* Differentiator */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = Differentiator; path = libDifferentiator.a; sourceTree = BUILT_PRODUCTS_DIR; }; D58CDBB4FDB03FEFCEF6A7698B52E58C /* UIWebView+Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIWebView+Rx.swift"; path = "RxCocoa/iOS/UIWebView+Rx.swift"; sourceTree = ""; }; D5961CEA2F034FF755AE934D6142D166 /* RxAtomic.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = RxAtomic.modulemap; sourceTree = ""; }; D753B8CACF58B2BA86791E6A9759F376 /* Rx.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Rx.swift; path = RxSwift/Rx.swift; sourceTree = ""; }; @@ -968,6 +968,7 @@ BAEE4D941D8CE7DA9084F4E6D8AE873C /* RxAtomic.h */, 4B5031C05629D34ADBD422E20095484F /* Support Files */, ); + name = RxAtomic; path = RxAtomic; sourceTree = ""; }; @@ -1020,6 +1021,7 @@ 4C76EC3273D1289BB76ABFC96FF97688 /* ViewTransition.swift */, CC910765EF0FB9A2FDF83DA110163D38 /* Support Files */, ); + name = RxDataSources; path = RxDataSources; sourceTree = ""; }; @@ -1178,6 +1180,7 @@ 60A1793CE989F2B488FE11F8840C6552 /* Zip+Collection.swift */, A6B020E6DBE054923F69B657BE208A7D /* Support Files */, ); + name = RxSwift; path = RxSwift; sourceTree = ""; }; @@ -1198,6 +1201,7 @@ 29BB56913C6393658BE86A459FC5D525 /* Utilities.swift */, 0FC970FB39FD66070AA88ABBAADD1056 /* Support Files */, ); + name = Differentiator; path = Differentiator; sourceTree = ""; }; @@ -1290,6 +1294,7 @@ 9E92B892E6177D07A7F08246CC17F71B /* Core */, FD72EDEB48C38AEEA73E7F6259BF661D /* Support Files */, ); + name = SDWebImage; path = SDWebImage; sourceTree = ""; }; @@ -1424,6 +1429,7 @@ CBC90B7713179281DDEDF858973B4C52 /* URLSession+Rx.swift */, 4565CDC1E07D90AD03618A510BCE6F95 /* Support Files */, ); + name = RxCocoa; path = RxCocoa; sourceTree = ""; }; @@ -1476,13 +1482,13 @@ FB8F0279DAED71A0ECA6450302F427C7 /* Products */ = { isa = PBXGroup; children = ( - D51C3D0C53D23B97B032E3BDD4F82C82 /* libDifferentiator.a */, - 05FD55CFBD31B3E24D1A29D060BEF8AB /* libPods-Trombi.a */, - 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* libRxAtomic.a */, - BC432FD48A5932251F1CAFBC4BF74894 /* libRxCocoa.a */, - 692F92D73EC27270EA9CC9575C3E65B6 /* libRxDataSources.a */, - 809C5FAB588354C9BA37DC3EAB8CB45C /* libRxSwift.a */, - B0B214D775196BA7CA8E17E53048A493 /* libSDWebImage.a */, + D51C3D0C53D23B97B032E3BDD4F82C82 /* Differentiator */, + 05FD55CFBD31B3E24D1A29D060BEF8AB /* Pods-Trombi */, + 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* RxAtomic */, + BC432FD48A5932251F1CAFBC4BF74894 /* RxCocoa */, + 692F92D73EC27270EA9CC9575C3E65B6 /* RxDataSources */, + 809C5FAB588354C9BA37DC3EAB8CB45C /* RxSwift */, + B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */, ); name = Products; sourceTree = ""; @@ -1613,7 +1619,7 @@ ); name = Differentiator; productName = Differentiator; - productReference = D51C3D0C53D23B97B032E3BDD4F82C82 /* libDifferentiator.a */; + productReference = D51C3D0C53D23B97B032E3BDD4F82C82 /* Differentiator */; productType = "com.apple.product-type.library.static"; }; 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */ = { @@ -1630,7 +1636,7 @@ ); name = SDWebImage; productName = SDWebImage; - productReference = B0B214D775196BA7CA8E17E53048A493 /* libSDWebImage.a */; + productReference = B0B214D775196BA7CA8E17E53048A493 /* SDWebImage */; productType = "com.apple.product-type.library.static"; }; 3B2E405FB76A0E213CE57985A423DED6 /* RxAtomic */ = { @@ -1647,7 +1653,7 @@ ); name = RxAtomic; productName = RxAtomic; - productReference = 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* libRxAtomic.a */; + productReference = 8B6BD841EFEE4E2CFAC4ECBD46F0CF73 /* RxAtomic */; productType = "com.apple.product-type.library.static"; }; 401909D4FB2014BF539896BF0CCA48C2 /* RxDataSources */ = { @@ -1668,7 +1674,7 @@ ); name = RxDataSources; productName = RxDataSources; - productReference = 692F92D73EC27270EA9CC9575C3E65B6 /* libRxDataSources.a */; + productReference = 692F92D73EC27270EA9CC9575C3E65B6 /* RxDataSources */; productType = "com.apple.product-type.library.static"; }; 7AD0C6DCDC9CEC8A3C7C10C7FEE07BE6 /* RxCocoa */ = { @@ -1687,7 +1693,7 @@ ); name = RxCocoa; productName = RxCocoa; - productReference = BC432FD48A5932251F1CAFBC4BF74894 /* libRxCocoa.a */; + productReference = BC432FD48A5932251F1CAFBC4BF74894 /* RxCocoa */; productType = "com.apple.product-type.library.static"; }; B85E77D1DFC28005554E786131D9CB5C /* Pods-Trombi */ = { @@ -1710,7 +1716,7 @@ ); name = "Pods-Trombi"; productName = "Pods-Trombi"; - productReference = 05FD55CFBD31B3E24D1A29D060BEF8AB /* libPods-Trombi.a */; + productReference = 05FD55CFBD31B3E24D1A29D060BEF8AB /* Pods-Trombi */; productType = "com.apple.product-type.library.static"; }; EA9EA43B3B503823EE36C60D9C8A865F /* RxSwift */ = { @@ -1729,7 +1735,7 @@ ); name = RxSwift; productName = RxSwift; - productReference = 809C5FAB588354C9BA37DC3EAB8CB45C /* libRxSwift.a */; + productReference = 809C5FAB588354C9BA37DC3EAB8CB45C /* RxSwift */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ diff --git a/Trombi/Trombi.xcodeproj/project.pbxproj b/Trombi/Trombi.xcodeproj/project.pbxproj index f8e9a9c..2f47f9c 100644 --- a/Trombi/Trombi.xcodeproj/project.pbxproj +++ b/Trombi/Trombi.xcodeproj/project.pbxproj @@ -20,7 +20,16 @@ 4BA3CFB821A6DA6E003358E6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFB621A6DA6E003358E6 /* Main.storyboard */; }; 4BA3CFBA21A6DA6F003358E6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFB921A6DA6F003358E6 /* Assets.xcassets */; }; 4BA3CFBD21A6DA6F003358E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFBB21A6DA6F003358E6 /* LaunchScreen.storyboard */; }; + 4F3FDE91283FC30C008A5082 /* MainTabbarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE90283FC30C008A5082 /* MainTabbarCoordinator.swift */; }; + 4F3FDE94283FC95B008A5082 /* ApplicationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */; }; + 4F3FDE96283FCB1E008A5082 /* CoordinatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */; }; + 4F3FDE98283FCF73008A5082 /* Resultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE97283FCF73008A5082 /* Resultable.swift */; }; + 4F3FDE9C283FD4F4008A5082 /* UIViewController+xib.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE9B283FD4F4008A5082 /* UIViewController+xib.swift */; }; + 4F3FDE9E283FD537008A5082 /* NSObject+Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE9D283FD537008A5082 /* NSObject+Bundle.swift */; }; + 4F3FDEA2283FD93C008A5082 /* SplashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F3FDEA0283FD93C008A5082 /* SplashViewController.xib */; }; 4F9AA99A27497C1500EE12E9 /* ApplicationDataInjecting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9AA99927497C1500EE12E9 /* ApplicationDataInjecting.swift */; }; + 4FDDD84F283FB7DC00F60E34 /* RxBaseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */; }; + 4FDDD851283FBD4300F60E34 /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDD850283FBD4300F60E34 /* DeepLink.swift */; }; 9D06DDBB21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D06DDBA21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift */; }; 9D110BA521B5E91200AB0A36 /* TrombiAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D110BA421B5E91200AB0A36 /* TrombiAPI.swift */; }; 9D12825A234129C100261AB6 /* EmployeeSearchTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D128258234129C000261AB6 /* EmployeeSearchTableViewCell.xib */; }; @@ -111,7 +120,16 @@ 4BA3CFB921A6DA6F003358E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4BA3CFBC21A6DA6F003358E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4BA3CFBE21A6DA6F003358E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4F3FDE90283FC30C008A5082 /* MainTabbarCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabbarCoordinator.swift; sourceTree = ""; }; + 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationCoordinator.swift; sourceTree = ""; }; + 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatorFactory.swift; sourceTree = ""; }; + 4F3FDE97283FCF73008A5082 /* Resultable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Resultable.swift; sourceTree = ""; }; + 4F3FDE9B283FD4F4008A5082 /* UIViewController+xib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+xib.swift"; sourceTree = ""; }; + 4F3FDE9D283FD537008A5082 /* NSObject+Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+Bundle.swift"; sourceTree = ""; }; + 4F3FDEA0283FD93C008A5082 /* SplashViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SplashViewController.xib; sourceTree = ""; }; 4F9AA99927497C1500EE12E9 /* ApplicationDataInjecting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDataInjecting.swift; sourceTree = ""; }; + 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxBaseCoordinator.swift; sourceTree = ""; }; + 4FDDD850283FBD4300F60E34 /* DeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLink.swift; sourceTree = ""; }; 9D06DDBA21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+dequeueReusableCell.swift"; sourceTree = ""; }; 9D110BA421B5E91200AB0A36 /* TrombiAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrombiAPI.swift; sourceTree = ""; }; 9D128258234129C000261AB6 /* EmployeeSearchTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EmployeeSearchTableViewCell.xib; sourceTree = ""; }; @@ -248,6 +266,14 @@ path = Trombi; sourceTree = ""; }; + 4F3FDE8F283FC2FB008A5082 /* Coordinator */ = { + isa = PBXGroup; + children = ( + 4F3FDE90283FC30C008A5082 /* MainTabbarCoordinator.swift */, + ); + path = Coordinator; + sourceTree = ""; + }; 4F9AA99827497BFF00EE12E9 /* Protocols */ = { isa = PBXGroup; children = ( @@ -256,6 +282,16 @@ path = Protocols; sourceTree = ""; }; + 4FDDD84D283FB7C200F60E34 /* Architecture */ = { + isa = PBXGroup; + children = ( + 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */, + 4FDDD850283FBD4300F60E34 /* DeepLink.swift */, + 4F3FDE97283FCF73008A5082 /* Resultable.swift */, + ); + path = Architecture; + sourceTree = ""; + }; 775D4545808F2476CDC03A4A /* Pods */ = { isa = PBXGroup; children = ( @@ -269,6 +305,7 @@ isa = PBXGroup; children = ( 9D187E8E23B409C20080033E /* SplashViewController.swift */, + 4F3FDEA0283FD93C008A5082 /* SplashViewController.xib */, ); path = Splash; sourceTree = ""; @@ -408,6 +445,7 @@ 9DAC757421BC3BE700BA791D /* MainTabBar */ = { isa = PBXGroup; children = ( + 4F3FDE8F283FC2FB008A5082 /* Coordinator */, 9DAC757521BC3C7800BA791D /* MainTabBarViewController.swift */, 9DAC758B21BC4C2F00BA791D /* MainTabBarViewViewModel.swift */, ); @@ -419,9 +457,11 @@ children = ( 9DAC757B21BC409400BA791D /* UIStoryboard+StoryboardsList.swift */, 9DAC757A21BC409400BA791D /* UIViewController+Storyboards.swift */, + 4F3FDE9B283FD4F4008A5082 /* UIViewController+xib.swift */, 9DAC758221BC458900BA791D /* UITableView+dequeueReusableCell.swift */, 9D06DDBA21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift */, 02F70557244CC57200287902 /* UINavigationBar+configurate.swift */, + 4F3FDE9D283FD537008A5082 /* NSObject+Bundle.swift */, 9DAC758021BC453500BA791D /* ReusableView.swift */, 9D3967B321CEE07A0087CEA7 /* UIColor+Trombi.swift */, 9DBA8CA421D2640A009FF7B5 /* UIFont+Trombi.swift */, @@ -468,6 +508,7 @@ 9DE90CCA21A9F9C300AF8DF3 /* Common */ = { isa = PBXGroup; children = ( + 4FDDD84D283FB7C200F60E34 /* Architecture */, 4F9AA99827497BFF00EE12E9 /* Protocols */, 9D5429DE23AFE49C000C3721 /* Structures */, 9D92F22C2228A179005C605B /* Views */, @@ -492,6 +533,8 @@ children = ( 4BA3CFBB21A6DA6F003358E6 /* LaunchScreen.storyboard */, 4BA3CFB221A6DA6E003358E6 /* AppDelegate.swift */, + 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */, + 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */, 4BA3CFB621A6DA6E003358E6 /* Main.storyboard */, 9DF9590421B2F459005F024E /* Modules */, 9DF9590221B2F25B005F024E /* Models */, @@ -634,6 +677,7 @@ 9DEEF2ED21D2693B00509063 /* Muli-Bold.ttf in Resources */, 4BA3CFB821A6DA6E003358E6 /* Main.storyboard in Resources */, 9DEEF2EE21D2693E00509063 /* Muli-ExtraBold.ttf in Resources */, + 4F3FDEA2283FD93C008A5082 /* SplashViewController.xib in Resources */, 9DBDAC6523C67B74006FE076 /* Teams.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -699,9 +743,11 @@ 9DAC757621BC3C7800BA791D /* MainTabBarViewController.swift in Sources */, 9DAC757C21BC409400BA791D /* UIViewController+Storyboards.swift in Sources */, 02473C132434963400E2E3AF /* BaseUrlAlertController.swift in Sources */, + 4F3FDE91283FC30C008A5082 /* MainTabbarCoordinator.swift in Sources */, 9D52BB2721F2036F00962C4D /* FiltersPresentationController.swift in Sources */, 9D83E3172235774A0042DC0B /* CircleView.swift in Sources */, 9DC28358221041B80024263A /* UserInfoTableViewCell.swift in Sources */, + 4F3FDE96283FCB1E008A5082 /* CoordinatorFactory.swift in Sources */, 9DE90CCD21A9FB5400AF8DF3 /* TrombiApiRequests.swift in Sources */, 9D12825B234129C100261AB6 /* EmployeeSearchTableViewCell.swift in Sources */, 9DAC758121BC453500BA791D /* ReusableView.swift in Sources */, @@ -715,6 +761,7 @@ 9D2071E223B151BF00082181 /* UsefulLinkTableViewCell.swift in Sources */, 9D52BAF721F1FF5700962C4D /* LayoutInfo.swift in Sources */, 02473C152434964600E2E3AF /* BaseUrlAlertViewModel.swift in Sources */, + 4F3FDE98283FCF73008A5082 /* Resultable.swift in Sources */, 9D52BB3321F2036F00962C4D /* FiltersViewController.swift in Sources */, 9D3967B421CEE07A0087CEA7 /* UIColor+Trombi.swift in Sources */, 9D3967B821CEE12E0087CEA7 /* UIColor+Convenience.swift in Sources */, @@ -729,17 +776,21 @@ 9D06DDBB21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift in Sources */, 9D52BB3921F2036F00962C4D /* FiltersPanelViewController.swift in Sources */, 9D1C06B12308642600D20470 /* JSONDecoder+TrombiAPI.swift in Sources */, + 4F3FDE9C283FD4F4008A5082 /* UIViewController+xib.swift in Sources */, 9DF9590921B2F74E005F024E /* HomeViewController.swift in Sources */, + 4FDDD851283FBD4300F60E34 /* DeepLink.swift in Sources */, 9DAC757D21BC409400BA791D /* UIStoryboard+StoryboardsList.swift in Sources */, 024C8A9024635062003A57B5 /* BottomPanel.swift in Sources */, 9DAC758C21BC4C2F00BA791D /* MainTabBarViewViewModel.swift in Sources */, 02F70558244CC57200287902 /* UINavigationBar+configurate.swift in Sources */, 9D52BAF821F1FF5700962C4D /* LayoutAlignment.swift in Sources */, 9DAC759721BC6B0600BA791D /* ApplicationData.swift in Sources */, + 4F3FDE9E283FD537008A5082 /* NSObject+Bundle.swift in Sources */, 9DAFB58D21B332CC0038C680 /* Employee.swift in Sources */, 9D110BA521B5E91200AB0A36 /* TrombiAPI.swift in Sources */, 9D3D0C40233FBA2A00CF2590 /* TrombiSearchBar.swift in Sources */, 9DA1BBB223A66DCF0032E6CD /* LastSearchTableViewCell.swift in Sources */, + 4F3FDE94283FC95B008A5082 /* ApplicationCoordinator.swift in Sources */, 024C8A93246359F6003A57B5 /* FiltersSection.swift in Sources */, 9D52BAFA21F1FF5700962C4D /* TagCellLayout.swift in Sources */, 9D8E92E921F38197004B8E9E /* FiltersViewViewModel.swift in Sources */, @@ -747,6 +798,7 @@ 9DF0A5842214C3E700358A3E /* FilterTagCellModel.swift in Sources */, 4BA3CFB321A6DA6E003358E6 /* AppDelegate.swift in Sources */, 9D59316423119699004448A2 /* SearchViewViewModel.swift in Sources */, + 4FDDD84F283FB7DC00F60E34 /* RxBaseCoordinator.swift in Sources */, 9D92F22E2228A187005C605B /* TrombiTopRoundedView.swift in Sources */, 9DAC758A21BC4B3000BA791D /* HomeViewViewModel.swift in Sources */, 02C3182A2432411D009CB2F4 /* SettingsViewViewModel.swift in Sources */, @@ -909,7 +961,7 @@ MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.ChristianRusin.Trombi; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Trombi provisioning profile"; + PROVISIONING_PROFILE_SPECIFIER = Trombi; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -932,7 +984,7 @@ MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.ChristianRusin.Trombi; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Trombi provisioning profile"; + PROVISIONING_PROFILE_SPECIFIER = Trombi; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/Trombi/Trombi/Application/AppDelegate.swift b/Trombi/Trombi/Application/AppDelegate.swift index eebf871..d6e81bd 100644 --- a/Trombi/Trombi/Application/AppDelegate.swift +++ b/Trombi/Trombi/Application/AppDelegate.swift @@ -7,27 +7,41 @@ // import UIKit +import RxCocoa +import RxSwift @UIApplicationMain final class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - var mainViewModel: MainTabBarViewViewModelInterface = MainTabBarViewViewModel() + private var applicationCoordinator: ApplicationCoordinator? +// var mainViewModel: MainTabBarViewViewModelInterface = MainTabBarViewViewModel() + let bag = DisposeBag() + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { prepareUiElementsProxies() prepareTabBarProxy() - guard let mainTabBarViewController = - UIStoryboard.main.instantiateInitialViewController() as? MainTabBarViewController else { - fatalError("Could not load MainTabBarViewViewModel") - } - - window = UIWindow(frame: UIScreen.main.bounds) - mainTabBarViewController.viewModel = mainViewModel - window?.rootViewController = mainTabBarViewController - window?.makeKeyAndVisible() +// guard let mainTabBarViewController = +// UIStoryboard.main.instantiateInitialViewController() as? MainTabBarViewController else { +// fatalError("Could not load MainTabBarViewViewModel") +// } + + let window = UIWindow(frame: UIScreen.main.bounds) +// self.window = window + + // This is UNNotificationResponse +// if let notificationResponse = connectionOptions.notificationResponse?.notification { +// appDelegate.launchDeepLink = DeepLinkBaseImpl(notification: notificationResponse) +// } else if let universalLink = connectionOptions.userActivities.first?.webpageURL { +// appDelegate.launchDeepLink = DeepLinkBaseImpl(universalLinkUrl: universalLink) +// } + + applicationCoordinator = ApplicationCoordinator(window: window, coordinatorFactory: CoordinatorFactory()) + applicationCoordinator?.start(with: nil) + .subscribe() + .disposed(by: bag) return true } diff --git a/Trombi/Trombi/Application/ApplicationCoordinator.swift b/Trombi/Trombi/Application/ApplicationCoordinator.swift new file mode 100644 index 0000000..31c61bd --- /dev/null +++ b/Trombi/Trombi/Application/ApplicationCoordinator.swift @@ -0,0 +1,58 @@ +// +// ApplicationCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import UIKit +import RxSwift + +class ApplicationCoordinator: RxBaseCoordinator { + var window: UIWindow +// private let coordinatorFactory: CoordinatorFactory + + init(window: UIWindow, coordinatorFactory: CoordinatorFactory) { +// self.coordinatorFactory = coordinatorFactory + self.window = window + + window.makeKeyAndVisible() + + super.init() + } + + override func start(with option: DeepLinkBase? = nil) -> Single { + Single.create { [weak self] _ in + self?.runApplicationFlow(option: option) + return Disposables.create() + } + } + + // MARK: - Deep link + override func handle(deepLink: DeepLinkBase) { } + + func runApplicationFlow(option: DeepLinkBase?) { + showSplashScreen() + .observeOn(MainScheduler.asyncInstance) + .subscribe(onSuccess: { [weak self] applicationData in + self?.runMainFlow(applicationData: applicationData) + }) + } + + func showSplashScreen() -> Single { + let controller = SplashViewController() + window.rootViewController = controller + return controller.modelResult + } + + func runMainFlow(applicationData: ApplicationData) { + guard let mainTabBarViewController = + UIStoryboard.main.instantiateInitialViewController() as? MainTabBarViewController else { + fatalError("Could not load MainTabBarViewViewModel") + } + mainTabBarViewController.applicationData = applicationData + + window.rootViewController = mainTabBarViewController + } +} diff --git a/Trombi/Trombi/Application/Base.lproj/Main.storyboard b/Trombi/Trombi/Application/Base.lproj/Main.storyboard index beb945a..740484c 100644 --- a/Trombi/Trombi/Application/Base.lproj/Main.storyboard +++ b/Trombi/Trombi/Application/Base.lproj/Main.storyboard @@ -1,10 +1,9 @@ - + - - + @@ -21,7 +20,6 @@ - @@ -29,51 +27,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -193,6 +146,5 @@ - diff --git a/Trombi/Trombi/Application/CoordinatorFactory.swift b/Trombi/Trombi/Application/CoordinatorFactory.swift new file mode 100644 index 0000000..ee17385 --- /dev/null +++ b/Trombi/Trombi/Application/CoordinatorFactory.swift @@ -0,0 +1,13 @@ +// +// CoordinatorFactory.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation + +public class CoordinatorFactory { + public init() {} +} diff --git a/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift b/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift new file mode 100644 index 0000000..a28af00 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift @@ -0,0 +1,13 @@ +// +// MainTabbarCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation + +class MainTabbarCoordinator: RxBaseCoordinator { + +} diff --git a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift b/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift index 74bddcb..a698ad6 100644 --- a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift +++ b/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift @@ -18,6 +18,7 @@ final class MainTabBarViewController: UITabBarController { // MARK: - Properties var viewModel: MainTabBarViewViewModelInterface? + var applicationData: ApplicationData? private var splashViewController: SplashViewController? @@ -31,28 +32,33 @@ final class MainTabBarViewController: UITabBarController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - if splashViewController == nil { - performSegue(withIdentifier: "Splash", sender: nil) +// if splashViewController == nil { +// performSegue(withIdentifier: "Splash", sender: nil) +// } + + if let safeApplicationData = self.applicationData { + viewModel?.homeViewViewModel.applicationData = safeApplicationData + viewModel?.usefulLinksViewViewModel.applicationData = safeApplicationData } } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { super.prepare(for: segue, sender: sender) - if let splashViewController = segue.destination as? SplashViewController { - self.splashViewController = splashViewController - self.splashViewController?.applicationData.asObservable().subscribe({ [weak self] event in - switch event { - case .completed, .error: - break - case .next(let applicationData): - if let safeApplicationData = applicationData { - self?.viewModel?.homeViewViewModel.applicationData = safeApplicationData - self?.viewModel?.usefulLinksViewViewModel.applicationData = safeApplicationData - self?.splashViewController?.dismiss(animated: false, completion: nil) - } - } - }).disposed(by: disposeBag) - } +// if let splashViewController = segue.destination as? SplashViewController { +// self.splashViewController = splashViewController +// self.splashViewController?.applicationData.asObservable().subscribe({ [weak self] event in +// switch event { +// case .completed, .error: +// break +// case .next(let applicationData): +// if let safeApplicationData = applicationData { +// self?.viewModel?.homeViewViewModel.applicationData = safeApplicationData +// self?.viewModel?.usefulLinksViewViewModel.applicationData = safeApplicationData +// self?.splashViewController?.dismiss(animated: false, completion: nil) +// } +// } +// }).disposed(by: disposeBag) +// } } // MARK: - Tabs init diff --git a/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift index c18bc83..8282e25 100644 --- a/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift +++ b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift @@ -10,17 +10,34 @@ import UIKit import RxSwift import RxCocoa -final class SplashViewController: UIViewController { +final class SplashViewController: UIViewController, Resultable { + + typealias ValueType = ApplicationData + + var modelResult: Single { + _modelResult + .take(1) + .asSingle() + } + + public var bag = DisposeBag() + + private var _modelResult = PublishRelay() // MARK: - RxSwift private let disposeBag = DisposeBag() - var applicationData: Driver { - return _applicationData.asDriver() + private let _applicationData = BehaviorRelay(value: nil) + + init() { + super.init(nibName: SplashViewController.identifier, bundle: SplashViewController.bundle) + hidesBottomBarWhenPushed = true } - private let _applicationData = BehaviorRelay(value: nil) + required init?(coder: NSCoder) { + super.init(coder: coder) + } private func getApplicationData() { let getEmployees = TrombiAPI.sharedAPI.getEmployees() @@ -39,36 +56,38 @@ final class SplashViewController: UIViewController { ) return applicationData - }) - - activityIndicatorView.isHidden = false - - observable.observeOn(MainScheduler.instance) - .subscribe({ [weak self] event in + }) + + observable + .do(onNext: { [weak self] _ in self?.activityIndicatorView.isHidden = true - switch event { - case .next(let applicationData): - self?._applicationData.accept(applicationData) - case .error(let error): - self?.handleError(error as NSError) - default: break - } - }).disposed(by: disposeBag) + }, onError: { [weak self] error in + self?.handleError(error as NSError) + }) + .subscribe(onNext: { [weak self] applicationData in + self?._modelResult.accept(applicationData) + }) + .disposed(by: disposeBag) + +// activityIndicatorView.isHidden = false +// +// observable.observeOn(MainScheduler.instance) +// .subscribe({ [weak self] event in +// self?.activityIndicatorView.isHidden = true +// switch event { +// case .next(let applicationData): +// self?._applicationData.accept(applicationData) +// case .error(let error): +// self?.handleError(error as NSError) +// default: break +// } +// }).disposed(by: disposeBag) } -// @IBOutlet private weak var backgroundGradientView: UIView! @IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! override func viewDidLoad() { super.viewDidLoad() - -// let gradientLayer = CAGradientLayer() -// gradientLayer.frame = view.bounds -// gradientLayer.colors = [#colorLiteral(red: 0.9803921569, green: 0.6705882353, blue: 0.0862745098, alpha: 1).cgColor, #colorLiteral(red: 1, green: 0.4274509804, blue: 0.1137254902, alpha: 1).cgColor] -// -// gradientLayer.shouldRasterize = true -// -// backgroundGradientView.layer.addSublayer(gradientLayer) activityIndicatorView.startAnimating() } diff --git a/Trombi/Trombi/Application/Modules/Splash/SplashViewController.xib b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.xib new file mode 100644 index 0000000..712b751 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.xib @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Common/Architecture/DeepLink.swift b/Trombi/Trombi/Common/Architecture/DeepLink.swift new file mode 100644 index 0000000..eff0de5 --- /dev/null +++ b/Trombi/Trombi/Common/Architecture/DeepLink.swift @@ -0,0 +1,15 @@ +// +// DeepLink.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation + +public protocol DeepLinkBase {} + +protocol DeepLinkOptionProcessCapable { + func handle(deepLink: DeepLinkBase) +} diff --git a/Trombi/Trombi/Common/Architecture/Resultable.swift b/Trombi/Trombi/Common/Architecture/Resultable.swift new file mode 100644 index 0000000..381d32c --- /dev/null +++ b/Trombi/Trombi/Common/Architecture/Resultable.swift @@ -0,0 +1,15 @@ +// +// Resultable.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import RxSwift + +public protocol Resultable { + associatedtype ValueType + + var modelResult: Single { get } +} diff --git a/Trombi/Trombi/Common/Architecture/RxBaseCoordinator.swift b/Trombi/Trombi/Common/Architecture/RxBaseCoordinator.swift new file mode 100644 index 0000000..f8750f5 --- /dev/null +++ b/Trombi/Trombi/Common/Architecture/RxBaseCoordinator.swift @@ -0,0 +1,70 @@ +// +// RxBaseCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import RxSwift + +// https://benoitpasquier.com/integrate-coordinator-pattern-in-rxswift/ +// https://medium.com/better-programming/reactive-mvvm-and-the-coordinator-pattern-done-right-88248baf8ca5 +// TODO: migrate to abstraction to get rid of coupling from RxSwift +open class RxBaseCoordinator: NSObject, DeepLinkOptionProcessCapable { + + public var isPopulated: Bool { + !childCoordinators.isEmpty + } + + private let identifier = UUID() + private var childCoordinators = [UUID: Any]() + + public var bag = DisposeBag() + + + @discardableResult + open func coordinate(to coordinator: RxBaseCoordinator, with option: DeepLinkBase? = nil) -> Single { + store(coordinator: coordinator) + return coordinator.start(with: option) + .do(onSuccess: { [weak self, unowned coordinator] _ in + self?.release(coordinator: coordinator) + }, onError: { [weak self, unowned coordinator] err in + self?.release(coordinator: coordinator) + }) + } + + open func start(with option: DeepLinkBase? = nil) -> Single { + fatalError("start() method must be implemented at child coordinator") + } + + open func addChild(coordinator: RxBaseCoordinator) { + store(coordinator: coordinator) + } + + open func resetCoordinator() { + childCoordinators.removeAll() + } + + open func remove(coordinator: RxBaseCoordinator) { + release(coordinator: coordinator) + } + + open func handle(deepLink: DeepLinkBase) { + childCoordinators.forEach { _, coordinator in + if let rxCoordinator = coordinator as? DeepLinkOptionProcessCapable { + rxCoordinator.handle(deepLink: deepLink) + } + } + } + + // MARK: - Private + + private func store(coordinator: RxBaseCoordinator) { + childCoordinators[coordinator.identifier] = coordinator + } + + private func release(coordinator: RxBaseCoordinator) { + childCoordinators[coordinator.identifier] = nil + } +} diff --git a/Trombi/Trombi/Common/Extenstions/NSObject+Bundle.swift b/Trombi/Trombi/Common/Extenstions/NSObject+Bundle.swift new file mode 100644 index 0000000..3cc3b88 --- /dev/null +++ b/Trombi/Trombi/Common/Extenstions/NSObject+Bundle.swift @@ -0,0 +1,23 @@ +// +// NSObject+Bundle.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation + +extension NSObject { + var nameOfClass: String { + NSStringFromClass(type(of: self)).components(separatedBy: ".").last ?? "" + } + + class var nameOfClass: String { + NSStringFromClass(self).components(separatedBy: ".").last ?? "" + } + + class var bundle: Bundle { + Bundle(for: self) + } +} diff --git a/Trombi/Trombi/Common/Extenstions/UIViewController+xib.swift b/Trombi/Trombi/Common/Extenstions/UIViewController+xib.swift new file mode 100644 index 0000000..2bb684d --- /dev/null +++ b/Trombi/Trombi/Common/Extenstions/UIViewController+xib.swift @@ -0,0 +1,26 @@ +// +// UIViewController+xib.swift +// Trombi +// +// Created by Kristian Rusyn on 26/05/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import UIKit + +extension UIViewController { + static var identifier: String { + var identifier = String(describing: self) + // If a class used with generic it returns whole name with generic + // like ClassName, to avoid this, here is cutting + // only first part - class name + if let cuttedIndex = identifier.firstIndex(of: "<") { + identifier = String(identifier[.. Date: Sat, 4 Jun 2022 18:23:19 +0200 Subject: [PATCH 2/2] Create root Coordinators for each module of application, updates in Coordinator/routing core architecture --- Trombi/Pods/Pods.xcodeproj/project.pbxproj | 4 +- .../TabBar/icSettings.imageset/Contents.json | 10 +- Trombi/Trombi.xcodeproj/project.pbxproj | 176 +++++++++++---- Trombi/Trombi/Application/AppDelegate.swift | 14 -- .../Application/ApplicationCoordinator.swift | 28 ++- .../Application/Base.lproj/Main.storyboard | 150 ------------- .../Application/CoordinatorFactory.swift | 14 +- .../Application/Models/ApplicationData.swift | 2 +- .../Trombi/Application/Models/Employee.swift | 4 +- Trombi/Trombi/Application/Models/Team.swift | 2 +- .../Home/Coordinator/HomeCoordinator.swift | 64 ++++++ .../Modules/Home/Factory/HomeFactory.swift | 26 +++ .../Filters.storyboard} | 85 +------ .../Home/Filters/FiltersViewViewModel.swift | 16 +- .../Filters/Views/FilterTagCellModel.swift | 2 +- .../Home/Filters/Views/FiltersSection.swift | 10 +- .../Modules/Home/HomeViewController.swift | 212 ++++++++++-------- .../Modules/Home/HomeViewController.xib | 45 ++++ .../Modules/Home/HomeViewViewModel.swift | 53 +++-- .../Coordinator/SearchCoordinator.swift | 37 +++ .../Modules/Home/Search/Search.storyboard | 88 -------- .../Home/Search/SearchViewController.swift | 43 ++-- .../Home/Search/SearchViewController.xib | 63 ++++++ .../Home/Search/SearchViewViewModel.swift | 22 +- .../Views/EmployeeSearchTableViewCell.swift | 2 +- .../Views/EmployeeCollectionViewCell.swift | 2 +- .../Home/Views/EmployeeSectionModel.swift | 12 +- .../Coordinator/MainTabbarCoordinator.swift | 56 ++++- .../MainTabBar/MainTabBarViewController.swift | 75 +------ .../MainTabBar/MainTabBarViewViewModel.swift | 30 --- .../Coordinator/SettingsCoordinator.swift | 40 ++++ .../Settings/Factory/SettingsFactory.swift | 19 ++ .../Modules/Settings/Settings.storyboard | 42 ---- .../Settings/SettingsViewController.swift | 27 +-- .../Settings/SettingsViewController.xib | 38 ++++ .../Settings/SettingsViewViewModel.swift | 17 +- .../Modules/Splash/SplashViewController.swift | 1 + .../Modules/Teams/Teams.storyboard | 33 ++- .../Coordinator/UsefulLinksCoordinator.swift | 38 ++++ .../Factory/UsefulLinksFactory.swift | 18 ++ .../UsefulLinks/UsefulLinks.storyboard | 45 ---- .../UsefulLinksViewController.swift | 33 ++- .../UsefulLinks/UsefulLinksViewController.xib | 38 ++++ .../UsefulLinksViewViewModel.swift | 44 ++-- .../Views/UsefulLinkTableViewCell.swift | 2 +- .../UserProfile/UserProfile.storyboard | 41 +++- .../UserProfile/UserProfilePresenting.swift | 29 +++ .../Common/Architecture/Presentable.swift | 19 ++ .../Trombi/Common/Architecture/Router.swift | 140 ++++++++++++ .../Architecture/RxBaseCoordinator.swift | 5 + .../Common/Extenstions/UIImage+Alpha.swift | 19 ++ .../UIStoryboard+StoryboardsList.swift | 19 -- .../Protocols/ApplicationDataInjecting.swift | 2 +- .../BaseUrlAlert/BaseUrlAlertController.swift | 19 +- 54 files changed, 1229 insertions(+), 846 deletions(-) delete mode 100644 Trombi/Trombi/Application/Base.lproj/Main.storyboard create mode 100644 Trombi/Trombi/Application/Modules/Home/Coordinator/HomeCoordinator.swift create mode 100644 Trombi/Trombi/Application/Modules/Home/Factory/HomeFactory.swift rename Trombi/Trombi/Application/Modules/Home/{Home.storyboard => Filters/Filters.storyboard} (75%) create mode 100644 Trombi/Trombi/Application/Modules/Home/HomeViewController.xib create mode 100644 Trombi/Trombi/Application/Modules/Home/Search/Coordinator/SearchCoordinator.swift delete mode 100644 Trombi/Trombi/Application/Modules/Home/Search/Search.storyboard create mode 100644 Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.xib delete mode 100644 Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewViewModel.swift create mode 100644 Trombi/Trombi/Application/Modules/Settings/Coordinator/SettingsCoordinator.swift create mode 100644 Trombi/Trombi/Application/Modules/Settings/Factory/SettingsFactory.swift delete mode 100644 Trombi/Trombi/Application/Modules/Settings/Settings.storyboard create mode 100644 Trombi/Trombi/Application/Modules/Settings/SettingsViewController.xib create mode 100644 Trombi/Trombi/Application/Modules/UsefulLinks/Coordinator/UsefulLinksCoordinator.swift create mode 100644 Trombi/Trombi/Application/Modules/UsefulLinks/Factory/UsefulLinksFactory.swift delete mode 100644 Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinks.storyboard create mode 100644 Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.xib create mode 100644 Trombi/Trombi/Application/Modules/UserProfile/UserProfilePresenting.swift create mode 100644 Trombi/Trombi/Common/Architecture/Presentable.swift create mode 100644 Trombi/Trombi/Common/Architecture/Router.swift create mode 100644 Trombi/Trombi/Common/Extenstions/UIImage+Alpha.swift delete mode 100644 Trombi/Trombi/Common/Extenstions/UIStoryboard+StoryboardsList.swift diff --git a/Trombi/Pods/Pods.xcodeproj/project.pbxproj b/Trombi/Pods/Pods.xcodeproj/project.pbxproj index c17ad0c..a06c20b 100644 --- a/Trombi/Pods/Pods.xcodeproj/project.pbxproj +++ b/Trombi/Pods/Pods.xcodeproj/project.pbxproj @@ -1744,8 +1744,8 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1240; - LastUpgradeCheck = 1240; + LastSwiftUpdateCheck = 1300; + LastUpgradeCheck = 1300; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 9.3"; diff --git a/Trombi/Resources/Assets.xcassets/TabBar/icSettings.imageset/Contents.json b/Trombi/Resources/Assets.xcassets/TabBar/icSettings.imageset/Contents.json index 3f914d9..929cf4f 100644 --- a/Trombi/Resources/Assets.xcassets/TabBar/icSettings.imageset/Contents.json +++ b/Trombi/Resources/Assets.xcassets/TabBar/icSettings.imageset/Contents.json @@ -1,8 +1,8 @@ { "images" : [ { - "idiom" : "universal", "filename" : "icSettings.png", + "idiom" : "universal", "scale" : "1x" }, { @@ -15,10 +15,10 @@ } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "original" } -} \ No newline at end of file +} diff --git a/Trombi/Trombi.xcodeproj/project.pbxproj b/Trombi/Trombi.xcodeproj/project.pbxproj index 2f47f9c..8201f06 100644 --- a/Trombi/Trombi.xcodeproj/project.pbxproj +++ b/Trombi/Trombi.xcodeproj/project.pbxproj @@ -17,9 +17,10 @@ 02F70558244CC57200287902 /* UINavigationBar+configurate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F70557244CC57200287902 /* UINavigationBar+configurate.swift */; }; 118492F5429998B2F936E9AE /* libPods-Trombi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0154AAA732CFCBB9555EB9E5 /* libPods-Trombi.a */; }; 4BA3CFB321A6DA6E003358E6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA3CFB221A6DA6E003358E6 /* AppDelegate.swift */; }; - 4BA3CFB821A6DA6E003358E6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFB621A6DA6E003358E6 /* Main.storyboard */; }; 4BA3CFBA21A6DA6F003358E6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFB921A6DA6F003358E6 /* Assets.xcassets */; }; 4BA3CFBD21A6DA6F003358E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BA3CFBB21A6DA6F003358E6 /* LaunchScreen.storyboard */; }; + 4F224C82284BA0270052AECB /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F224C81284BA0270052AECB /* Presentable.swift */; }; + 4F224C84284BA30D0052AECB /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F224C83284BA30D0052AECB /* Router.swift */; }; 4F3FDE91283FC30C008A5082 /* MainTabbarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE90283FC30C008A5082 /* MainTabbarCoordinator.swift */; }; 4F3FDE94283FC95B008A5082 /* ApplicationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */; }; 4F3FDE96283FCB1E008A5082 /* CoordinatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */; }; @@ -28,6 +29,15 @@ 4F3FDE9E283FD537008A5082 /* NSObject+Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3FDE9D283FD537008A5082 /* NSObject+Bundle.swift */; }; 4F3FDEA2283FD93C008A5082 /* SplashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F3FDEA0283FD93C008A5082 /* SplashViewController.xib */; }; 4F9AA99A27497C1500EE12E9 /* ApplicationDataInjecting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9AA99927497C1500EE12E9 /* ApplicationDataInjecting.swift */; }; + 4F9FC4BC284E311500EBB0E3 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4BB284E311500EBB0E3 /* HomeCoordinator.swift */; }; + 4F9FC4BF284E316A00EBB0E3 /* HomeFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4BE284E316A00EBB0E3 /* HomeFactory.swift */; }; + 4F9FC4C1284E39D200EBB0E3 /* HomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F9FC4C0284E39D200EBB0E3 /* HomeViewController.xib */; }; + 4F9FC4C4284E499600EBB0E3 /* UsefulLinksViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F9FC4C3284E499600EBB0E3 /* UsefulLinksViewController.xib */; }; + 4F9FC4C6284E53DB00EBB0E3 /* UsefulLinksCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4C5284E53DB00EBB0E3 /* UsefulLinksCoordinator.swift */; }; + 4F9FC4C9284E541E00EBB0E3 /* UsefulLinksFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4C8284E541E00EBB0E3 /* UsefulLinksFactory.swift */; }; + 4F9FC4CC284E5E6800EBB0E3 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4CB284E5E6800EBB0E3 /* SettingsCoordinator.swift */; }; + 4F9FC4CF284E5E8200EBB0E3 /* SettingsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9FC4CE284E5E8200EBB0E3 /* SettingsFactory.swift */; }; + 4F9FC4D3284E5FB500EBB0E3 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F9FC4D2284E5FB500EBB0E3 /* SettingsViewController.xib */; }; 4FDDD84F283FB7DC00F60E34 /* RxBaseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */; }; 4FDDD851283FBD4300F60E34 /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDD850283FBD4300F60E34 /* DeepLink.swift */; }; 9D06DDBB21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D06DDBA21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift */; }; @@ -37,12 +47,10 @@ 9D15A8DE22BFE0FF007E1C73 /* EmployeesCollectionViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D15A8DD22BFE0FF007E1C73 /* EmployeesCollectionViewHeader.xib */; }; 9D187E8F23B409C20080033E /* SplashViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D187E8E23B409C20080033E /* SplashViewController.swift */; }; 9D1C06B12308642600D20470 /* JSONDecoder+TrombiAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D1C06B02308642600D20470 /* JSONDecoder+TrombiAPI.swift */; }; - 9D2071D823B1481800082181 /* UsefulLinks.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D2071D723B1481800082181 /* UsefulLinks.storyboard */; }; 9D2071DC23B1484A00082181 /* UsefulLinksViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2071DB23B1484A00082181 /* UsefulLinksViewViewModel.swift */; }; 9D2071DE23B1487600082181 /* UsefulLinksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2071DD23B1487600082181 /* UsefulLinksViewController.swift */; }; 9D2071E223B151BF00082181 /* UsefulLinkTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2071E023B151BF00082181 /* UsefulLinkTableViewCell.swift */; }; 9D2071E323B151BF00082181 /* UsefulLinkTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D2071E123B151BF00082181 /* UsefulLinkTableViewCell.xib */; }; - 9D297E3A24154190008E1A00 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D297E3924154190008E1A00 /* Settings.storyboard */; }; 9D297E3C24154263008E1A00 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D297E3B24154263008E1A00 /* SettingsViewController.swift */; }; 9D2F8D9824AF57FA00EC277C /* EmployeesCollectionViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F8D9724AF57FA00EC277C /* EmployeesCollectionViewHeader.swift */; }; 9D3967B421CEE07A0087CEA7 /* UIColor+Trombi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3967B321CEE07A0087CEA7 /* UIColor+Trombi.swift */; }; @@ -55,21 +63,15 @@ 9D52BAF821F1FF5700962C4D /* LayoutAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BAF421F1FF5700962C4D /* LayoutAlignment.swift */; }; 9D52BAF921F1FF5700962C4D /* TagCellLayoutDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BAF521F1FF5700962C4D /* TagCellLayoutDelegate.swift */; }; 9D52BAFA21F1FF5700962C4D /* TagCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BAF621F1FF5700962C4D /* TagCellLayout.swift */; }; - 9D52BB2721F2036F00962C4D /* FiltersPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB0421F2036F00962C4D /* FiltersPresentationController.swift */; }; - 9D52BB2821F2036F00962C4D /* FiltersPresentTransitionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB0521F2036F00962C4D /* FiltersPresentTransitionAnimation.swift */; }; 9D52BB2F21F2036F00962C4D /* FiltersCollectionViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D52BB1021F2036F00962C4D /* FiltersCollectionViewHeader.xib */; }; - 9D52BB3321F2036F00962C4D /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB1421F2036F00962C4D /* FiltersViewController.swift */; }; - 9D52BB3921F2036F00962C4D /* FiltersPanelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB1D21F2036F00962C4D /* FiltersPanelViewController.swift */; }; 9D5429E023AFE4AA000C3721 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5429DF23AFE4AA000C3721 /* Stack.swift */; }; 9D55DF5821C9205C009A983F /* EmployeeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D55DF5621C9205C009A983F /* EmployeeCollectionViewCell.swift */; }; 9D55DF5921C9205C009A983F /* EmployeeCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D55DF5721C9205C009A983F /* EmployeeCollectionViewCell.xib */; }; 9D59316223119668004448A2 /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D59316123119668004448A2 /* SearchViewController.swift */; }; 9D59316423119699004448A2 /* SearchViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D59316323119699004448A2 /* SearchViewViewModel.swift */; }; - 9D5931662311A11D004448A2 /* Search.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D5931652311A11D004448A2 /* Search.storyboard */; }; 9D69B62022A5B6F1008ED9B5 /* EmployeeSectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D69B61F22A5B6F1008ED9B5 /* EmployeeSectionModel.swift */; }; 9D83E3172235774A0042DC0B /* CircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D83E3162235774A0042DC0B /* CircleView.swift */; }; 9D8E92E521F35A6F004B8E9E /* UIView+RoundCorners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D8E92E421F35A6F004B8E9E /* UIView+RoundCorners.swift */; }; - 9D8E92E921F38197004B8E9E /* FiltersViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D8E92E821F38197004B8E9E /* FiltersViewViewModel.swift */; }; 9D8E92EE21F3CDC2004B8E9E /* TeamTagCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D8E92EC21F3CDC2004B8E9E /* TeamTagCollectionViewCell.swift */; }; 9D8E92EF21F3CDC2004B8E9E /* TeamTagCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D8E92ED21F3CDC2004B8E9E /* TeamTagCollectionViewCell.xib */; }; 9D92F22E2228A187005C605B /* TrombiTopRoundedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D92F22D2228A187005C605B /* TrombiTopRoundedView.swift */; }; @@ -77,17 +79,24 @@ 9DA1BBB223A66DCF0032E6CD /* LastSearchTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA1BBB023A66DCF0032E6CD /* LastSearchTableViewCell.swift */; }; 9DA1BBB323A66DCF0032E6CD /* LastSearchTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9DA1BBB123A66DCF0032E6CD /* LastSearchTableViewCell.xib */; }; 9DAC757621BC3C7800BA791D /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC757521BC3C7800BA791D /* MainTabBarViewController.swift */; }; - 9DAC757821BC3C9700BA791D /* Home.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9DAC757721BC3C9700BA791D /* Home.storyboard */; }; 9DAC757C21BC409400BA791D /* UIViewController+Storyboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC757A21BC409400BA791D /* UIViewController+Storyboards.swift */; }; - 9DAC757D21BC409400BA791D /* UIStoryboard+StoryboardsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC757B21BC409400BA791D /* UIStoryboard+StoryboardsList.swift */; }; 9DAC758121BC453500BA791D /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC758021BC453500BA791D /* ReusableView.swift */; }; 9DAC758321BC458900BA791D /* UITableView+dequeueReusableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC758221BC458900BA791D /* UITableView+dequeueReusableCell.swift */; }; 9DAC758A21BC4B3000BA791D /* HomeViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC758921BC4B3000BA791D /* HomeViewViewModel.swift */; }; - 9DAC758C21BC4C2F00BA791D /* MainTabBarViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC758B21BC4C2F00BA791D /* MainTabBarViewViewModel.swift */; }; 9DAC759721BC6B0600BA791D /* ApplicationData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAC759621BC6B0600BA791D /* ApplicationData.swift */; }; 9DAFB58C21B332CC0038C680 /* UsefulLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAFB58921B332CC0038C680 /* UsefulLink.swift */; }; 9DAFB58D21B332CC0038C680 /* Employee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAFB58A21B332CC0038C680 /* Employee.swift */; }; 9DAFB58E21B332CC0038C680 /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DAFB58B21B332CC0038C680 /* Team.swift */; }; + 9DB867142870865300F5847C /* UIImage+Alpha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB867132870865300F5847C /* UIImage+Alpha.swift */; }; + 9DB867162870935C00F5847C /* SearchViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9DB867152870935C00F5847C /* SearchViewController.xib */; }; + 9DB867192870995300F5847C /* SearchCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB867182870995300F5847C /* SearchCoordinator.swift */; }; + 9DB8671D2870A87F00F5847C /* UserProfilePresenting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB8671C2870A87F00F5847C /* UserProfilePresenting.swift */; }; + 9DB8671F2870AB9D00F5847C /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB1421F2036F00962C4D /* FiltersViewController.swift */; }; + 9DB867202870ABA200F5847C /* FiltersPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB0421F2036F00962C4D /* FiltersPresentationController.swift */; }; + 9DB867222870ABA200F5847C /* FiltersViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D8E92E821F38197004B8E9E /* FiltersViewViewModel.swift */; }; + 9DB867232870ABA200F5847C /* FiltersPanelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB1D21F2036F00962C4D /* FiltersPanelViewController.swift */; }; + 9DB867242870ABA200F5847C /* FiltersPresentTransitionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D52BB0521F2036F00962C4D /* FiltersPresentTransitionAnimation.swift */; }; + 9DB867262870B1B500F5847C /* Filters.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9DB867252870B1B500F5847C /* Filters.storyboard */; }; 9DBA8CA521D2640A009FF7B5 /* UIFont+Trombi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DBA8CA421D2640A009FF7B5 /* UIFont+Trombi.swift */; }; 9DBDAC6523C67B74006FE076 /* Teams.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9DBDAC6423C67B74006FE076 /* Teams.storyboard */; }; 9DC2835522103EEF0024263A /* EmployeeProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DC2835422103EEF0024263A /* EmployeeProfileViewController.swift */; }; @@ -116,10 +125,11 @@ 02F70557244CC57200287902 /* UINavigationBar+configurate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+configurate.swift"; sourceTree = ""; }; 4BA3CFAF21A6DA6E003358E6 /* Trombi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Trombi.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4BA3CFB221A6DA6E003358E6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4BA3CFB721A6DA6E003358E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 4BA3CFB921A6DA6F003358E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4BA3CFBC21A6DA6F003358E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4BA3CFBE21A6DA6F003358E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4F224C81284BA0270052AECB /* Presentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = ""; }; + 4F224C83284BA30D0052AECB /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; 4F3FDE90283FC30C008A5082 /* MainTabbarCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabbarCoordinator.swift; sourceTree = ""; }; 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationCoordinator.swift; sourceTree = ""; }; 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatorFactory.swift; sourceTree = ""; }; @@ -128,6 +138,15 @@ 4F3FDE9D283FD537008A5082 /* NSObject+Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+Bundle.swift"; sourceTree = ""; }; 4F3FDEA0283FD93C008A5082 /* SplashViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SplashViewController.xib; sourceTree = ""; }; 4F9AA99927497C1500EE12E9 /* ApplicationDataInjecting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDataInjecting.swift; sourceTree = ""; }; + 4F9FC4BB284E311500EBB0E3 /* HomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCoordinator.swift; sourceTree = ""; }; + 4F9FC4BE284E316A00EBB0E3 /* HomeFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFactory.swift; sourceTree = ""; }; + 4F9FC4C0284E39D200EBB0E3 /* HomeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeViewController.xib; sourceTree = ""; }; + 4F9FC4C3284E499600EBB0E3 /* UsefulLinksViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UsefulLinksViewController.xib; sourceTree = ""; }; + 4F9FC4C5284E53DB00EBB0E3 /* UsefulLinksCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsefulLinksCoordinator.swift; sourceTree = ""; }; + 4F9FC4C8284E541E00EBB0E3 /* UsefulLinksFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsefulLinksFactory.swift; sourceTree = ""; }; + 4F9FC4CB284E5E6800EBB0E3 /* SettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinator.swift; sourceTree = ""; }; + 4F9FC4CE284E5E8200EBB0E3 /* SettingsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFactory.swift; sourceTree = ""; }; + 4F9FC4D2284E5FB500EBB0E3 /* SettingsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = ""; }; 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxBaseCoordinator.swift; sourceTree = ""; }; 4FDDD850283FBD4300F60E34 /* DeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLink.swift; sourceTree = ""; }; 9D06DDBA21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+dequeueReusableCell.swift"; sourceTree = ""; }; @@ -137,12 +156,10 @@ 9D15A8DD22BFE0FF007E1C73 /* EmployeesCollectionViewHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EmployeesCollectionViewHeader.xib; sourceTree = ""; }; 9D187E8E23B409C20080033E /* SplashViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashViewController.swift; sourceTree = ""; }; 9D1C06B02308642600D20470 /* JSONDecoder+TrombiAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+TrombiAPI.swift"; sourceTree = ""; }; - 9D2071D723B1481800082181 /* UsefulLinks.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = UsefulLinks.storyboard; sourceTree = ""; }; 9D2071DB23B1484A00082181 /* UsefulLinksViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsefulLinksViewViewModel.swift; sourceTree = ""; }; 9D2071DD23B1487600082181 /* UsefulLinksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsefulLinksViewController.swift; sourceTree = ""; }; 9D2071E023B151BF00082181 /* UsefulLinkTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsefulLinkTableViewCell.swift; sourceTree = ""; }; 9D2071E123B151BF00082181 /* UsefulLinkTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UsefulLinkTableViewCell.xib; sourceTree = ""; }; - 9D297E3924154190008E1A00 /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; 9D297E3B24154263008E1A00 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; 9D29BBFD21D2604000EDBCA0 /* Muli-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Muli-ExtraBold.ttf"; sourceTree = ""; }; 9D29BBFE21D2604000EDBCA0 /* Muli-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Muli-Bold.ttf"; sourceTree = ""; }; @@ -168,7 +185,6 @@ 9D55DF5721C9205C009A983F /* EmployeeCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EmployeeCollectionViewCell.xib; sourceTree = ""; }; 9D59316123119668004448A2 /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = ""; }; 9D59316323119699004448A2 /* SearchViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewViewModel.swift; sourceTree = ""; }; - 9D5931652311A11D004448A2 /* Search.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Search.storyboard; sourceTree = ""; }; 9D69B61F22A5B6F1008ED9B5 /* EmployeeSectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmployeeSectionModel.swift; sourceTree = ""; }; 9D83E3162235774A0042DC0B /* CircleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleView.swift; sourceTree = ""; }; 9D8E92E421F35A6F004B8E9E /* UIView+RoundCorners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+RoundCorners.swift"; sourceTree = ""; }; @@ -180,17 +196,19 @@ 9DA1BBB023A66DCF0032E6CD /* LastSearchTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastSearchTableViewCell.swift; sourceTree = ""; }; 9DA1BBB123A66DCF0032E6CD /* LastSearchTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LastSearchTableViewCell.xib; sourceTree = ""; }; 9DAC757521BC3C7800BA791D /* MainTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarViewController.swift; sourceTree = ""; }; - 9DAC757721BC3C9700BA791D /* Home.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Home.storyboard; sourceTree = ""; }; 9DAC757A21BC409400BA791D /* UIViewController+Storyboards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Storyboards.swift"; sourceTree = ""; }; - 9DAC757B21BC409400BA791D /* UIStoryboard+StoryboardsList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+StoryboardsList.swift"; sourceTree = ""; }; 9DAC758021BC453500BA791D /* ReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReusableView.swift; sourceTree = ""; }; 9DAC758221BC458900BA791D /* UITableView+dequeueReusableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+dequeueReusableCell.swift"; sourceTree = ""; }; 9DAC758921BC4B3000BA791D /* HomeViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewViewModel.swift; sourceTree = ""; }; - 9DAC758B21BC4C2F00BA791D /* MainTabBarViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarViewViewModel.swift; sourceTree = ""; }; 9DAC759621BC6B0600BA791D /* ApplicationData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationData.swift; sourceTree = ""; }; 9DAFB58921B332CC0038C680 /* UsefulLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UsefulLink.swift; sourceTree = ""; }; 9DAFB58A21B332CC0038C680 /* Employee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Employee.swift; sourceTree = ""; }; 9DAFB58B21B332CC0038C680 /* Team.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Team.swift; sourceTree = ""; }; + 9DB867132870865300F5847C /* UIImage+Alpha.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Alpha.swift"; sourceTree = ""; }; + 9DB867152870935C00F5847C /* SearchViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SearchViewController.xib; sourceTree = ""; }; + 9DB867182870995300F5847C /* SearchCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchCoordinator.swift; sourceTree = ""; }; + 9DB8671C2870A87F00F5847C /* UserProfilePresenting.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserProfilePresenting.swift; sourceTree = ""; }; + 9DB867252870B1B500F5847C /* Filters.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Filters.storyboard; sourceTree = ""; }; 9DBA8CA421D2640A009FF7B5 /* UIFont+Trombi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Trombi.swift"; sourceTree = ""; }; 9DBDAC6423C67B74006FE076 /* Teams.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Teams.storyboard; sourceTree = ""; }; 9DC2835422103EEF0024263A /* EmployeeProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmployeeProfileViewController.swift; sourceTree = ""; }; @@ -282,12 +300,62 @@ path = Protocols; sourceTree = ""; }; + 4F9FC4BA284E310600EBB0E3 /* Coordinator */ = { + isa = PBXGroup; + children = ( + 4F9FC4BB284E311500EBB0E3 /* HomeCoordinator.swift */, + ); + path = Coordinator; + sourceTree = ""; + }; + 4F9FC4BD284E315800EBB0E3 /* Factory */ = { + isa = PBXGroup; + children = ( + 4F9FC4BE284E316A00EBB0E3 /* HomeFactory.swift */, + ); + path = Factory; + sourceTree = ""; + }; + 4F9FC4C2284E497A00EBB0E3 /* Coordinator */ = { + isa = PBXGroup; + children = ( + 4F9FC4C5284E53DB00EBB0E3 /* UsefulLinksCoordinator.swift */, + ); + path = Coordinator; + sourceTree = ""; + }; + 4F9FC4C7284E540A00EBB0E3 /* Factory */ = { + isa = PBXGroup; + children = ( + 4F9FC4C8284E541E00EBB0E3 /* UsefulLinksFactory.swift */, + ); + path = Factory; + sourceTree = ""; + }; + 4F9FC4CA284E5C9B00EBB0E3 /* Coordinator */ = { + isa = PBXGroup; + children = ( + 4F9FC4CB284E5E6800EBB0E3 /* SettingsCoordinator.swift */, + ); + path = Coordinator; + sourceTree = ""; + }; + 4F9FC4CD284E5E7700EBB0E3 /* Factory */ = { + isa = PBXGroup; + children = ( + 4F9FC4CE284E5E8200EBB0E3 /* SettingsFactory.swift */, + ); + path = Factory; + sourceTree = ""; + }; 4FDDD84D283FB7C200F60E34 /* Architecture */ = { isa = PBXGroup; children = ( 4FDDD84E283FB7DC00F60E34 /* RxBaseCoordinator.swift */, 4FDDD850283FBD4300F60E34 /* DeepLink.swift */, 4F3FDE97283FCF73008A5082 /* Resultable.swift */, + 4F224C83284BA30D0052AECB /* Router.swift */, + 4F224C81284BA0270052AECB /* Presentable.swift */, ); path = Architecture; sourceTree = ""; @@ -313,10 +381,12 @@ 9D2071D623B147D500082181 /* UsefulLinks */ = { isa = PBXGroup; children = ( + 4F9FC4C7284E540A00EBB0E3 /* Factory */, + 4F9FC4C2284E497A00EBB0E3 /* Coordinator */, 9D2071DF23B1519F00082181 /* Views */, - 9D2071D723B1481800082181 /* UsefulLinks.storyboard */, 9D2071DB23B1484A00082181 /* UsefulLinksViewViewModel.swift */, 9D2071DD23B1487600082181 /* UsefulLinksViewController.swift */, + 4F9FC4C3284E499600EBB0E3 /* UsefulLinksViewController.xib */, ); path = UsefulLinks; sourceTree = ""; @@ -333,10 +403,12 @@ 9D297E382415409E008E1A00 /* Settings */ = { isa = PBXGroup; children = ( + 4F9FC4CD284E5E7700EBB0E3 /* Factory */, + 4F9FC4CA284E5C9B00EBB0E3 /* Coordinator */, 02C318242431F018009CB2F4 /* Views */, - 9D297E3924154190008E1A00 /* Settings.storyboard */, 9D297E3B24154263008E1A00 /* SettingsViewController.swift */, 02C318292432411D009CB2F4 /* SettingsViewViewModel.swift */, + 4F9FC4D2284E5FB500EBB0E3 /* SettingsViewController.xib */, ); path = Settings; sourceTree = ""; @@ -392,6 +464,7 @@ 9D52BB0421F2036F00962C4D /* FiltersPresentationController.swift */, 9D52BB0521F2036F00962C4D /* FiltersPresentTransitionAnimation.swift */, 9D52BB1D21F2036F00962C4D /* FiltersPanelViewController.swift */, + 9DB867252870B1B500F5847C /* Filters.storyboard */, ); path = Filters; sourceTree = ""; @@ -422,10 +495,11 @@ 9D59316023119635004448A2 /* Search */ = { isa = PBXGroup; children = ( + 9DB867172870992100F5847C /* Coordinator */, 9D3D0C3E233FB9C200CF2590 /* Views */, 9D59316123119668004448A2 /* SearchViewController.swift */, 9D59316323119699004448A2 /* SearchViewViewModel.swift */, - 9D5931652311A11D004448A2 /* Search.storyboard */, + 9DB867152870935C00F5847C /* SearchViewController.xib */, 9D9E7774236795FF0075FD25 /* SearchService.swift */, ); path = Search; @@ -447,7 +521,6 @@ children = ( 4F3FDE8F283FC2FB008A5082 /* Coordinator */, 9DAC757521BC3C7800BA791D /* MainTabBarViewController.swift */, - 9DAC758B21BC4C2F00BA791D /* MainTabBarViewViewModel.swift */, ); path = MainTabBar; sourceTree = ""; @@ -455,7 +528,6 @@ 9DAC757921BC3EF100BA791D /* Extenstions */ = { isa = PBXGroup; children = ( - 9DAC757B21BC409400BA791D /* UIStoryboard+StoryboardsList.swift */, 9DAC757A21BC409400BA791D /* UIViewController+Storyboards.swift */, 4F3FDE9B283FD4F4008A5082 /* UIViewController+xib.swift */, 9DAC758221BC458900BA791D /* UITableView+dequeueReusableCell.swift */, @@ -470,6 +542,7 @@ 9D1C06B02308642600D20470 /* JSONDecoder+TrombiAPI.swift */, 9D5278C523A652E300C9C8DC /* UserDefaults+Trombi.swift */, 9D4936B823CA4C2100805B22 /* UIView+FindFirstTextField.swift */, + 9DB867132870865300F5847C /* UIImage+Alpha.swift */, ); path = Extenstions; sourceTree = ""; @@ -486,6 +559,14 @@ path = Views; sourceTree = ""; }; + 9DB867172870992100F5847C /* Coordinator */ = { + isa = PBXGroup; + children = ( + 9DB867182870995300F5847C /* SearchCoordinator.swift */, + ); + path = Coordinator; + sourceTree = ""; + }; 9DBDAC6323C67B47006FE076 /* Teams */ = { isa = PBXGroup; children = ( @@ -497,6 +578,7 @@ 9DC2835322103EB80024263A /* UserProfile */ = { isa = PBXGroup; children = ( + 9DB8671C2870A87F00F5847C /* UserProfilePresenting.swift */, 9DC2835422103EEF0024263A /* EmployeeProfileViewController.swift */, 9DC28356221041B80024263A /* UserInfoTableViewCell.swift */, 9DC28357221041B80024263A /* UserInfoTableViewCell.xib */, @@ -535,7 +617,6 @@ 4BA3CFB221A6DA6E003358E6 /* AppDelegate.swift */, 4F3FDE93283FC95B008A5082 /* ApplicationCoordinator.swift */, 4F3FDE95283FCB1E008A5082 /* CoordinatorFactory.swift */, - 4BA3CFB621A6DA6E003358E6 /* Main.storyboard */, 9DF9590421B2F459005F024E /* Modules */, 9DF9590221B2F25B005F024E /* Models */, ); @@ -571,12 +652,14 @@ 9DF9590521B2F459005F024E /* Home */ = { isa = PBXGroup; children = ( + 4F9FC4BD284E315800EBB0E3 /* Factory */, + 4F9FC4BA284E310600EBB0E3 /* Coordinator */, 9D59316023119635004448A2 /* Search */, 9D52BAFE21F2034100962C4D /* Filters */, 9DAC758421BC463C00BA791D /* Views */, 9DF9590821B2F74E005F024E /* HomeViewController.swift */, 9DAC758921BC4B3000BA791D /* HomeViewViewModel.swift */, - 9DAC757721BC3C9700BA791D /* Home.storyboard */, + 4F9FC4C0284E39D200EBB0E3 /* HomeViewController.xib */, ); path = Home; sourceTree = ""; @@ -658,24 +741,24 @@ files = ( 9DC28359221041B80024263A /* UserInfoTableViewCell.xib in Resources */, 9DEEF2EF21D2694000509063 /* Muli-SemiBold.ttf in Resources */, - 9D2071D823B1481800082181 /* UsefulLinks.storyboard in Resources */, 4BA3CFBD21A6DA6F003358E6 /* LaunchScreen.storyboard in Resources */, 9D15A8DE22BFE0FF007E1C73 /* EmployeesCollectionViewHeader.xib in Resources */, 9D2071E323B151BF00082181 /* UsefulLinkTableViewCell.xib in Resources */, 02C318282431F052009CB2F4 /* SettingsTableViewCell.xib in Resources */, - 9D297E3A24154190008E1A00 /* Settings.storyboard in Resources */, - 9D5931662311A11D004448A2 /* Search.storyboard in Resources */, 4BA3CFBA21A6DA6F003358E6 /* Assets.xcassets in Resources */, + 4F9FC4C1284E39D200EBB0E3 /* HomeViewController.xib in Resources */, 9D12825A234129C100261AB6 /* EmployeeSearchTableViewCell.xib in Resources */, 9D4936BC23CA66F400805B22 /* UserProfile.storyboard in Resources */, + 9DB867162870935C00F5847C /* SearchViewController.xib in Resources */, + 4F9FC4D3284E5FB500EBB0E3 /* SettingsViewController.xib in Resources */, + 4F9FC4C4284E499600EBB0E3 /* UsefulLinksViewController.xib in Resources */, 9DCF1FD421FD09BA00605CB3 /* OtherTagCollectionViewCell.xib in Resources */, - 9DAC757821BC3C9700BA791D /* Home.storyboard in Resources */, 9DA1BBB323A66DCF0032E6CD /* LastSearchTableViewCell.xib in Resources */, 9D52BB2F21F2036F00962C4D /* FiltersCollectionViewHeader.xib in Resources */, 9D55DF5921C9205C009A983F /* EmployeeCollectionViewCell.xib in Resources */, 9D8E92EF21F3CDC2004B8E9E /* TeamTagCollectionViewCell.xib in Resources */, 9DEEF2ED21D2693B00509063 /* Muli-Bold.ttf in Resources */, - 4BA3CFB821A6DA6E003358E6 /* Main.storyboard in Resources */, + 9DB867262870B1B500F5847C /* Filters.storyboard in Resources */, 9DEEF2EE21D2693E00509063 /* Muli-ExtraBold.ttf in Resources */, 4F3FDEA2283FD93C008A5082 /* SplashViewController.xib in Resources */, 9DBDAC6523C67B74006FE076 /* Teams.storyboard in Resources */, @@ -736,33 +819,37 @@ 9DFB774722292A9A00160540 /* CircleImageView.swift in Sources */, 9DC2835522103EEF0024263A /* EmployeeProfileViewController.swift in Sources */, 9D187E8F23B409C20080033E /* SplashViewController.swift in Sources */, + 9DB867192870995300F5847C /* SearchCoordinator.swift in Sources */, 9D5278C623A652E300C9C8DC /* UserDefaults+Trombi.swift in Sources */, 9D55DF5821C9205C009A983F /* EmployeeCollectionViewCell.swift in Sources */, - 9D52BB2821F2036F00962C4D /* FiltersPresentTransitionAnimation.swift in Sources */, + 9DB867242870ABA200F5847C /* FiltersPresentTransitionAnimation.swift in Sources */, 9D52BAF921F1FF5700962C4D /* TagCellLayoutDelegate.swift in Sources */, 9DAC757621BC3C7800BA791D /* MainTabBarViewController.swift in Sources */, 9DAC757C21BC409400BA791D /* UIViewController+Storyboards.swift in Sources */, 02473C132434963400E2E3AF /* BaseUrlAlertController.swift in Sources */, 4F3FDE91283FC30C008A5082 /* MainTabbarCoordinator.swift in Sources */, - 9D52BB2721F2036F00962C4D /* FiltersPresentationController.swift in Sources */, 9D83E3172235774A0042DC0B /* CircleView.swift in Sources */, 9DC28358221041B80024263A /* UserInfoTableViewCell.swift in Sources */, 4F3FDE96283FCB1E008A5082 /* CoordinatorFactory.swift in Sources */, 9DE90CCD21A9FB5400AF8DF3 /* TrombiApiRequests.swift in Sources */, 9D12825B234129C100261AB6 /* EmployeeSearchTableViewCell.swift in Sources */, 9DAC758121BC453500BA791D /* ReusableView.swift in Sources */, + 4F9FC4BC284E311500EBB0E3 /* HomeCoordinator.swift in Sources */, 9D5429E023AFE4AA000C3721 /* Stack.swift in Sources */, 9D69B62022A5B6F1008ED9B5 /* EmployeeSectionModel.swift in Sources */, 4F9AA99A27497C1500EE12E9 /* ApplicationDataInjecting.swift in Sources */, 9D59316223119668004448A2 /* SearchViewController.swift in Sources */, + 4F9FC4C6284E53DB00EBB0E3 /* UsefulLinksCoordinator.swift in Sources */, 9D8E92E521F35A6F004B8E9E /* UIView+RoundCorners.swift in Sources */, 9D2F8D9824AF57FA00EC277C /* EmployeesCollectionViewHeader.swift in Sources */, 9D2071DC23B1484A00082181 /* UsefulLinksViewViewModel.swift in Sources */, 9D2071E223B151BF00082181 /* UsefulLinkTableViewCell.swift in Sources */, + 9DB867232870ABA200F5847C /* FiltersPanelViewController.swift in Sources */, + 9DB8671D2870A87F00F5847C /* UserProfilePresenting.swift in Sources */, 9D52BAF721F1FF5700962C4D /* LayoutInfo.swift in Sources */, 02473C152434964600E2E3AF /* BaseUrlAlertViewModel.swift in Sources */, 4F3FDE98283FCF73008A5082 /* Resultable.swift in Sources */, - 9D52BB3321F2036F00962C4D /* FiltersViewController.swift in Sources */, + 9DB867142870865300F5847C /* UIImage+Alpha.swift in Sources */, 9D3967B421CEE07A0087CEA7 /* UIColor+Trombi.swift in Sources */, 9D3967B821CEE12E0087CEA7 /* UIColor+Convenience.swift in Sources */, 9D2071DE23B1487600082181 /* UsefulLinksViewController.swift in Sources */, @@ -772,20 +859,23 @@ 9D4936B923CA4C2100805B22 /* UIView+FindFirstTextField.swift in Sources */, 9DAFB58C21B332CC0038C680 /* UsefulLink.swift in Sources */, 9D9E7775236795FF0075FD25 /* SearchService.swift in Sources */, + 4F224C82284BA0270052AECB /* Presentable.swift in Sources */, 9D8E92EE21F3CDC2004B8E9E /* TeamTagCollectionViewCell.swift in Sources */, + 9DB867202870ABA200F5847C /* FiltersPresentationController.swift in Sources */, 9D06DDBB21CEA32C0006E676 /* UICollectionView+dequeueReusableCell.swift in Sources */, - 9D52BB3921F2036F00962C4D /* FiltersPanelViewController.swift in Sources */, + 4F9FC4C9284E541E00EBB0E3 /* UsefulLinksFactory.swift in Sources */, 9D1C06B12308642600D20470 /* JSONDecoder+TrombiAPI.swift in Sources */, 4F3FDE9C283FD4F4008A5082 /* UIViewController+xib.swift in Sources */, 9DF9590921B2F74E005F024E /* HomeViewController.swift in Sources */, 4FDDD851283FBD4300F60E34 /* DeepLink.swift in Sources */, - 9DAC757D21BC409400BA791D /* UIStoryboard+StoryboardsList.swift in Sources */, + 4F9FC4CF284E5E8200EBB0E3 /* SettingsFactory.swift in Sources */, + 9DB867222870ABA200F5847C /* FiltersViewViewModel.swift in Sources */, 024C8A9024635062003A57B5 /* BottomPanel.swift in Sources */, - 9DAC758C21BC4C2F00BA791D /* MainTabBarViewViewModel.swift in Sources */, 02F70558244CC57200287902 /* UINavigationBar+configurate.swift in Sources */, 9D52BAF821F1FF5700962C4D /* LayoutAlignment.swift in Sources */, 9DAC759721BC6B0600BA791D /* ApplicationData.swift in Sources */, 4F3FDE9E283FD537008A5082 /* NSObject+Bundle.swift in Sources */, + 4F9FC4BF284E316A00EBB0E3 /* HomeFactory.swift in Sources */, 9DAFB58D21B332CC0038C680 /* Employee.swift in Sources */, 9D110BA521B5E91200AB0A36 /* TrombiAPI.swift in Sources */, 9D3D0C40233FBA2A00CF2590 /* TrombiSearchBar.swift in Sources */, @@ -793,12 +883,14 @@ 4F3FDE94283FC95B008A5082 /* ApplicationCoordinator.swift in Sources */, 024C8A93246359F6003A57B5 /* FiltersSection.swift in Sources */, 9D52BAFA21F1FF5700962C4D /* TagCellLayout.swift in Sources */, - 9D8E92E921F38197004B8E9E /* FiltersViewViewModel.swift in Sources */, + 4F9FC4CC284E5E6800EBB0E3 /* SettingsCoordinator.swift in Sources */, 9DCF1FD321FD09BA00605CB3 /* OtherTagCollectionViewCell.swift in Sources */, 9DF0A5842214C3E700358A3E /* FilterTagCellModel.swift in Sources */, 4BA3CFB321A6DA6E003358E6 /* AppDelegate.swift in Sources */, + 9DB8671F2870AB9D00F5847C /* FiltersViewController.swift in Sources */, 9D59316423119699004448A2 /* SearchViewViewModel.swift in Sources */, 4FDDD84F283FB7DC00F60E34 /* RxBaseCoordinator.swift in Sources */, + 4F224C84284BA30D0052AECB /* Router.swift in Sources */, 9D92F22E2228A187005C605B /* TrombiTopRoundedView.swift in Sources */, 9DAC758A21BC4B3000BA791D /* HomeViewViewModel.swift in Sources */, 02C3182A2432411D009CB2F4 /* SettingsViewViewModel.swift in Sources */, @@ -809,14 +901,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ - 4BA3CFB621A6DA6E003358E6 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 4BA3CFB721A6DA6E003358E6 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; 4BA3CFBB21A6DA6F003358E6 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( diff --git a/Trombi/Trombi/Application/AppDelegate.swift b/Trombi/Trombi/Application/AppDelegate.swift index d6e81bd..1dc2b0e 100644 --- a/Trombi/Trombi/Application/AppDelegate.swift +++ b/Trombi/Trombi/Application/AppDelegate.swift @@ -14,7 +14,6 @@ import RxSwift final class AppDelegate: UIResponder, UIApplicationDelegate { private var applicationCoordinator: ApplicationCoordinator? -// var mainViewModel: MainTabBarViewViewModelInterface = MainTabBarViewViewModel() let bag = DisposeBag() @@ -23,20 +22,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { prepareUiElementsProxies() prepareTabBarProxy() -// guard let mainTabBarViewController = -// UIStoryboard.main.instantiateInitialViewController() as? MainTabBarViewController else { -// fatalError("Could not load MainTabBarViewViewModel") -// } - let window = UIWindow(frame: UIScreen.main.bounds) -// self.window = window - - // This is UNNotificationResponse -// if let notificationResponse = connectionOptions.notificationResponse?.notification { -// appDelegate.launchDeepLink = DeepLinkBaseImpl(notification: notificationResponse) -// } else if let universalLink = connectionOptions.userActivities.first?.webpageURL { -// appDelegate.launchDeepLink = DeepLinkBaseImpl(universalLinkUrl: universalLink) -// } applicationCoordinator = ApplicationCoordinator(window: window, coordinatorFactory: CoordinatorFactory()) applicationCoordinator?.start(with: nil) diff --git a/Trombi/Trombi/Application/ApplicationCoordinator.swift b/Trombi/Trombi/Application/ApplicationCoordinator.swift index 31c61bd..a77a165 100644 --- a/Trombi/Trombi/Application/ApplicationCoordinator.swift +++ b/Trombi/Trombi/Application/ApplicationCoordinator.swift @@ -11,15 +11,15 @@ import RxSwift class ApplicationCoordinator: RxBaseCoordinator { var window: UIWindow -// private let coordinatorFactory: CoordinatorFactory + private let coordinatorFactory: CoordinatorFactory init(window: UIWindow, coordinatorFactory: CoordinatorFactory) { -// self.coordinatorFactory = coordinatorFactory + self.coordinatorFactory = coordinatorFactory self.window = window window.makeKeyAndVisible() - super.init() + super.init(router: CoordinatorFactory.router(nil)) } override func start(with option: DeepLinkBase? = nil) -> Single { @@ -36,8 +36,9 @@ class ApplicationCoordinator: RxBaseCoordinator { showSplashScreen() .observeOn(MainScheduler.asyncInstance) .subscribe(onSuccess: { [weak self] applicationData in - self?.runMainFlow(applicationData: applicationData) - }) + self?.runMainFlow(applicationData: applicationData) + }) + .disposed(by: bag) } func showSplashScreen() -> Single { @@ -47,12 +48,15 @@ class ApplicationCoordinator: RxBaseCoordinator { } func runMainFlow(applicationData: ApplicationData) { - guard let mainTabBarViewController = - UIStoryboard.main.instantiateInitialViewController() as? MainTabBarViewController else { - fatalError("Could not load MainTabBarViewViewModel") - } - mainTabBarViewController.applicationData = applicationData - - window.rootViewController = mainTabBarViewController + let mainTabbarCoordinator = MainTabbarCoordinator(coordinatorFactory: coordinatorFactory, + applicationData: applicationData) + coordinate(to: mainTabbarCoordinator) + .subscribe(onSuccess: { [weak self] _ in + self?.runApplicationFlow(option: nil) + }) + .disposed(by: bag) + + window.rootViewController = mainTabbarCoordinator.tabbarController.toPresent() + window.makeKeyAndVisible() } } diff --git a/Trombi/Trombi/Application/Base.lproj/Main.storyboard b/Trombi/Trombi/Application/Base.lproj/Main.storyboard deleted file mode 100644 index 740484c..0000000 --- a/Trombi/Trombi/Application/Base.lproj/Main.storyboard +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Trombi/Trombi/Application/CoordinatorFactory.swift b/Trombi/Trombi/Application/CoordinatorFactory.swift index ee17385..b16b9f8 100644 --- a/Trombi/Trombi/Application/CoordinatorFactory.swift +++ b/Trombi/Trombi/Application/CoordinatorFactory.swift @@ -6,8 +6,20 @@ // Copyright © 2022 Christian Rusin . All rights reserved. // -import Foundation +import UIKit public class CoordinatorFactory { public init() {} + + public static func router(_ navController: UINavigationController?) -> Router { + RouterImp(rootController: navigationController(navController)) + } + + public static func navigationController(_ navController: UINavigationController?) -> UINavigationController { + navController ?? UINavigationController(rootViewController: UIViewController()) + } + + public func homeCoordinator(applicationData: ApplicationData) -> HomeCoordinator { + return HomeCoordinator(applicationData: applicationData) + } } diff --git a/Trombi/Trombi/Application/Models/ApplicationData.swift b/Trombi/Trombi/Application/Models/ApplicationData.swift index 3dd1a69..a0fe06c 100644 --- a/Trombi/Trombi/Application/Models/ApplicationData.swift +++ b/Trombi/Trombi/Application/Models/ApplicationData.swift @@ -8,7 +8,7 @@ import Foundation -class ApplicationData { +public class ApplicationData { init(employees: [Employee] = [], teams: [Team] = [], usefuleLinks: [UsefulLink] = []) { self.employees = employees diff --git a/Trombi/Trombi/Application/Models/Employee.swift b/Trombi/Trombi/Application/Models/Employee.swift index f9c59da..71a7aca 100644 --- a/Trombi/Trombi/Application/Models/Employee.swift +++ b/Trombi/Trombi/Application/Models/Employee.swift @@ -8,7 +8,7 @@ import Foundation -struct Employee: Codable { +public struct Employee: Codable { enum CodingKeys: String, CodingKey { case identifier = "id" @@ -47,7 +47,7 @@ struct Employee: Codable { } } -extension Employee { +public extension Employee { fileprivate enum Defaults { static let secondsInDay = 3600.0 * 24.0 static let newcomerInterval: TimeInterval = 30.0 * secondsInDay diff --git a/Trombi/Trombi/Application/Models/Team.swift b/Trombi/Trombi/Application/Models/Team.swift index 27774ed..144fc41 100644 --- a/Trombi/Trombi/Application/Models/Team.swift +++ b/Trombi/Trombi/Application/Models/Team.swift @@ -8,7 +8,7 @@ import Foundation -struct Team: Codable, Equatable, Hashable { +public struct Team: Codable, Equatable, Hashable { enum CodingKeys: String, CodingKey { diff --git a/Trombi/Trombi/Application/Modules/Home/Coordinator/HomeCoordinator.swift b/Trombi/Trombi/Application/Modules/Home/Coordinator/HomeCoordinator.swift new file mode 100644 index 0000000..fe53f7d --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Home/Coordinator/HomeCoordinator.swift @@ -0,0 +1,64 @@ +// +// HomeCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import RxSwift + +public final class HomeCoordinator: RxBaseCoordinator, UserProfilePresenting { + let homeFactory = HomeFactory() + let applicationData: ApplicationData + + init(applicationData: ApplicationData) { + self.applicationData = applicationData + super.init(router: CoordinatorFactory.router(nil)) + } + + // swiftlint:disable:next function_body_length + public override func start(with option: DeepLinkBase? = nil) -> Single { + let homeViewModel = HomeViewViewModel(applicationData: applicationData) + let homeController = homeFactory.makeHomeRootPresentable(with: homeViewModel) + + router.toPresent()?.tabBarItem = constructTabItem() + router.setRootModule(homeController) + + homeViewModel + .openSearch + .subscribe(onNext: { [weak self] in + self?.pushSearchScreen() + }) + .disposed(by: bag) + + homeViewModel + .openEmployee + .subscribe(onNext: { [weak self] employeeAndTeam in + self?.openUserProfile(employeeAndTeam) + }) + .disposed(by: bag) + + return homeViewModel.modelResult + } + + func pushSearchScreen() { + let searchCoordinator = SearchCoordinator(applicationData: applicationData) + + router.present(searchCoordinator.router.toPresent()) + + coordinate(to: searchCoordinator) + .subscribe() + .disposed(by: bag) + } +} + +extension HomeCoordinator { + + private func constructTabItem() -> UITabBarItem { + let item = UITabBarItem(title: nil, image: UIImage(named: "icHome"), tag: 0) + item.selectedImage = UIImage(named: "icHomeActive") + item.badgeColor = UIColor.mainBlackColor + return item + } +} diff --git a/Trombi/Trombi/Application/Modules/Home/Factory/HomeFactory.swift b/Trombi/Trombi/Application/Modules/Home/Factory/HomeFactory.swift new file mode 100644 index 0000000..509e5fd --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Home/Factory/HomeFactory.swift @@ -0,0 +1,26 @@ +// +// HomeFactory.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation +import UIKit + +public protocol HomeFactoryInterface: AnyObject { + func makeHomeRootPresentable(with viewModel: ViewModel) -> Presentable + + func makeSearchScreenPresentable(with viewModel: ViewModel) -> Presentable +} + +public class HomeFactory: HomeFactoryInterface { + public func makeHomeRootPresentable(with viewModel: ViewModel) -> Presentable { + return HomeViewController(viewModel: viewModel) + } + + public func makeSearchScreenPresentable(with viewModel: ViewModel) -> Presentable { + return SearchViewController(viewModel: viewModel) + } +} diff --git a/Trombi/Trombi/Application/Modules/Home/Home.storyboard b/Trombi/Trombi/Application/Modules/Home/Filters/Filters.storyboard similarity index 75% rename from Trombi/Trombi/Application/Modules/Home/Home.storyboard rename to Trombi/Trombi/Application/Modules/Home/Filters/Filters.storyboard index 45788bb..94d5a80 100644 --- a/Trombi/Trombi/Application/Modules/Home/Home.storyboard +++ b/Trombi/Trombi/Application/Modules/Home/Filters/Filters.storyboard @@ -1,9 +1,9 @@ - + - + @@ -13,70 +13,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -131,7 +67,7 @@ - - - - - - - - - + @@ -243,13 +171,13 @@ + - @@ -272,6 +200,5 @@ - diff --git a/Trombi/Trombi/Application/Modules/Home/Filters/FiltersViewViewModel.swift b/Trombi/Trombi/Application/Modules/Home/Filters/FiltersViewViewModel.swift index f91781a..655a933 100644 --- a/Trombi/Trombi/Application/Modules/Home/Filters/FiltersViewViewModel.swift +++ b/Trombi/Trombi/Application/Modules/Home/Filters/FiltersViewViewModel.swift @@ -10,7 +10,7 @@ import Foundation import RxCocoa import RxSwift -protocol FiltersViewViewModelInterface { +public protocol FiltersViewViewModelInterface { // MARK: - Input var lastUpdatedTagCell: BehaviorRelay { get } @@ -25,7 +25,7 @@ protocol FiltersViewViewModelInterface { var filtered: Driver { get } } -final class FiltersViewViewModel: FiltersViewViewModelInterface { +public final class FiltersViewViewModel: FiltersViewViewModelInterface { // MARK: - RxSwift @@ -33,15 +33,15 @@ final class FiltersViewViewModel: FiltersViewViewModelInterface { // MARK: - FiltersViewViewModelInterface - private(set) var lastUpdatedTagCell: BehaviorRelay = BehaviorRelay(value: nil) - private(set) var resetFilters = PublishRelay() + private(set) public var lastUpdatedTagCell: BehaviorRelay = BehaviorRelay(value: nil) + private(set) public var resetFilters = PublishRelay() - var filtersSections: Driver<[FiltersSection]> { return _filtersSections.asDriver() } - var filteredTeams: Driver > { return _filteredTeams.asDriver() } - var newcomersFilterSelected: Driver { return _newcomersFilterSelected.asDriver() } + public var filtersSections: Driver<[FiltersSection]> { return _filtersSections.asDriver() } + public var filteredTeams: Driver > { return _filteredTeams.asDriver() } + public var newcomersFilterSelected: Driver { return _newcomersFilterSelected.asDriver() } // 2 combineLatests in order to make a bindings instead - var filtered: Driver { + public var filtered: Driver { return Observable.combineLatest( filteredTeams.asObservable(), _newcomersFilterSelected.asObservable() diff --git a/Trombi/Trombi/Application/Modules/Home/Filters/Views/FilterTagCellModel.swift b/Trombi/Trombi/Application/Modules/Home/Filters/Views/FilterTagCellModel.swift index aeab74e..ce4face 100644 --- a/Trombi/Trombi/Application/Modules/Home/Filters/Views/FilterTagCellModel.swift +++ b/Trombi/Trombi/Application/Modules/Home/Filters/Views/FilterTagCellModel.swift @@ -8,7 +8,7 @@ import Foundation -struct FilterTagCellModel { +public struct FilterTagCellModel { enum CellType { case newcomers case team(Team) diff --git a/Trombi/Trombi/Application/Modules/Home/Filters/Views/FiltersSection.swift b/Trombi/Trombi/Application/Modules/Home/Filters/Views/FiltersSection.swift index de57caa..0546a16 100644 --- a/Trombi/Trombi/Application/Modules/Home/Filters/Views/FiltersSection.swift +++ b/Trombi/Trombi/Application/Modules/Home/Filters/Views/FiltersSection.swift @@ -8,13 +8,13 @@ import RxDataSources -struct FiltersSection: SectionModelType { - typealias Item = FilterTagCellModel +public struct FiltersSection: SectionModelType { + public typealias Item = FilterTagCellModel - var header: String - var items: [Item] + public var header: String + public var items: [Item] - init(original: FiltersSection, items: [Item]) { + public init(original: FiltersSection, items: [Item]) { self = original self.items = items } diff --git a/Trombi/Trombi/Application/Modules/Home/HomeViewController.swift b/Trombi/Trombi/Application/Modules/Home/HomeViewController.swift index ea80d98..76c7c17 100644 --- a/Trombi/Trombi/Application/Modules/Home/HomeViewController.swift +++ b/Trombi/Trombi/Application/Modules/Home/HomeViewController.swift @@ -2,7 +2,7 @@ // HomeViewController.swift // Trombi // -// Created by Christian Rusin on 22/11/2018. +// Created by Christian Rusin on 22/11/2018. // Copyright © 2018 Christian Rusin . All rights reserved. // @@ -11,73 +11,67 @@ import RxSwift import RxCocoa import RxDataSources -final class HomeViewController: UIViewController { +public final class HomeViewController: UIViewController, UICollectionViewDelegateFlowLayout { // MARK: - ViewModel - var viewModel: HomeViewViewModelInterface? - + public var viewModel: ViewModel + + init(viewModel: ViewModel) { + self.viewModel = viewModel + super.init(nibName: HomeViewController.identifier, bundle: HomeViewController.bundle) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - IBOutlet @IBOutlet private weak var collectionView: UICollectionView? - @IBOutlet private weak var filterBarButtonItem: UIBarButtonItem? + + private var filterBarButtonItem: UIBarButtonItem? + private var searchBarButtonItem: UIBarButtonItem? // MARK: - RxSwift private let disposeBag = DisposeBag() // MARK: - Lifecycle - override func viewDidLoad() { + public override func viewDidLoad() { super.viewDidLoad() - navigationController?.navigationBar.configurate() - - if let viewModel = viewModel { - bindViewModel(viewModel) - } else { - print("UsefulLinksViewViewModel is not set up") - } + + setupNavigationTitle() setupCollectionView() + setupNavigationItems() + bindViewModel() } - override func viewWillAppear(_ animated: Bool) { + public override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(false, animated: true) } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - super.prepare(for: segue, sender: sender) - - guard let viewModel = viewModel else { return } - - if segue.identifier == String(describing: FiltersPanelViewController.self) { - if let filtersPanelViewController = segue.destination as? FiltersPanelViewController { - filtersPanelViewController.filtersViewViewModel = viewModel.filtersViewViewModel - } - } else if segue.identifier == String(describing: EmployeeProfileViewController.self) { - if let userProfileViewController = segue.destination as? EmployeeProfileViewController { - if let employeeInfo = sender as? EmployeeCellModel { - userProfileViewController.team = employeeInfo.team - userProfileViewController.employee = employeeInfo.employee - } - } - } else if segue.identifier == String(describing: SearchViewController.self) { - if let navigationController = segue.destination as? UINavigationController, - let searchViewController = navigationController.viewControllers.first as? SearchViewController { - searchViewController.viewModel = SearchViewViewModel(applicationData: viewModel.applicationData) - } - } - } - - // MARK: - IBAction - - @IBAction func searchButtonTouched(_ sender: Any) { - performSegue(withIdentifier: String(describing: SearchViewController.self), sender: nil) - } - - @IBAction func filterButtonTouched(_ sender: Any) { - performSegue(withIdentifier: String(describing: FiltersPanelViewController.self), sender: nil) + // MARK: - binding ViewModel + private func bindViewModel() { + bindCollectionView() + + searchBarButtonItem? + .rx + .tap + .bind(to: viewModel.openSearch) + .disposed(by: disposeBag) + + filterBarButtonItem? + .rx + .tap + .subscribe(onNext: { [weak self] in + self?.openFilters() + }) + .disposed(by: disposeBag) } - // MARK: - binding ViewModel - private func bindViewModel(_ viewModel: HomeViewViewModelInterface) { + // MARK: - Private methods + + private func bindCollectionView() { guard let collectionView = collectionView else { print("collectionView is not set up") return @@ -115,85 +109,115 @@ final class HomeViewController: UIViewController { }, onCompleted: nil, onDisposed: nil).disposed(by: disposeBag) } - // MARK: - Private methods - + private func setupNavigationTitle() { + navigationController?.navigationBar.configurate() + navigationItem.title = "Home" + navigationController?.navigationBar.prefersLargeTitles = true + } + private func setupCollectionView() { collectionView?.registerReusableCell(type: EmployeeCollectionViewCell.self) collectionView?.registerReusableHeader(type: EmployeesCollectionViewHeader.self) - collectionView?.rx.modelSelected(EmployeeCellModel.self).subscribe( + collectionView?.rx.modelSelected(EmployeeCellModel.self) + .subscribe( onNext: { [weak self] cell in - self?.performSegue( - withIdentifier: String(describing: EmployeeProfileViewController.self), - sender: cell - ) - }, onError: nil, - onCompleted: nil, - onDisposed: nil - ).disposed(by: disposeBag) - + guard let team = cell.team else { return } + + self?.viewModel + .openEmployee + .onNext(EmployeeAndTeam(cell.employee, team)) + }).disposed(by: disposeBag) + collectionView?.rx.setDelegate(self).disposed(by: disposeBag) } -} - -// MARK: - Constants - -extension HomeViewController { - fileprivate enum Defaults { - - static let itemTopMarginRatio: CGFloat = CGFloat(20.0/775.0) - static let itemSideMarginRatio: CGFloat = CGFloat(25.0/375.0) - static let itemSpacingRatio: CGFloat = CGFloat(15.0/375.0) - - static let itemWidthToHeightRatio = CGFloat(155.0/231.0) - - static let headerHeight = CGFloat(40.0) + + func setupNavigationItems() { + filterBarButtonItem = UIBarButtonItem(image: UIImage(named: "icFilter"), style: .plain, target: nil, action: nil) + filterBarButtonItem?.rx.tap.subscribe(onNext: { + print("tap") + }).disposed(by: disposeBag) + + searchBarButtonItem = UIBarButtonItem(image: UIImage(named: "icSearch"), style: .plain, target: nil, action: nil) + searchBarButtonItem?.tintColor = UIColor.mainBlackColor + + self.navigationItem.rightBarButtonItems = [filterBarButtonItem!, searchBarButtonItem!] + } - static let additionalMargin = CGFloat(15.0) + private func sideMargin() -> CGFloat { + let margin = view.bounds.width * HomeDefaults.itemSideMarginRatio + return margin } -} -// MARK: - HorizontalFloatingHeaderLayoutDelegate -extension HomeViewController: UICollectionViewDelegateFlowLayout { + private func itemWidth() -> CGFloat { + let width = view.bounds.width - sideMargin() * 2.0 + return width / CGFloat(2.0) - (view.bounds.width * HomeDefaults.itemSpacingRatio) / 2.0 + } + private func itemHeight() -> CGFloat { + return itemWidth() * (1.0 / HomeDefaults.itemWidthToHeightRatio) + } + + private func openFilters() { + let filtersStoryboard = + UIStoryboard(name: "Filters", + bundle: FiltersPanelViewController.bundle) + + guard let filtersPanelViewController = + filtersStoryboard.instantiateViewController(withIdentifier: + FiltersPanelViewController.storyboardIdentifier) as? FiltersPanelViewController else { + print("Failed to load FiltersPanelViewController") + return + } + + filtersPanelViewController.filtersViewViewModel = viewModel.filtersViewViewModel + present(filtersPanelViewController, animated: true) + } + + // MARK: - UICollectionViewDelegateFlowLayout + @objc(collectionView:layout:referenceSizeForHeaderInSection:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - return CGSize(width: view.bounds.width, height: Defaults.headerHeight) + return CGSize(width: view.bounds.width, height: HomeDefaults.headerHeight) } + @objc(collectionView:layout:sizeForItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: itemWidth(), height: itemHeight()) } + @objc(collectionView:layout:insetForSectionAtIndex:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { - return UIEdgeInsets(top: Defaults.itemTopMarginRatio * view.bounds.height, + return UIEdgeInsets(top: HomeDefaults.itemTopMarginRatio * view.bounds.height, left: sideMargin(), bottom: 0.0, right: sideMargin()) } + @objc(collectionView:layout:minimumLineSpacingForSectionAtIndex:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { - return view.bounds.height * Defaults.itemTopMarginRatio - } - - private func sideMargin() -> CGFloat { - let margin = view.bounds.width * Defaults.itemSideMarginRatio - return margin - } - - private func itemWidth() -> CGFloat { - let width = view.bounds.width - sideMargin() * 2.0 - return width / CGFloat(2.0) - (view.bounds.width * Defaults.itemSpacingRatio) / 2.0 + return view.bounds.height * HomeDefaults.itemTopMarginRatio } +} - private func itemHeight() -> CGFloat { - return itemWidth() * (1.0 / Defaults.itemWidthToHeightRatio) - } +// MARK: - Constants +fileprivate enum HomeDefaults { + + static let itemTopMarginRatio: CGFloat = CGFloat(20.0/775.0) + static let itemSideMarginRatio: CGFloat = CGFloat(25.0/375.0) + static let itemSpacingRatio: CGFloat = CGFloat(15.0/375.0) + + static let itemWidthToHeightRatio = CGFloat(155.0/231.0) + + static let headerHeight = CGFloat(40.0) + + static let additionalMargin = CGFloat(15.0) } + diff --git a/Trombi/Trombi/Application/Modules/Home/HomeViewController.xib b/Trombi/Trombi/Application/Modules/Home/HomeViewController.xib new file mode 100644 index 0000000..bd8f9ab --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Home/HomeViewController.xib @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Application/Modules/Home/HomeViewViewModel.swift b/Trombi/Trombi/Application/Modules/Home/HomeViewViewModel.swift index 8d810fc..ee91570 100644 --- a/Trombi/Trombi/Application/Modules/Home/HomeViewViewModel.swift +++ b/Trombi/Trombi/Application/Modules/Home/HomeViewViewModel.swift @@ -10,14 +10,14 @@ import Foundation import RxCocoa import RxSwift -protocol HomeViewViewModelInterface: ApplicationDataInjecting { +public protocol HomeViewViewModelInterface: ApplicationDataInjecting, Resultable { // MARK: - Output var employeesSections: Driver<[EmployeesSection]> { get } var filtersViewViewModel: FiltersViewViewModel { get } -} - -// MARK: - Constants -extension HomeViewViewModel { + + // MARK: - Input + var openSearch: PublishSubject { get } + var openEmployee: PublishSubject { get } } final class HomeViewViewModel: HomeViewViewModelInterface { @@ -25,25 +25,48 @@ final class HomeViewViewModel: HomeViewViewModelInterface { // MARK: - RxSwift private let disposeBag = DisposeBag() + + public var modelResult: Single { + _modelResult + .take(1) + .asSingle() + } + + var openSearch = PublishSubject() + var openEmployee = PublishSubject() + + public var bag = DisposeBag() + + private var _modelResult = PublishRelay() + init(applicationData: ApplicationData) { + self.applicationData = applicationData + refresh() + } + // MARK: - Properties - var applicationData: ApplicationData = ApplicationData() { + var applicationData: ApplicationData { didSet { - filtersViewViewModel.teams = applicationData.teams - // subscribe to updates from filter panel and genrerate filtered data - Observable.combineLatest( - filtersViewViewModel.filteredTeams.asObservable(), - filtersViewViewModel.newcomersFilterSelected.asObservable() - ).map({ (filteredTeams, newcomersFilterSelected) -> [EmployeesSection] in - return self.getEemployeesSections(filteredTeams: filteredTeams, sortByNewcomers: newcomersFilterSelected) - }).bind(to: _employeesSections).disposed(by: disposeBag) + refresh() } } + + func refresh() { + filtersViewViewModel.teams = applicationData.teams + // subscribe to updates from filter panel and genrerate filtered data + Observable.combineLatest( + filtersViewViewModel.filteredTeams.asObservable(), + filtersViewViewModel.newcomersFilterSelected.asObservable() + ).map({ (filteredTeams, newcomersFilterSelected) -> [EmployeesSection] in + return self.getEemployeesSections(filteredTeams: filteredTeams, sortByNewcomers: newcomersFilterSelected) + }).bind(to: _employeesSections).disposed(by: disposeBag) + } + // MARK: - Output var employeesSections: Driver<[EmployeesSection]> { return _employeesSections.asDriver() } var filtersViewViewModel: FiltersViewViewModel = FiltersViewViewModel(teams: []) - + // MARK: - Private properties private let _employeesSections = BehaviorRelay<[EmployeesSection]>(value: []) diff --git a/Trombi/Trombi/Application/Modules/Home/Search/Coordinator/SearchCoordinator.swift b/Trombi/Trombi/Application/Modules/Home/Search/Coordinator/SearchCoordinator.swift new file mode 100644 index 0000000..6587c3c --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Home/Search/Coordinator/SearchCoordinator.swift @@ -0,0 +1,37 @@ +// +// HomeCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import RxSwift + +public final class SearchCoordinator: RxBaseCoordinator, UserProfilePresenting { + let homeFactory = HomeFactory() + let applicationData: ApplicationData + + init(applicationData: ApplicationData) { + self.applicationData = applicationData + super.init(router: CoordinatorFactory.router(nil)) + } + + // swiftlint:disable:next function_body_length + public override func start(with option: DeepLinkBase? = nil) -> Single { + let searchViewModel = SearchViewViewModel(applicationData: applicationData) + let searchController = homeFactory.makeSearchScreenPresentable(with: searchViewModel) + + searchViewModel + .openEmployee + .asObservable() + .subscribe(onNext: { [weak self] employeeAndTeam in + self?.openUserProfile(employeeAndTeam) + }) + .disposed(by: bag) + + router.setRootModule(searchController) + + return searchViewModel.modelResult + } +} diff --git a/Trombi/Trombi/Application/Modules/Home/Search/Search.storyboard b/Trombi/Trombi/Application/Modules/Home/Search/Search.storyboard deleted file mode 100644 index b2be35c..0000000 --- a/Trombi/Trombi/Application/Modules/Home/Search/Search.storyboard +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - Muli-SemiBold - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.swift b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.swift index c90075a..ae225d7 100644 --- a/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.swift +++ b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.swift @@ -11,18 +11,26 @@ import RxCocoa import RxSwift import RxAtomic -enum SearchTableElementModel { +public enum SearchTableElementModel { case employee(EmployeeSearchCellModel) case lastSearch(String) } -final class SearchViewController: UIViewController { +final class SearchViewController: UIViewController { // MARK: - RxSwift private let disposeBag = DisposeBag() // MARK: - ViewModel - var viewModel: SearchViewViewModelInterface? + var viewModel: ViewModel + + init(viewModel: ViewModel) { + self.viewModel = viewModel + super.init(nibName: SearchViewController.identifier, bundle: SearchViewController.bundle) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } // MARK: - Properties private lazy var trombiSearchBar = TrombiSearchBar(frame: .zero) @@ -40,11 +48,7 @@ final class SearchViewController: UIViewController { trombiSearchBar.trombiDelegate = self navigationItem.titleView = trombiSearchBar - if let viewModel = viewModel { - bindViewModel(viewModel) - } else { - print("SearchViewViewModel is not set up") - } + bindViewModel(viewModel) } override func viewDidAppear(_ animated: Bool) { @@ -58,7 +62,7 @@ final class SearchViewController: UIViewController { } // MARK: - binding ViewModel - private func bindViewModel(_ viewModel: SearchViewViewModelInterface) { + private func bindViewModel(_ viewModel: ViewModel) { viewModel.searchTable .asObservable() .bind(to: tableView.rx.items) { (tableView, row, searchDataModel) -> UITableViewCell in @@ -88,7 +92,7 @@ final class SearchViewController: UIViewController { trombiSearchBar.rx.searchButtonClicked.subscribe { [weak self] _ in self?.trombiSearchBar.resignFirstResponder() if let text = self?.trombiSearchBar.text { - self?.viewModel?.lastSearch.onNext(text) + self?.viewModel.lastSearch.onNext(text) } }.disposed(by: disposeBag) @@ -101,26 +105,9 @@ final class SearchViewController: UIViewController { viewModel.forcedSearchText.drive(onNext: { [weak self] forceSearchText in guard let forceSearchText = forceSearchText else { return } self?.trombiSearchBar.text = forceSearchText - self?.viewModel?.enteredSearch.accept(forceSearchText) + self?.viewModel.enteredSearch.accept(forceSearchText) }, onCompleted: nil, onDisposed: nil) .disposed(by: disposeBag) - - viewModel.openEmployee.asObservable().subscribe { [weak self] event in - switch event { - case .next(let employeeAndTeam): - if let employee = employeeAndTeam?.0, let team = employeeAndTeam?.1 { - let employeeViewController = - EmployeeProfileViewController.modal( - employee: employee, - team: team, - onDismiss: nil) - - self?.present(employeeViewController, animated: true, completion: nil) - } - default: - break - } - }.disposed(by: disposeBag) } } diff --git a/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.xib b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.xib new file mode 100644 index 0000000..cbeae0c --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewController.xib @@ -0,0 +1,63 @@ + + + + + + + + + + + + Muli-SemiBold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Application/Modules/Home/Search/SearchViewViewModel.swift b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewViewModel.swift index 77b7eb2..2561ad4 100644 --- a/Trombi/Trombi/Application/Modules/Home/Search/SearchViewViewModel.swift +++ b/Trombi/Trombi/Application/Modules/Home/Search/SearchViewViewModel.swift @@ -11,22 +11,31 @@ import RxSwift import RxCocoa import RxDataSources -protocol SearchViewViewModelInterface { - // MARK: - Input +public protocol SearchViewViewModelInterface: Resultable { + // MARK: - Output var enteredSearch: BehaviorRelay { get } var selectedItem: BehaviorRelay { get } var lastSearch: PublishSubject { get } - // MARK: - Output + // MARK: - Input var noResultsIsHidden: Driver { get } var searchTable: Driver<[SearchTableElementModel]> { get } - var openEmployee: Signal<(Employee, Team)?> { get } + var openEmployee: PublishSubject { get } var forcedSearchText: Driver { get } } final class SearchViewViewModel: SearchViewViewModelInterface { + public var modelResult: Single { + _modelResult + .take(1) + .asSingle() + } + + private var _modelResult = PublishRelay() + + typealias ValueType = Any // MARK: - RxSwift private let disposeBag = DisposeBag() @@ -42,7 +51,6 @@ final class SearchViewViewModel: SearchViewViewModelInterface { var noResultsIsHidden: Driver { return _noResultsIsHidden.asDriver() } var searchTable: Driver<[SearchTableElementModel]> { return _searchTable.asDriver() } - var openEmployee: Signal<(Employee, Team)?> { return _openEmployee.asSignal(onErrorJustReturn: nil) } var forcedSearchText: Driver { return _forcedSearchText.asDriver() } @@ -54,7 +62,7 @@ final class SearchViewViewModel: SearchViewViewModelInterface { private let _searchTable = BehaviorRelay<[SearchTableElementModel]>(value: []) - private let _openEmployee = BehaviorRelay<(Employee, Team)?>(value: nil) + let openEmployee = PublishSubject() private let _forcedSearchText = BehaviorRelay(value: nil) @@ -95,7 +103,7 @@ final class SearchViewViewModel: SearchViewViewModelInterface { case .employee: if let selectedFoundEmployee = self?.foundEmployees[row], let team = self?.applicationData.teamOfEmployee(selectedFoundEmployee) { - self?._openEmployee.accept((selectedFoundEmployee, team)) + self?.openEmployee.onNext((selectedFoundEmployee, team)) } case .lastSearch(let lastSearch): self?._forcedSearchText.accept(lastSearch) diff --git a/Trombi/Trombi/Application/Modules/Home/Search/Views/EmployeeSearchTableViewCell.swift b/Trombi/Trombi/Application/Modules/Home/Search/Views/EmployeeSearchTableViewCell.swift index 64da85f..2238104 100644 --- a/Trombi/Trombi/Application/Modules/Home/Search/Views/EmployeeSearchTableViewCell.swift +++ b/Trombi/Trombi/Application/Modules/Home/Search/Views/EmployeeSearchTableViewCell.swift @@ -8,7 +8,7 @@ import UIKit -struct EmployeeSearchCellModel { +public struct EmployeeSearchCellModel { let imageUrl: String let nameText: String let positionText: String diff --git a/Trombi/Trombi/Application/Modules/Home/Views/EmployeeCollectionViewCell.swift b/Trombi/Trombi/Application/Modules/Home/Views/EmployeeCollectionViewCell.swift index c946312..97194c4 100644 --- a/Trombi/Trombi/Application/Modules/Home/Views/EmployeeCollectionViewCell.swift +++ b/Trombi/Trombi/Application/Modules/Home/Views/EmployeeCollectionViewCell.swift @@ -9,7 +9,7 @@ import UIKit import SDWebImage -struct EmployeeCellModel { +public struct EmployeeCellModel { let employee: Employee let team: Team? diff --git a/Trombi/Trombi/Application/Modules/Home/Views/EmployeeSectionModel.swift b/Trombi/Trombi/Application/Modules/Home/Views/EmployeeSectionModel.swift index e854131..f987ccb 100644 --- a/Trombi/Trombi/Application/Modules/Home/Views/EmployeeSectionModel.swift +++ b/Trombi/Trombi/Application/Modules/Home/Views/EmployeeSectionModel.swift @@ -9,14 +9,14 @@ import UIKit import RxDataSources -struct EmployeesSection: SectionModelType { - typealias Item = EmployeeCellModel +public struct EmployeesSection: SectionModelType { + public typealias Item = EmployeeCellModel - var header: String - let rightSideImage: UIImage? - var items: [Item] + public var header: String + public let rightSideImage: UIImage? + public var items: [Item] - init(original: EmployeesSection, items: [Item]) { + public init(original: EmployeesSection, items: [Item]) { self = original self.items = items } diff --git a/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift b/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift index a28af00..578ac92 100644 --- a/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift +++ b/Trombi/Trombi/Application/Modules/MainTabBar/Coordinator/MainTabbarCoordinator.swift @@ -6,8 +6,60 @@ // Copyright © 2022 Christian Rusin . All rights reserved. // -import Foundation +import UIKit +import RxSwift -class MainTabbarCoordinator: RxBaseCoordinator { +final class MainTabbarCoordinator: RxBaseCoordinator { + let tabbarController: UITabBarController = UITabBarController() + let coordinatorFactory: CoordinatorFactory + let applicationData: ApplicationData + init(coordinatorFactory: CoordinatorFactory, applicationData: ApplicationData) { + self.coordinatorFactory = coordinatorFactory + self.applicationData = applicationData + super.init(router: CoordinatorFactory.router(nil)) + } + + // swiftlint:disable:next function_body_length + override func start(with option: DeepLinkBase? = nil) -> Single { + let homeCoordinator = prepareHomeModuleCoordinator(with: option) + + let usefulLinksCoordinator = prepareUsefulLinksModuleCoordinator(with: option) + let settingsCoordinator = prepareSettingsModuleCoordinator(with: option) + + let tabViewControllers: [UIViewController] = + [homeCoordinator.router.toPresent() as? UINavigationController ?? UIViewController(), + usefulLinksCoordinator.router.toPresent() as? UINavigationController ?? UIViewController(), + settingsCoordinator.router.toPresent() as? UINavigationController ?? UIViewController()] + + tabbarController.viewControllers = tabViewControllers + + addChild(coordinator: homeCoordinator) + homeCoordinator.start() + .subscribe() + .disposed(by: bag) + + addChild(coordinator: usefulLinksCoordinator) + usefulLinksCoordinator.start() + .subscribe() + .disposed(by: bag) + + return coordinate(to: settingsCoordinator).map({ $0 as Any }) + } + + func prepareHomeModuleCoordinator(with option: DeepLinkBase? = nil) -> RxBaseCoordinator { + return HomeCoordinator(applicationData: applicationData) + } + + func prepareUsefulLinksModuleCoordinator(with option: DeepLinkBase? = nil) -> RxBaseCoordinator { + return UsefulLinksCoorinator(applicationData: applicationData) + } + + func prepareSettingsModuleCoordinator(with option: DeepLinkBase? = nil) -> RxBaseCoordinator { + return SettingsCoorinator(applicationData: applicationData) + } + + func prepareXModuleCoordinator(with option: DeepLinkBase? = nil) -> RxBaseCoordinator { + return RxBaseCoordinator(router: CoordinatorFactory.router(nil)) + } } diff --git a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift b/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift index a698ad6..ed9d03c 100644 --- a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift +++ b/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewController.swift @@ -9,7 +9,7 @@ import UIKit import RxSwift -final class MainTabBarViewController: UITabBarController { +final class MainTabBarViewController: UITabBarController, UITabBarControllerDelegate { // MARK: - RxSwift @@ -17,80 +17,25 @@ final class MainTabBarViewController: UITabBarController { // MARK: - Properties - var viewModel: MainTabBarViewViewModelInterface? - var applicationData: ApplicationData? - - private var splashViewController: SplashViewController? + override var viewControllers: [UIViewController]? { + didSet { + initTabs() + } + } // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() + + delegate = self + tabBar.isTranslucent = false tabBar.tintColor = UIColor.black initTabs() } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) -// if splashViewController == nil { -// performSegue(withIdentifier: "Splash", sender: nil) -// } - - if let safeApplicationData = self.applicationData { - viewModel?.homeViewViewModel.applicationData = safeApplicationData - viewModel?.usefulLinksViewViewModel.applicationData = safeApplicationData - } - } - - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - super.prepare(for: segue, sender: sender) -// if let splashViewController = segue.destination as? SplashViewController { -// self.splashViewController = splashViewController -// self.splashViewController?.applicationData.asObservable().subscribe({ [weak self] event in -// switch event { -// case .completed, .error: -// break -// case .next(let applicationData): -// if let safeApplicationData = applicationData { -// self?.viewModel?.homeViewViewModel.applicationData = safeApplicationData -// self?.viewModel?.usefulLinksViewViewModel.applicationData = safeApplicationData -// self?.splashViewController?.dismiss(animated: false, completion: nil) -// } -// } -// }).disposed(by: disposeBag) -// } - } - // MARK: - Tabs init private func initTabs() { - viewControllers?.forEach({ tabViewController in - if let navigationController = tabViewController as? UINavigationController { - if let homeViewController = navigationController.viewControllers.first as? HomeViewController { - homeViewController.viewModel = viewModel?.homeViewViewModel - } else if let usefulLinksViewController = - navigationController.viewControllers.first as? UsefulLinksViewController { - usefulLinksViewController.viewModel = viewModel?.usefulLinksViewViewModel - } else if let settingsViewController = navigationController.viewControllers.first as? SettingsViewController { - settingsViewController.viewModel = viewModel?.settingsViewViewModel - viewModel?.settingsViewViewModel - .finishedWithBaseUrl - .asObservable() - .filter({ baseUrl -> Bool in - return baseUrl != nil - }).subscribe({ [weak self] event in - switch event { - case .next: - if let splashViewController = self?.splashViewController { - self?.present(splashViewController, animated: false, completion: nil) - } else { - self?.performSegue(withIdentifier: "Splash", sender: nil) - } - default: - break - } - }).disposed(by: disposeBag) - } - } - }) + self.selectedIndex = 0 } } diff --git a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewViewModel.swift b/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewViewModel.swift deleted file mode 100644 index 3115b03..0000000 --- a/Trombi/Trombi/Application/Modules/MainTabBar/MainTabBarViewViewModel.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// MainTabBarViewViewModel.swift -// Trombi -// -// Created by Chris Rusin on 12/8/18. -// Copyright © 2018 Christian Rusin . All rights reserved. -// - -import Foundation -import RxSwift -import RxCocoa - -protocol MainTabBarViewViewModelInterface { - var homeViewViewModel: HomeViewViewModelInterface { get set } - var usefulLinksViewViewModel: UsefulLinksViewViewModelInterface { get set } - var settingsViewViewModel: SettingsViewViewModelInterface { get set } -} - -final class MainTabBarViewViewModel: MainTabBarViewViewModelInterface { - - // MARK: - RxSwift - - private let disposeBag = DisposeBag() - - // MARK: - Properties - - var homeViewViewModel: HomeViewViewModelInterface = HomeViewViewModel() - var usefulLinksViewViewModel: UsefulLinksViewViewModelInterface = UsefulLinksViewViewModel() - var settingsViewViewModel: SettingsViewViewModelInterface = SettingsViewViewModel() -} diff --git a/Trombi/Trombi/Application/Modules/Settings/Coordinator/SettingsCoordinator.swift b/Trombi/Trombi/Application/Modules/Settings/Coordinator/SettingsCoordinator.swift new file mode 100644 index 0000000..7e9679c --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Settings/Coordinator/SettingsCoordinator.swift @@ -0,0 +1,40 @@ +// +// SettingsCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import RxSwift + +public final class SettingsCoorinator: RxBaseCoordinator { + let settingsFactory = SettingsFactory() + let applicationData: ApplicationData + + init(applicationData: ApplicationData) { + self.applicationData = applicationData + super.init(router: CoordinatorFactory.router(nil)) + } + + // swiftlint:disable:next function_body_length + public override func start(with option: DeepLinkBase? = nil) -> Single { + let usefulLinksViewModel = SettingsViewViewModel() + let settingsController = settingsFactory.makeSettingsRootPresentable(with: usefulLinksViewModel) + + router.toPresent()?.tabBarItem = constructTabItem() + router.setRootModule(settingsController) + + return usefulLinksViewModel.modelResult + } + + private func constructTabItem() -> UITabBarItem { + let settingsImage = UIImage(named: "icSettings") + let settingsImageTranparent = UIImage(named: "icSettings")?.image(alpha: 0.9) + + let item = UITabBarItem(title: nil, image: settingsImageTranparent, tag: 0) + item.selectedImage = settingsImage + item.badgeColor = UIColor.mainBlackColor + return item + } +} diff --git a/Trombi/Trombi/Application/Modules/Settings/Factory/SettingsFactory.swift b/Trombi/Trombi/Application/Modules/Settings/Factory/SettingsFactory.swift new file mode 100644 index 0000000..312b076 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Settings/Factory/SettingsFactory.swift @@ -0,0 +1,19 @@ +// +// SettingsFactory.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation + +public protocol SettingsFactoryInterface: AnyObject { + func makeSettingsRootPresentable(with viewModel: ViewModel) -> Presentable +} + +public class SettingsFactory: SettingsFactoryInterface { + public func makeSettingsRootPresentable(with viewModel: ViewModel) -> Presentable { + return SettingsViewController(viewModel: viewModel) + } +} diff --git a/Trombi/Trombi/Application/Modules/Settings/Settings.storyboard b/Trombi/Trombi/Application/Modules/Settings/Settings.storyboard deleted file mode 100644 index c3c0cb0..0000000 --- a/Trombi/Trombi/Application/Modules/Settings/Settings.storyboard +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.swift b/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.swift index d9d8b78..839b6a1 100644 --- a/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.swift +++ b/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.swift @@ -10,13 +10,22 @@ import UIKit import RxSwift import RxCocoa -class SettingsViewController: UIViewController { +class SettingsViewController: UIViewController { // MARK: - RxSwift private let disposeBag = DisposeBag() // MARK: - ViewModel - var viewModel: SettingsViewViewModelInterface? + let viewModel: ViewModel + + init(viewModel: ViewModel) { + self.viewModel = viewModel + super.init(nibName: SettingsViewController.identifier, bundle: SettingsViewController.bundle) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } // MARK: - IBOutlet @IBOutlet private weak var tableView: UITableView? @@ -34,15 +43,11 @@ class SettingsViewController: UIViewController { tableView.tableFooterView = UIView() tableView.registerReusableCell(type: SettingsTableViewCell.self) - if let viewModel = viewModel { - bindViewModel(viewModel) - } else { - print("SearchViewViewModel is not set up") - } + bindViewModel() } // MARK: - binding ViewModel - private func bindViewModel(_ viewModel: SettingsViewViewModelInterface) { + private func bindViewModel() { guard let tableView = tableView else { print("Table view is not set up") return @@ -85,13 +90,9 @@ class SettingsViewController: UIViewController { switch event { case .next(let currentBaseUrl): let alert = BaseUrlAlertController(currentBaseUrl: currentBaseUrl) - guard let viewModel = strongSelf.viewModel else { - return - } alert.acceptedWithBaseUrl - .asObservable() - .bind(to: viewModel.finishedWithBaseUrl) + .bind(to: strongSelf.viewModel.newUrlSelected) .disposed(by: strongSelf.disposeBag) strongSelf.present(alert, animated: true, completion: nil) diff --git a/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.xib b/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.xib new file mode 100644 index 0000000..eef1181 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/Settings/SettingsViewController.xib @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Application/Modules/Settings/SettingsViewViewModel.swift b/Trombi/Trombi/Application/Modules/Settings/SettingsViewViewModel.swift index 9436989..b835819 100644 --- a/Trombi/Trombi/Application/Modules/Settings/SettingsViewViewModel.swift +++ b/Trombi/Trombi/Application/Modules/Settings/SettingsViewViewModel.swift @@ -10,10 +10,10 @@ import Foundation import RxSwift import RxCocoa -protocol SettingsViewViewModelInterface { +public protocol SettingsViewViewModelInterface: Resultable { // MARK: - Input var selectedItem: BehaviorRelay { get } - var finishedWithBaseUrl: BehaviorRelay { get } + var newUrlSelected: PublishRelay { get } // MARK: - Output var settingsTable: Driver<[String]> { get } @@ -23,6 +23,8 @@ protocol SettingsViewViewModelInterface { extension SettingsViewViewModel: SettingsViewViewModelInterface { + public typealias ValueType = String? + enum Defaults { static let helpUrl: String = "christianrusinm@gmail.com" } @@ -38,9 +40,17 @@ final class SettingsViewViewModel { // MARK: - RxSwift private let disposeBag = DisposeBag() + public var modelResult: Single { + _modelResult + .take(1) + .asSingle() + } + + private var _modelResult = PublishRelay() + // MARK: - SettingsViewViewModelInterface private(set) var selectedItem: BehaviorRelay = BehaviorRelay(value: nil) - private(set) var finishedWithBaseUrl: BehaviorRelay = BehaviorRelay(value: nil) + private(set) var newUrlSelected = PublishRelay() let settingsTable: Driver<[String]> = { BehaviorRelay<[String]>(value: SettingsRow.allCases.compactMap({ return $0.rawValue })).asDriver() @@ -54,6 +64,7 @@ final class SettingsViewViewModel { private let _sendEmailToAdress = BehaviorRelay(value: nil) init() { + newUrlSelected.bind(to: _modelResult).disposed(by: disposeBag) setup() } diff --git a/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift index 8282e25..df921cf 100644 --- a/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift +++ b/Trombi/Trombi/Application/Modules/Splash/SplashViewController.swift @@ -59,6 +59,7 @@ final class SplashViewController: UIViewController, Resultable { }) observable + .observeOn(MainScheduler.asyncInstance) .do(onNext: { [weak self] _ in self?.activityIndicatorView.isHidden = true }, onError: { [weak self] error in diff --git a/Trombi/Trombi/Application/Modules/Teams/Teams.storyboard b/Trombi/Trombi/Application/Modules/Teams/Teams.storyboard index 8e2ceb9..5328e9e 100644 --- a/Trombi/Trombi/Application/Modules/Teams/Teams.storyboard +++ b/Trombi/Trombi/Application/Modules/Teams/Teams.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -19,9 +17,10 @@ - + + @@ -29,12 +28,30 @@ - + - + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/Coordinator/UsefulLinksCoordinator.swift b/Trombi/Trombi/Application/Modules/UsefulLinks/Coordinator/UsefulLinksCoordinator.swift new file mode 100644 index 0000000..aad3e9d --- /dev/null +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/Coordinator/UsefulLinksCoordinator.swift @@ -0,0 +1,38 @@ +// +// UsefulLinksCoordinator.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + + +import RxSwift + +public final class UsefulLinksCoorinator: RxBaseCoordinator { + let usefulLinksFactory = UsefulLinksFactory() + let applicationData: ApplicationData + + init(applicationData: ApplicationData) { + self.applicationData = applicationData + super.init(router: CoordinatorFactory.router(nil)) + } + + // swiftlint:disable:next function_body_length + public override func start(with option: DeepLinkBase? = nil) -> Single { + let usefulLinksViewModel = UsefulLinksViewViewModel(applicationData: applicationData) + let usefulLinksController = usefulLinksFactory.makeUsefulLinksRootPresentable(with: usefulLinksViewModel) + + router.toPresent()?.tabBarItem = constructTabItem() + router.setRootModule(usefulLinksController) + + return usefulLinksViewModel.modelResult + } + + private func constructTabItem() -> UITabBarItem { + let item = UITabBarItem(title: nil, image: UIImage(named: "icLinks"), tag: 0) + item.selectedImage = UIImage(named: "icLinksActive") + item.badgeColor = UIColor.mainBlackColor + return item + } +} diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/Factory/UsefulLinksFactory.swift b/Trombi/Trombi/Application/Modules/UsefulLinks/Factory/UsefulLinksFactory.swift new file mode 100644 index 0000000..373db62 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/Factory/UsefulLinksFactory.swift @@ -0,0 +1,18 @@ +// +// UsefulLinksFactory.swift +// Trombi +// +// Created by Kristian Rusyn on 06/06/2022. +// Copyright © 2022 Christian Rusin . All rights reserved. +// + +import Foundation +public protocol UsefulLinksFactoryInterface: AnyObject { + func makeUsefulLinksRootPresentable(with viewModel: ViewModel) -> Presentable +} + +public class UsefulLinksFactory: UsefulLinksFactoryInterface { + public func makeUsefulLinksRootPresentable(with viewModel: ViewModel) -> Presentable { + return UsefulLinksViewController(viewModel: viewModel) + } +} diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinks.storyboard b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinks.storyboard deleted file mode 100644 index c513995..0000000 --- a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinks.storyboard +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.swift b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.swift index aab3e2f..d9252a6 100644 --- a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.swift +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.swift @@ -11,31 +11,35 @@ import SafariServices import RxSwift import RxCocoa -final class UsefulLinksViewController: UIViewController { +final class UsefulLinksViewController: UIViewController { // MARK: - RxSwift private let disposeBag = DisposeBag() // MARK: - ViewModel - var viewModel: UsefulLinksViewViewModelInterface? - + let viewModel: ViewModel + + init(viewModel: ViewModel) { + self.viewModel = viewModel + super.init(nibName: UsefulLinksViewController.identifier, bundle: UsefulLinksViewController.bundle) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - IBOutlets - @IBOutlet weak var tableView: UITableView? + @IBOutlet private weak var tableView: UITableView? // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() - navigationController?.navigationBar.configurate() + setupNavigationTitle() - if let viewModel = viewModel { - bindViewModel(viewModel) - } else { - print("UsefulLinksViewViewModel is not set up") - } - tableView?.registerReusableCell(type: UsefulLinkTableViewCell.self) + bindViewModel(viewModel) } // MARK: - binding ViewModel @@ -73,4 +77,11 @@ final class UsefulLinksViewController: UIViewController { } }.disposed(by: disposeBag) } + + // MARK: - Private methods + private func setupNavigationTitle() { + navigationController?.navigationBar.configurate() + navigationItem.title = "Useful links" + navigationController?.navigationBar.prefersLargeTitles = true + } } diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.xib b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.xib new file mode 100644 index 0000000..7eab7b1 --- /dev/null +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewController.xib @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewViewModel.swift b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewViewModel.swift index 3a6a053..6cf2e1c 100644 --- a/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewViewModel.swift +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/UsefulLinksViewViewModel.swift @@ -9,7 +9,7 @@ import RxSwift import RxCocoa -protocol UsefulLinksViewViewModelInterface: ApplicationDataInjecting { +public protocol UsefulLinksViewViewModelInterface: ApplicationDataInjecting { // MARK: - Input var selectedItem: BehaviorRelay { get } @@ -18,12 +18,21 @@ protocol UsefulLinksViewViewModelInterface: ApplicationDataInjecting { var openUrl: Signal { get } } -final class UsefulLinksViewViewModel: UsefulLinksViewViewModelInterface { +public final class UsefulLinksViewViewModel: UsefulLinksViewViewModelInterface { // MARK: - RxSwift private let disposeBag = DisposeBag() + + public var modelResult: Single { + _modelResult + .take(1) + .asSingle() + } + + private var _modelResult = PublishRelay() - init() { + init(applicationData: ApplicationData) { + self.applicationData = applicationData selectedItem.subscribe { [weak self] event in switch event { case .next(let index): @@ -34,27 +43,32 @@ final class UsefulLinksViewViewModel: UsefulLinksViewViewModelInterface { break } }.disposed(by: disposeBag) + refresh() } // MARK: - UsefulLinksViewViewModelInterface - private(set) var selectedItem: BehaviorRelay = BehaviorRelay(value: nil) + private(set) public var selectedItem: BehaviorRelay = BehaviorRelay(value: nil) - var usefulLinksTable: Driver<[UsefulLinkCellModel]> { return _usefulLinksTable.asDriver() } - var openUrl: Signal { return _openUrl.asSignal(onErrorJustReturn: "") } + public var usefulLinksTable: Driver<[UsefulLinkCellModel]> { return _usefulLinksTable.asDriver() } + public var openUrl: Signal { return _openUrl.asSignal(onErrorJustReturn: "") } public var applicationData: ApplicationData = ApplicationData() { didSet { - let usefulLinkCellsModels = applicationData.usefuleLinks.map({ usefulLink in - return UsefulLinkCellModel( - imageUrl: usefulLink.imageUrl, - title: usefulLink.title, - description: usefulLink.description - ) - }) - - _usefulLinksTable.accept(usefulLinkCellsModels) + refresh() } } + + func refresh() { + let usefulLinkCellsModels = applicationData.usefuleLinks.map({ usefulLink in + return UsefulLinkCellModel( + imageUrl: usefulLink.imageUrl, + title: usefulLink.title, + description: usefulLink.description + ) + }) + + _usefulLinksTable.accept(usefulLinkCellsModels) + } // MARK: - Private properties private let _usefulLinksTable = BehaviorRelay<[UsefulLinkCellModel]>(value: []) diff --git a/Trombi/Trombi/Application/Modules/UsefulLinks/Views/UsefulLinkTableViewCell.swift b/Trombi/Trombi/Application/Modules/UsefulLinks/Views/UsefulLinkTableViewCell.swift index 42516ff..5c10d30 100644 --- a/Trombi/Trombi/Application/Modules/UsefulLinks/Views/UsefulLinkTableViewCell.swift +++ b/Trombi/Trombi/Application/Modules/UsefulLinks/Views/UsefulLinkTableViewCell.swift @@ -8,7 +8,7 @@ import UIKit -struct UsefulLinkCellModel { +public struct UsefulLinkCellModel { let imageUrl: String let title: String diff --git a/Trombi/Trombi/Application/Modules/UserProfile/UserProfile.storyboard b/Trombi/Trombi/Application/Modules/UserProfile/UserProfile.storyboard index b1ca49a..8300766 100644 --- a/Trombi/Trombi/Application/Modules/UserProfile/UserProfile.storyboard +++ b/Trombi/Trombi/Application/Modules/UserProfile/UserProfile.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -44,7 +42,7 @@