diff --git a/Podfile b/Podfile index 457d3e25ca..c629de64f6 100644 --- a/Podfile +++ b/Podfile @@ -32,11 +32,14 @@ def shared_pods # Authentication SDKs pod '1PasswordExtension' pod 'Google/SignIn' + pod 'Typhoon' end target 'Rocket.Chat' do # Shared pods shared_pods + pod 'RxSwift', '~> 3.0' + pod 'RxCocoa', '~> 3.0' end target 'Rocket.ChatTests' do diff --git a/Podfile.lock b/Podfile.lock index b696eda0c6..c065895e9e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -39,11 +39,14 @@ PODS: - GTMSessionFetcher/Full (1.1.11): - GTMSessionFetcher/Core (= 1.1.11) - MobilePlayer (1.2.0) - - Realm (2.9.1): - - Realm/Headers (= 2.9.1) - - Realm/Headers (2.9.1) - - RealmSwift (2.9.1): - - Realm (= 2.9.1) + - Realm (2.8.3): + - Realm/Headers (= 2.8.3) + - Realm/Headers (2.8.3) + - RealmSwift (2.8.3): + - Realm (= 2.8.3) + - RxCocoa (3.5.0): + - RxSwift (~> 3.4) + - RxSwift (3.5.0) - SDWebImage (3.8.2): - SDWebImage/Core (= 3.8.2) - SDWebImage/Core (3.8.2) @@ -53,6 +56,14 @@ PODS: - Starscream (2.0.4) - SwiftyJSON (3.1.4) - TSMarkdownParser (2.1.3) + - Typhoon (4.0.2): + - Typhoon/DeallocNotifier (= 4.0.2) + - Typhoon/IntrospectionUtils (= 4.0.2) + - Typhoon/no-arc (= 4.0.2) + - Typhoon/DeallocNotifier (4.0.2) + - Typhoon/IntrospectionUtils (4.0.2) + - Typhoon/no-arc (4.0.2): + - Typhoon/IntrospectionUtils - URBMediaFocusViewController (0.9.0) DEPENDENCIES: @@ -62,6 +73,8 @@ DEPENDENCIES: - Google/SignIn - MobilePlayer - RealmSwift + - RxCocoa (~> 3.0) + - RxSwift (~> 3.0) - SDWebImage (~> 3.8) - semver - SideMenuController (from `https://github.com/rafaelks/SideMenuController.git`) @@ -69,6 +82,7 @@ DEPENDENCIES: - Starscream (~> 2.0.0) - SwiftyJSON - TSMarkdownParser + - Typhoon - URBMediaFocusViewController EXTERNAL SOURCES: @@ -93,8 +107,10 @@ SPEC CHECKSUMS: GTMOAuth2: 7fc9c10f5c745f4d9850419ea88889fe3baa6b7d GTMSessionFetcher: 5ad62e8200fa00ed011fe5e08d27fef72c5b1429 MobilePlayer: 069b13482499f14c25b6ce53f63a91e17975b073 - Realm: f91fb43bd474c4f731a116ebf7392c75dd015920 - RealmSwift: 207f12a4a36b696c5183c60a1c06d70234a23e56 + Realm: 3601ef091c8c499a31101d8563b991e75546cdce + RealmSwift: 8183818515471b01a99abdd2970f8e4fd52b6f4a + RxCocoa: a0a09f45d0e5b48ecb6a4a7b4b4c89c88d3f633f + RxSwift: 18ee9d78b45edb3b0b7e79916b47a116e6dbc842 SDWebImage: 098e97e6176540799c27e804c96653ee0833d13c semver: efe6bf4af25bffab18d442592771be392210b5ce SideMenuController: 44670bc1e1c58d9460fc028e246926227edefec0 @@ -102,8 +118,9 @@ SPEC CHECKSUMS: Starscream: df5974ee928b157c8eda8af8de7c620276b7dfcc SwiftyJSON: c2842d878f95482ffceec5709abc3d05680c0220 TSMarkdownParser: 114779f14d46e7fc6d9880d4797e5abcc01f92c3 + Typhoon: 05db9d33d798b90c202bf3f754275c03efe93297 URBMediaFocusViewController: 26779e301fe75ec0152fbe8b476bd06ccee9f9b3 -PODFILE CHECKSUM: cfd52ac0a6d692b61877e0c2a5228a9763f3cdfd +PODFILE CHECKSUM: 255285c8818cf0cb3da7b41b550e0ed879532eb8 COCOAPODS: 1.2.1 diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 922b172ff3..7e5352989e 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -58,7 +58,6 @@ 4159720C1D3DB854002258F4 /* Email.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4159720B1D3DB854002258F4 /* Email.swift */; }; 4159720E1D3DB882002258F4 /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4159720D1D3DB882002258F4 /* Mention.swift */; }; 415972101D3DBDA0002258F4 /* RealmExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4159720F1D3DBDA0002258F4 /* RealmExtension.swift */; }; - 41597DCE1E8D3C5B00638E3E /* TwoFactorAuthenticationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41597DCD1E8D3C5B00638E3E /* TwoFactorAuthenticationViewController.swift */; }; 416133321D46CA4E00E09DA2 /* ChatMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416133311D46CA4E00E09DA2 /* ChatMessageCell.swift */; }; 416133341D46CA7200E09DA2 /* ChatMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 416133331D46CA7200E09DA2 /* ChatMessageCell.xib */; }; 416133381D46DB1D00E09DA2 /* BaseModelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416133371D46DB1D00E09DA2 /* BaseModelSpec.swift */; }; @@ -140,7 +139,6 @@ 41DCB8281DDC82E000E1197F /* SubscriptionSearchMoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41DCB8271DDC82E000E1197F /* SubscriptionSearchMoreView.swift */; }; 41DF76E31D2C50710028DBF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41DF76E21D2C50710028DBF8 /* AppDelegate.swift */; }; 41DF76E81D2C50710028DBF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 41DF76E61D2C50710028DBF8 /* Main.storyboard */; }; - 41DF76EA1D2C50710028DBF8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 41DF76E91D2C50710028DBF8 /* Assets.xcassets */; }; 41DF76ED1D2C50720028DBF8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 41DF76EB1D2C50720028DBF8 /* LaunchScreen.storyboard */; }; 41DF77031D2C50720028DBF8 /* RocketChatUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41DF77021D2C50720028DBF8 /* RocketChatUITests.swift */; }; 41E2F9FF1D414DE800238DFD /* Chat.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 41E2F9FE1D414DE800238DFD /* Chat.storyboard */; }; @@ -162,6 +160,14 @@ 597ECBA21E3708A50041C5C5 /* DataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 597ECBA11E3708A50041C5C5 /* DataExtension.swift */; }; 597ECBA41E3708B10041C5C5 /* PushManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 597ECBA31E3708B10041C5C5 /* PushManager.swift */; }; 68D186DF1ED9714F0030EE8C /* MessageURLSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68D186DE1ED9714F0030EE8C /* MessageURLSpec.swift */; }; + 7308DFBB1F28C78C00F77C28 /* AuthStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7308DFBA1F28C78C00F77C28 /* AuthStates.swift */; }; + 734A2E491F26231300A902B0 /* AuthInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 734A2E481F26231300A902B0 /* AuthInteractor.swift */; }; + 737DA8A81F4D9EA90036DACD /* HTTPResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 737DA8A71F4D9EA80036DACD /* HTTPResponse.swift */; }; + 737DA8AA1F502C8C0036DACD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 737DA8A91F502C8C0036DACD /* Assets.xcassets */; }; + 73904E721F1FAD8D00FBDB7B /* CoreComponentsAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = 73904E711F1FAD8D00FBDB7B /* CoreComponentsAssembly.m */; }; + 73904E791F1FBF0500FBDB7B /* Configuration.plist in Resources */ = {isa = PBXBuildFile; fileRef = 73904E781F1FBF0500FBDB7B /* Configuration.plist */; }; + 73DD56371F1FAB3100821775 /* ApplicationAssembly.m in Sources */ = {isa = PBXBuildFile; fileRef = 73DD56361F1FAB3100821775 /* ApplicationAssembly.m */; }; + 73FBA8931F3DE5CC00DE7692 /* TitleFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FBA8921F3DE5CC00DE7692 /* TitleFormatter.swift */; }; 7DE1B07114BBD1D46E9CC71B /* Pods_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F5191CD6C53AEA006C82524 /* Pods_Rocket_Chat.framework */; }; 925FF74E1E8EFB3E00982043 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925FF74D1E8EFB3E00982043 /* SettingsViewModel.swift */; }; 925FF7511E8EFCAD00982043 /* SettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925FF7501E8EFCAD00982043 /* SettingsViewModelTests.swift */; }; @@ -242,7 +248,6 @@ 4159720B1D3DB854002258F4 /* Email.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Email.swift; path = Models/Email.swift; sourceTree = ""; }; 4159720D1D3DB882002258F4 /* Mention.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Mention.swift; path = Models/Mention.swift; sourceTree = ""; }; 4159720F1D3DBDA0002258F4 /* RealmExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RealmExtension.swift; path = Extensions/RealmExtension.swift; sourceTree = ""; }; - 41597DCD1E8D3C5B00638E3E /* TwoFactorAuthenticationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TwoFactorAuthenticationViewController.swift; path = Controllers/Auth/TwoFactorAuthenticationViewController.swift; sourceTree = ""; }; 416133311D46CA4E00E09DA2 /* ChatMessageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatMessageCell.swift; path = Views/Cells/Chat/ChatMessageCell.swift; sourceTree = ""; }; 416133331D46CA7200E09DA2 /* ChatMessageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatMessageCell.xib; path = Views/Cells/Chat/ChatMessageCell.xib; sourceTree = ""; }; 416133371D46DB1D00E09DA2 /* BaseModelSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BaseModelSpec.swift; path = Models/BaseModelSpec.swift; sourceTree = ""; }; @@ -325,7 +330,6 @@ 41DF76DF1D2C50710028DBF8 /* Rocket.Chat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rocket.Chat.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41DF76E21D2C50710028DBF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 41DF76E71D2C50710028DBF8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 41DF76E91D2C50710028DBF8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 41DF76EC1D2C50720028DBF8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 41DF76EE1D2C50720028DBF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 41DF76F31D2C50720028DBF8 /* Rocket.ChatTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Rocket.ChatTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -358,6 +362,16 @@ 597ECBA31E3708B10041C5C5 /* PushManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PushManager.swift; path = Managers/PushManager.swift; sourceTree = ""; }; 68D186DE1ED9714F0030EE8C /* MessageURLSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MessageURLSpec.swift; path = Models/MessageURLSpec.swift; sourceTree = ""; }; 68D870A8D54F5431A14607AE /* Pods_Rocket_ChatTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rocket_ChatTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7308DFBA1F28C78C00F77C28 /* AuthStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthStates.swift; sourceTree = ""; }; + 734A2E481F26231300A902B0 /* AuthInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AuthInteractor.swift; path = Interactors/AuthInteractor.swift; sourceTree = ""; }; + 737DA8A71F4D9EA80036DACD /* HTTPResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPResponse.swift; sourceTree = ""; }; + 737DA8A91F502C8C0036DACD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 73904E701F1FAD8D00FBDB7B /* CoreComponentsAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreComponentsAssembly.h; path = Assembly/CoreComponentsAssembly.h; sourceTree = ""; }; + 73904E711F1FAD8D00FBDB7B /* CoreComponentsAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoreComponentsAssembly.m; path = Assembly/CoreComponentsAssembly.m; sourceTree = ""; }; + 73904E781F1FBF0500FBDB7B /* Configuration.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Configuration.plist; path = Assembly/Configuration.plist; sourceTree = ""; }; + 73DD56351F1FAB3100821775 /* ApplicationAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ApplicationAssembly.h; path = Assembly/ApplicationAssembly.h; sourceTree = ""; }; + 73DD56361F1FAB3100821775 /* ApplicationAssembly.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ApplicationAssembly.m; path = Assembly/ApplicationAssembly.m; sourceTree = ""; }; + 73FBA8921F3DE5CC00DE7692 /* TitleFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TitleFormatter.swift; path = Helpers/TitleFormatter.swift; sourceTree = ""; }; 925FF74D1E8EFB3E00982043 /* SettingsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = ""; }; 925FF7501E8EFCAD00982043 /* SettingsViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewModelTests.swift; sourceTree = ""; }; A0FFC1601E8A9D8D00A1B5EA /* TintedTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TintedTextField.swift; path = Views/Subscriptions/TintedTextField.swift; sourceTree = ""; }; @@ -428,6 +442,7 @@ 414A1FFB1D46395900093E10 /* SocketResponse.swift */, 4162E1541D654A7400AAAE49 /* SocketHandlers.swift */, 414A1FF51D46320F00093E10 /* ResponseMessage.swift */, + 737DA8A71F4D9EA80036DACD /* HTTPResponse.swift */, ); name = Response; sourceTree = ""; @@ -589,12 +604,12 @@ 4174CB101D2D997E0086DAC8 /* Auth */ = { isa = PBXGroup; children = ( - 4174CB0C1D2D994A0086DAC8 /* ConnectServerViewController.swift */, + 7308DFBA1F28C78C00F77C28 /* AuthStates.swift */, 4174CB161D2D9BB70086DAC8 /* AuthViewController.swift */, + 4174CB0C1D2D994A0086DAC8 /* ConnectServerViewController.swift */, 414D99151EA0E7CB0020F7E9 /* SignupViewController.swift */, 412719431E6B353B00461FEE /* AuthViewControllerGoogleExtensions.swift */, 412719451E6B403700461FEE /* RegisterUsernameViewController.swift */, - 41597DCD1E8D3C5B00638E3E /* TwoFactorAuthenticationViewController.swift */, ); name = Auth; sourceTree = ""; @@ -775,6 +790,7 @@ isa = PBXGroup; children = ( 41D701D51E67111E00FED2EE /* MessageTextFontAttributes.swift */, + 73FBA8921F3DE5CC00DE7692 /* TitleFormatter.swift */, 413996161F3B44500075F96E /* UploadHelper.swift */, 41D4ABAA1F4CD10C00ACDDDD /* ChatCollectionViewFlowLayout.swift */, ); @@ -816,6 +832,9 @@ 41DF76E11D2C50710028DBF8 /* Rocket.Chat */ = { isa = PBXGroup; children = ( + 737DA8A91F502C8C0036DACD /* Assets.xcassets */, + 734A2E471F2622D300A902B0 /* Interactors */, + 73DD562F1F1F798800821775 /* Assembly */, 4199A9861DABCC2E0035F820 /* External */, 41A79C0D1D2F084F00A1968E /* Models */, 4174CB1D1D2DB3270086DAC8 /* Extensions */, @@ -826,7 +845,6 @@ 4174CB0A1D2D990F0086DAC8 /* Controllers */, 41DF76E21D2C50710028DBF8 /* AppDelegate.swift */, 4174CB201D2DD4690086DAC8 /* Rocket.Chat-Bridge.h */, - 41DF76E91D2C50710028DBF8 /* Assets.xcassets */, 41DF76EE1D2C50720028DBF8 /* Info.plist */, 41833F4D1DEF16B600E54655 /* Keys.plist */, 4116C52C1E69B15400AC4E43 /* GoogleService-Info.plist */, @@ -904,6 +922,26 @@ name = Socket; sourceTree = ""; }; + 734A2E471F2622D300A902B0 /* Interactors */ = { + isa = PBXGroup; + children = ( + 734A2E481F26231300A902B0 /* AuthInteractor.swift */, + ); + name = Interactors; + sourceTree = ""; + }; + 73DD562F1F1F798800821775 /* Assembly */ = { + isa = PBXGroup; + children = ( + 73DD56351F1FAB3100821775 /* ApplicationAssembly.h */, + 73DD56361F1FAB3100821775 /* ApplicationAssembly.m */, + 73904E701F1FAD8D00FBDB7B /* CoreComponentsAssembly.h */, + 73904E711F1FAD8D00FBDB7B /* CoreComponentsAssembly.m */, + 73904E781F1FBF0500FBDB7B /* Configuration.plist */, + ); + name = Assembly; + sourceTree = ""; + }; 925FF74F1E8EFC9200982043 /* Settings */ = { isa = PBXGroup; children = ( @@ -1026,7 +1064,7 @@ TargetAttributes = { 41DF76DE1D2C50710028DBF8 = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = S6UPZG7ZR3; + DevelopmentTeam = BLCC5NH78A; LastSwiftMigration = 0810; SystemCapabilities = { com.apple.BackgroundModes = { @@ -1105,9 +1143,11 @@ 41D894041F4EF65700E284D2 /* ChatDirectMessageHeaderCell.xib in Resources */, 41EB22361E5F056600AA3AE7 /* Localizable.strings in Resources */, 41E2F9FF1D414DE800238DFD /* Chat.storyboard in Resources */, + 73904E791F1FBF0500FBDB7B /* Configuration.plist in Resources */, 41DF76E81D2C50710028DBF8 /* Main.storyboard in Resources */, 41F167EB1DAC4D5500775CCA /* ChatTitleView.xib in Resources */, 41FF36071DBEC0BA0074E20A /* ChatMessageVideoView.xib in Resources */, + 737DA8AA1F502C8C0036DACD /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1419,6 +1459,7 @@ 41ADDD491E9DBB100007A458 /* LoaderView.swift in Sources */, 411F7D941F5179A50080E8AD /* ChatChannelHeaderCell.swift in Sources */, 41F167E91DAC4D4300775CCA /* ChatTitleView.swift in Sources */, + 7308DFBB1F28C78C00F77C28 /* AuthStates.swift in Sources */, 41552F661D30308C0081438D /* AuthManager.swift in Sources */, 415972101D3DBDA0002258F4 /* RealmExtension.swift in Sources */, 413996171F3B44500075F96E /* UploadHelper.swift in Sources */, @@ -1446,6 +1487,7 @@ 41A1748C1DD9F2F900188E3B /* UIViewControllerExtension.swift in Sources */, 41D701D61E67111E00FED2EE /* MessageTextFontAttributes.swift in Sources */, 41C275DF1D848005003C88CF /* AvatarView.swift in Sources */, + 734A2E491F26231300A902B0 /* AuthInteractor.swift in Sources */, A0FFC1611E8A9D8D00A1B5EA /* TintedTextField.swift in Sources */, 4174CB171D2D9BB70086DAC8 /* AuthViewController.swift in Sources */, 418688111E53CC86002F785C /* ChatControllerMessageActions.swift in Sources */, @@ -1461,6 +1503,7 @@ 41BD37E11E290F2900CBC4C2 /* UserModelMapping.swift in Sources */, 412BCC871E55C6B800F7F4EE /* ChatMessageTextView.swift in Sources */, 414D99161EA0E7CB0020F7E9 /* SignupViewController.swift in Sources */, + 73DD56371F1FAB3100821775 /* ApplicationAssembly.m in Sources */, 41A79C0F1D2F085F00A1968E /* User.swift in Sources */, 41E2FA071D41513C00238DFD /* ChatViewController.swift in Sources */, 4151B45E1E2D32EA00F8AA1B /* MessageURLModelMapping.swift in Sources */, @@ -1481,9 +1524,11 @@ 41A91AF11E51CD41005C94B1 /* SubscriptionUserStatusView.swift in Sources */, 412731D71DE0A89B00FC45A0 /* ChatPreviewModeView.swift in Sources */, 4180204F1E718E370012A092 /* ChannelInfoViewController.swift in Sources */, + 73FBA8931F3DE5CC00DE7692 /* TitleFormatter.swift in Sources */, 41C45AEF1DFAD42800D9969C /* ChatDataController.swift in Sources */, 41EE157E1E05BED600754D45 /* ChatControllerAutocomplete.swift in Sources */, 4162E1531D651A8800AAAE49 /* UserManager.swift in Sources */, + 737DA8A81F4D9EA90036DACD /* HTTPResponse.swift in Sources */, 4112BEEC1E7971A400E734CB /* MainChatViewController.swift in Sources */, 419ECCA41F3CA21A005F224B /* DownloadManager.swift in Sources */, 419D85001DF599DA0021F034 /* ChatHeaderViewStatus.swift in Sources */, @@ -1500,6 +1545,7 @@ 411D76E51F39F05A00B0A8DF /* AuthSettingsManager.swift in Sources */, 415029B51E72D519009F596C /* ChannelInfoBasicCell.swift in Sources */, D32E28251DFD86C300D6019C /* LauncherProtocol.swift in Sources */, + 73904E721F1FAD8D00FBDB7B /* CoreComponentsAssembly.m in Sources */, 41DF76E31D2C50710028DBF8 /* AppDelegate.swift in Sources */, 4174CB131D2D99960086DAC8 /* BaseViewController.swift in Sources */, 597ECBA21E3708A50041C5C5 /* DataExtension.swift in Sources */, @@ -1702,11 +1748,11 @@ CODE_SIGN_ENTITLEMENTS = Rocket.Chat/Rocket.Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = S6UPZG7ZR3; + DEVELOPMENT_TEAM = BLCC5NH78A; INFOPLIST_FILE = Rocket.Chat/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.ios; + PRODUCT_BUNDLE_IDENTIFIER = com.seekingalpha.MarketChat; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = "Rocket.Chat/Rocket.Chat-Bridge.h"; @@ -1723,11 +1769,11 @@ CODE_SIGN_ENTITLEMENTS = Rocket.Chat/Rocket.Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = S6UPZG7ZR3; + DEVELOPMENT_TEAM = BLCC5NH78A; INFOPLIST_FILE = Rocket.Chat/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.ios; + PRODUCT_BUNDLE_IDENTIFIER = com.seekingalpha.MarketChat; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = "Rocket.Chat/Rocket.Chat-Bridge.h"; diff --git a/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme b/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme index 9777d4c8f5..3cd5f2cf56 100644 --- a/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme +++ b/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme @@ -63,7 +63,7 @@ +#import + +@interface ApplicationAssembly : TyphoonAssembly +@end diff --git a/Rocket.Chat/Assembly/ApplicationAssembly.m b/Rocket.Chat/Assembly/ApplicationAssembly.m new file mode 100644 index 0000000000..51e536cb9c --- /dev/null +++ b/Rocket.Chat/Assembly/ApplicationAssembly.m @@ -0,0 +1,30 @@ +// +// ApplicationAssembly.m +// Rocket.Chat +// +// Created by Alexander Bugara on 7/19/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +#import "ApplicationAssembly.h" +#import "Rocket_Chat-Swift.h" + +@implementation ApplicationAssembly + +- (AuthViewController *)connectServerViewController { + return [TyphoonDefinition + withClass:[AuthViewController class] + configuration:^(TyphoonDefinition *definition) { + [definition injectProperty:@selector(serverURL) with:TyphoonConfig(@"serverURL")]; + [definition injectProperty:@selector(login) with:TyphoonConfig(@"login")]; + [definition injectProperty:@selector(password) with:TyphoonConfig(@"password")]; + [definition injectProperty:@selector(interactor) with:[AuthInteractor new]]; + [definition injectProperty:@selector(stateMachine) with:[AuthStateMachine new]]; + }]; +} + +- (id)config { + return [TyphoonDefinition withConfigName:@"Configuration.plist"]; +} + +@end diff --git a/Rocket.Chat/Assembly/Configuration.plist b/Rocket.Chat/Assembly/Configuration.plist new file mode 100644 index 0000000000..f1fd134f1b --- /dev/null +++ b/Rocket.Chat/Assembly/Configuration.plist @@ -0,0 +1,12 @@ + + + + + serverURL + NSURL(http://rc.staging.seekingalpha.com) + login + semion@seekingalpha.com + password + 123456 + + diff --git a/Rocket.Chat/Assembly/CoreComponentsAssembly.h b/Rocket.Chat/Assembly/CoreComponentsAssembly.h new file mode 100644 index 0000000000..2c78949182 --- /dev/null +++ b/Rocket.Chat/Assembly/CoreComponentsAssembly.h @@ -0,0 +1,13 @@ +// +// CoreComponentsAssembly.h +// Rocket.Chat +// +// Created by Alexander Bugara on 7/19/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +#import +#import + +@interface CoreComponentsAssembly : TyphoonAssembly +@end diff --git a/Rocket.Chat/Assembly/CoreComponentsAssembly.m b/Rocket.Chat/Assembly/CoreComponentsAssembly.m new file mode 100644 index 0000000000..f604b5f983 --- /dev/null +++ b/Rocket.Chat/Assembly/CoreComponentsAssembly.m @@ -0,0 +1,12 @@ +// +// CoreComponentsAssembly.m +// Rocket.Chat +// +// Created by Alexander Bugara on 7/19/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +#import "CoreComponentsAssembly.h" + +@implementation CoreComponentsAssembly +@end diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Contents.json b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Contents.json index bfdf653de2..06aba2f0d3 100644 --- a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,25 +1,27 @@ { "images" : [ { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-Small-41.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "Icon-Small.png", + "filename" : "Icon-Small-1.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "Icon-Small@2x.png", + "filename" : "Icon-Small@2x-1.png", "scale" : "2x" }, { @@ -31,13 +33,13 @@ { "size" : "40x40", "idiom" : "iphone", - "filename" : "Icon-40@2x.png", + "filename" : "Icon-Small-40@2x-1.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", - "filename" : "Icon-40@3x.png", + "filename" : "Icon-Small-40@3x.png", "scale" : "3x" }, { @@ -65,13 +67,15 @@ "scale" : "3x" }, { - "idiom" : "ipad", "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-Small-20.png", "scale" : "1x" }, { - "idiom" : "ipad", "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-Small-42.png", "scale" : "2x" }, { @@ -89,13 +93,13 @@ { "size" : "40x40", "idiom" : "ipad", - "filename" : "Icon-40.png", + "filename" : "Icon-Small-40.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", - "filename" : "Icon-40@2x.png", + "filename" : "Icon-Small-40@2x.png", "scale" : "2x" }, { @@ -137,7 +141,7 @@ { "size" : "83.5x83.5", "idiom" : "ipad", - "filename" : "Icon-83.5@2x.png", + "filename" : "Icon-167@2x.png", "scale" : "2x" } ], diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-167@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-167@2x.png new file mode 100644 index 0000000000..c85b52a0dd Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-167@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40.png deleted file mode 100644 index af4ef575bf..0000000000 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40.png and /dev/null differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index b2ddf6c47e..0000000000 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png and /dev/null differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png deleted file mode 100644 index d08e16a6fb..0000000000 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png and /dev/null differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100644 index 0000000000..a9ce4b4c8a Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png index d08e16a6fb..736e02ea27 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png index b04a9c3bfc..c5faf892a4 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72.png index b3070d5f09..d0a13ee318 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png index 50fa3bf232..2e5be0c602 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76.png index f6eaff7c81..ebbf1267f8 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png index 4d89c18a51..b44b39251d 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png deleted file mode 100644 index e6c4fa566c..0000000000 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png and /dev/null differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-1.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-1.png new file mode 100644 index 0000000000..33130dd77f Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-1.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-20.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-20.png new file mode 100644 index 0000000000..2fb07f7c61 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-20.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100644 index 0000000000..446d13b8a9 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png new file mode 100644 index 0000000000..322a34158e Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100644 index 0000000000..322a34158e Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100644 index 0000000000..8ab676d61c Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-41.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-41.png new file mode 100644 index 0000000000..446d13b8a9 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-41.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-42.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-42.png new file mode 100644 index 0000000000..446d13b8a9 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-42.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png index e0eb084f5c..89edfff8f4 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png index 114f9cbe16..0e0125beb9 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small.png index 8b68e42fe0..33130dd77f 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png new file mode 100644 index 0000000000..cbb515a11e Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png index 6841b12c0e..cbb515a11e 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png index f6ec32942e..d7e21ba684 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon.png index 2b64c8c45b..d84b0f9609 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon.png differ diff --git a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon@2x.png b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon@2x.png index 747d866fec..ec00943835 100644 Binary files a/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon@2x.png and b/Rocket.Chat/Assets.xcassets/AppIcon.appiconset/Icon@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/Contents.json new file mode 100644 index 0000000000..6630155c77 --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "rectangle-1209-copy.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1209-copy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1209-copy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy.png b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy.png new file mode 100644 index 0000000000..cda0db0868 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@2x.png b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@2x.png new file mode 100644 index 0000000000..919c8b04fd Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@3x.png b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@3x.png new file mode 100644 index 0000000000..084bb2c525 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Background.imageset/rectangle-1209-copy@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Contents.json b/Rocket.Chat/Assets.xcassets/Auth/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Auth/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/Contents.json new file mode 100644 index 0000000000..ffbc6e03b5 --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "logo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "logo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "logo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo.png b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo.png new file mode 100644 index 0000000000..12944dc064 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@2x.png b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@2x.png new file mode 100644 index 0000000000..d3871fd4b2 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@3x.png b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@3x.png new file mode 100644 index 0000000000..a60fa4abbf Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/Logo.imageset/logo@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/Contents.json new file mode 100644 index 0000000000..f9ef8eb60e --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "rounded-rectangle-1.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rounded-rectangle-1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rounded-rectangle-1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1.png b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1.png new file mode 100644 index 0000000000..7741e1ab13 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@2x.png b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@2x.png new file mode 100644 index 0000000000..3b46f134ad Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@3x.png b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@3x.png new file mode 100644 index 0000000000..cc2f6be7dd Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Auth/TextField.imageset/rounded-rectangle-1@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/Contents.json new file mode 100644 index 0000000000..23d3c0d32b --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "rectangle-1205-copy-2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1205-copy-2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1205-copy-2@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2.png b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2.png new file mode 100644 index 0000000000..2b37648e3b Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2.png differ diff --git a/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@2x.png b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@2x.png new file mode 100644 index 0000000000..94c3fd7180 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@3x.png b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@3x.png new file mode 100644 index 0000000000..cc9386800e Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Icons/MenuMod.imageset/rectangle-1205-copy-2@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/Contents.json b/Rocket.Chat/Assets.xcassets/Menu/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Menu/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/Contents.json new file mode 100644 index 0000000000..bdd448090a --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "rectangle-1209.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1209@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rectangle-1209@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209.png b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209.png new file mode 100644 index 0000000000..93bd33a20a Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@2x.png b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@2x.png new file mode 100644 index 0000000000..f2e760364d Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@3x.png b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@3x.png new file mode 100644 index 0000000000..9dc978c657 Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/MenuBacground.imageset/rectangle-1209@3x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/Contents.json b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/Contents.json new file mode 100644 index 0000000000..062277ce16 --- /dev/null +++ b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "layer-6.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "layer-6@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "layer-6@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6.png b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6.png new file mode 100644 index 0000000000..6a36cb39af Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@2x.png b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@2x.png new file mode 100644 index 0000000000..9a1119306a Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@2x.png differ diff --git a/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@3x.png b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@3x.png new file mode 100644 index 0000000000..df701ecb9f Binary files /dev/null and b/Rocket.Chat/Assets.xcassets/Menu/UserIcon.imageset/layer-6@3x.png differ diff --git a/Rocket.Chat/AuthStates.swift b/Rocket.Chat/AuthStates.swift new file mode 100644 index 0000000000..e3836235e4 --- /dev/null +++ b/Rocket.Chat/AuthStates.swift @@ -0,0 +1,159 @@ +// +// AuthStates.swift +// Rocket.Chat +// +// Created by Alexander Bugara on 7/26/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import Foundation +import RxSwift +import RxCocoa + +protocol AuthState { + var authViewController: AuthViewController { get set } + init(authViewController: AuthViewController) + func execute() +} + +protocol TransitionState { + func success() -> AuthState? + func failure() -> AuthState? +} + +struct FirstLoadingState: AuthState { + var authViewController: AuthViewController + init(authViewController: AuthViewController) { + self.authViewController = authViewController + } + let disposeBag = DisposeBag() + func execute() { + self.authViewController.contentContainer.isHidden = true + self.authViewController.customActivityIndicator.startAnimating() + self.authViewController.textFieldUsername.resignFirstResponder() + self.authViewController.textFieldPassword.resignFirstResponder() + + let authSharedObservable = self.authViewController.interactor?.checkAuth()?.shareReplay(1) + _ = authSharedObservable?.filter { value in + return value == false + }.flatMap { _ -> Observable> in + return (self.authViewController.interactor?.validate(URL: self.authViewController.serverURL))! + }.flatMap {result -> Observable> in + var result1: Observable>? + switch result { + case .success(let socketURL): + result1 = (self.authViewController.interactor?.connect(socketURL: socketURL))! + default: + break + } + return result1! + }.subscribe( onNext: {result in + switch result { + case .success(let serverSettings): + self.authViewController.serverPublicSettings = serverSettings + self.authViewController.finishExecution(nextState: ShowLoginState(authViewController: self.authViewController)) + default: + break + } + }).disposed(by: disposeBag) + + _ = authSharedObservable?.filter {value in + return value == true + }.subscribe( onNext: {_ in + self.authViewController.finishExecution(nextState: ShowChatState(authViewController: self.authViewController)) + }).disposed(by: disposeBag) + } +} + +struct ShowLoginState: AuthState, TransitionState { + var authViewController: AuthViewController + init(authViewController: AuthViewController) { + self.authViewController = authViewController + } + func execute() { + self.authViewController.contentContainer.isHidden = false + self.authViewController.customActivityIndicator.stopAnimating() + self.authViewController.textFieldUsername.becomeFirstResponder() + } + func success() -> AuthState? { + return LoginInProgressState(authViewController: self.authViewController) + } + func failure() -> AuthState? { + return nil + } + +} + +struct ShowChatState: AuthState { + var authViewController: AuthViewController + init(authViewController: AuthViewController) { + self.authViewController = authViewController + } + func execute() { + self.authViewController.contentContainer.isHidden = false + self.authViewController.customActivityIndicator.stopAnimating() + self.authViewController.showChat() + self.authViewController.finishExecution(nextState: nil) + } +} + +struct LoginInProgressState: AuthState, TransitionState { + var authViewController: AuthViewController + init(authViewController: AuthViewController) { + self.authViewController = authViewController + } + func execute() { + self.authViewController.authenticateWithUsernameOrEmail() + } + func success() -> AuthState? { + return LoginSuccessState(authViewController: self.authViewController) + } + func failure() -> AuthState? { + return ShowLoginState(authViewController: self.authViewController) + } +} + +struct LoginSuccessState: AuthState { + var authViewController: AuthViewController + init(authViewController: AuthViewController) { + self.authViewController = authViewController + } + let disposeBag = DisposeBag() + func execute() { + self.authViewController.startLoading() + _ = self.authViewController.interactor?.checkAuth()?.filter {value in + return value == true + }.subscribe( onNext: {_ in + if let user = AuthManager.currentUser() { + if user.username != nil { + self.authViewController.stopLoading() + self.authViewController.showChat() + } + } + }).disposed(by: disposeBag) + } +} + +class AuthStateMachine: NSObject { + private var currentState: AuthState? + func switchState(state: AuthState?) { + self.currentState = state + } + func execute() { + self.currentState?.execute() + } + func success() { + guard let transitinableState = self.currentState as? TransitionState else { + return + } + self.currentState = transitinableState.success() + self.execute() + } + func error() { + guard let transitinableState = self.currentState as? TransitionState else { + return + } + self.currentState = transitinableState.failure() + } + +} diff --git a/Rocket.Chat/Controllers/Auth/AuthViewController.swift b/Rocket.Chat/Controllers/Auth/AuthViewController.swift index b7caacf5fe..0ec9082dc9 100644 --- a/Rocket.Chat/Controllers/Auth/AuthViewController.swift +++ b/Rocket.Chat/Controllers/Auth/AuthViewController.swift @@ -12,19 +12,15 @@ import SafariServices import OnePasswordExtension final class AuthViewController: BaseViewController { - + var interactor: AuthInteractor? internal var connecting = false - var serverURL: URL! + var serverURL: URL? var serverPublicSettings: AuthSettings? - - @IBOutlet weak var viewFields: UIView! { - didSet { - viewFields.layer.cornerRadius = 4 - viewFields.layer.borderColor = UIColor.RCLightGray().cgColor - viewFields.layer.borderWidth = 0.5 - } - } - + var login: String? + var password: String? + var stateMachine: AuthStateMachine? + @IBOutlet weak var contentContainer: UIView! + @IBOutlet weak var viewFields: UIView! @IBOutlet weak var onePasswordButton: UIButton! { didSet { onePasswordButton.isHidden = !OnePasswordExtension.shared().isAppExtensionAvailable() @@ -34,24 +30,36 @@ final class AuthViewController: BaseViewController { @IBOutlet weak var textFieldUsername: UITextField! @IBOutlet weak var textFieldPassword: UITextField! @IBOutlet weak var visibleViewBottomConstraint: NSLayoutConstraint! + @IBOutlet weak var activityIndicator: UIActivityIndicatorView! + @IBOutlet weak var textInfoLabel: UILabel! + @IBOutlet weak var signInButton: UIButton! - @IBOutlet weak var buttonAuthenticateGoogle: UIButton! { + var customActivityIndicator: LoaderView! + + @IBOutlet weak var activityIndicatorContainer: UIView! { didSet { - buttonAuthenticateGoogle.layer.cornerRadius = 3 + let width = activityIndicatorContainer.bounds.width + let height = activityIndicatorContainer.bounds.height + let frame = CGRect(x: 0, y: 0, width: width, height: height) + let activityIndicator = LoaderView(frame: frame) + activityIndicator.color = .white + activityIndicatorContainer.addSubview(activityIndicator) + self.customActivityIndicator = activityIndicator } } - - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! - - deinit { - NotificationCenter.default.removeObserver(self) - } - override func viewDidLoad() { super.viewDidLoad() - title = serverURL.host - - self.updateAuthenticationMethods() + if let navigationBar = navigationController?.navigationBar { + navigationBar.setBackgroundImage(UIImage(), for: .default) + navigationBar.shadowImage = UIImage() + navigationBar.isTranslucent = true + navigationController?.view?.backgroundColor = .clear + } + AuthManager.recoverAuthIfNeeded() + self.textFieldUsername.text = self.login + self.textFieldPassword.text = self.password + self.stateMachine?.switchState(state: FirstLoadingState(authViewController: self)) + self.stateMachine?.execute() } override func viewDidAppear(_ animated: Bool) { @@ -70,19 +78,11 @@ final class AuthViewController: BaseViewController { name: NSNotification.Name.UIKeyboardWillHide, object: nil ) - - if !connecting { - textFieldUsername.becomeFirstResponder() - } } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if segue.identifier == "TwoFactor" { - if let controller = segue.destination as? TwoFactorAuthenticationViewController { - controller.username = textFieldUsername.text ?? "" - controller.password = textFieldPassword.text ?? "" - } - } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(true) + NotificationCenter.default.removeObserver(self) } // MARK: Keyboard Handlers @@ -96,41 +96,58 @@ final class AuthViewController: BaseViewController { visibleViewBottomConstraint.constant = 0 } - // MARK: Authentication methods - fileprivate func updateAuthenticationMethods() { - guard let settings = self.serverPublicSettings else { return } - self.buttonAuthenticateGoogle.isHidden = !settings.isGoogleAuthenticationEnabled - } - internal func handleAuthenticationResponse(_ response: SocketResponse) { stopLoading() - if response.isError() { - if let error = response.result["error"].dictionary { - // User is using 2FA - if error["error"]?.string == "totp-required" { - performSegue(withIdentifier: "TwoFactor", sender: nil) - return - } - - let alert = UIAlertController( - title: localized("error.socket.default_error_title"), - message: error["message"]?.string ?? localized("error.socket.default_error_message"), - preferredStyle: .alert - ) - - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) - present(alert, animated: true, completion: nil) - } +// if response.isError() { +// if let error = response.result["error"].dictionary { +// let code = error["error"]?.int +// if code != nil && code == 403 { +// performSegue(withIdentifier: "403", sender: nil) +// } else { +// let alert = UIAlertController( +// title: localized("error.socket.default_error_title"), +// message: error["message"]?.string ?? localized("error.socket.default_error_message"), +// preferredStyle: .alert +// ) +// +// alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) +// present(alert, animated: true, completion: nil) +// } +// } +// self.stateMachine?.error() +// } else { + self.stateMachine?.success() +// } + } + + internal func loginResponse(_ response: HTTPResponse) { + stopLoading() + if !response.isError { + self.stateMachine?.success() } else { - if let user = AuthManager.currentUser() { - if user.username != nil { - dismiss(animated: true, completion: nil) - } else { - performSegue(withIdentifier: "RequestUsername", sender: nil) - } - } + self.stateMachine?.error() } + +// if response.isError() { +// if let error = response.result["error"].dictionary { +// let code = error["error"]?.int +// if code != nil && code == 403 { +// performSegue(withIdentifier: "403", sender: nil) +// } else { +// let alert = UIAlertController( +// title: localized("error.socket.default_error_title"), +// message: error["message"]?.string ?? localized("error.socket.default_error_message"), +// preferredStyle: .alert +// ) +// +// alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) +// present(alert, animated: true, completion: nil) +// } +// } +// self.stateMachine?.error() +// } else { +// } } // MARK: Loaders @@ -154,21 +171,10 @@ final class AuthViewController: BaseViewController { func authenticateWithUsernameOrEmail() { let email = textFieldUsername.text ?? "" let password = textFieldPassword.text ?? "" - startLoading() - - if serverPublicSettings?.isLDAPAuthenticationEnabled ?? false { - let params = [ - "ldap": true, - "username": email, - "ldapPass": password, - "ldapOptions": [] - ] as [String : Any] - - AuthManager.auth(params: params, completion: self.handleAuthenticationResponse) - } else { - AuthManager.auth(email, password: password, completion: self.handleAuthenticationResponse) - } + let params = ["email": email, + "password": password] + AuthManager.auth(params: params, completion: self.loginResponse) } @IBAction func buttonAuthenticateGoogleDidPressed(_ sender: Any) { @@ -178,7 +184,7 @@ final class AuthViewController: BaseViewController { @IBAction func buttonTermsDidPressed(_ sender: Any) { var components = URLComponents() components.scheme = "https" - components.host = self.serverURL.host + components.host = self.serverURL?.host if var newURL = components.url { newURL = newURL.appendingPathComponent("terms-of-service") @@ -191,7 +197,7 @@ final class AuthViewController: BaseViewController { @IBAction func buttonPolicyDidPressed(_ sender: Any) { var components = URLComponents() components.scheme = "https" - components.host = self.serverURL.host + components.host = self.serverURL?.host if var newURL = components.url { newURL = newURL.appendingPathComponent("privacy-policy") @@ -213,14 +219,55 @@ final class AuthViewController: BaseViewController { self?.authenticateWithUsernameOrEmail() } } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + UIApplication.shared.statusBarStyle = .lightContent + } + + func showChat() { + // Open chat + let storyboardChat = UIStoryboard(name: "Chat", bundle: Bundle.main) + let controller = storyboardChat.instantiateInitialViewController() + let application = UIApplication.shared + if let window = application.keyWindow { + window.rootViewController = controller + } + } + + func alertInvalidURL() { + let alert = UIAlertController( + title: localized("alert.connection.invalid_url.title"), + message: localized("alert.connection.invalid_url.message"), + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: localized("global.ok"), style: .default, handler: nil)) + present(alert, animated: true, completion: nil) + } + func alertWrongServerVersion(version: String, minVersion: String) { + let alert = UIAlertController( + title: localized("alert.connection.invalid_version.title"), + message: String(format: localized("alert.connection.invalid_version.message"), version, minVersion), + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: localized("global.ok"), style: .default, handler: nil)) + self.present(alert, animated: true, completion: nil) + } + func finishExecution(nextState: AuthState?) { + self.stateMachine?.switchState(state: nextState) + self.stateMachine?.execute() + } + @IBAction func signIn() { + self.stateMachine?.success() + } } extension AuthViewController: UITextFieldDelegate { - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return !connecting } - func textFieldShouldReturn(_ textField: UITextField) -> Bool { if connecting { return false @@ -231,9 +278,8 @@ extension AuthViewController: UITextFieldDelegate { } if textField == textFieldPassword { - authenticateWithUsernameOrEmail() + self.stateMachine?.success() } - return true } } diff --git a/Rocket.Chat/Controllers/Chat/ChatViewController.swift b/Rocket.Chat/Controllers/Chat/ChatViewController.swift index cdbbde2f77..4effbb68e5 100644 --- a/Rocket.Chat/Controllers/Chat/ChatViewController.swift +++ b/Rocket.Chat/Controllers/Chat/ChatViewController.swift @@ -78,8 +78,8 @@ final class ChatViewController: SLKTextViewController { override func viewDidLoad() { super.viewDidLoad() navigationController?.navigationBar.isTranslucent = false - navigationController?.navigationBar.barTintColor = UIColor.white - navigationController?.navigationBar.tintColor = UIColor(rgb: 0x5B5B5B, alphaVal: 1) + navigationController?.navigationBar.barTintColor = #colorLiteral(red: 0.1333333333, green: 0.1333333333, blue: 0.1333333333, alpha: 1) + navigationController?.navigationBar.tintColor = #colorLiteral(red: 0.1333333333, green: 0.1333333333, blue: 0.1333333333, alpha: 1) mediaFocusViewController.shouldDismissOnTap = true mediaFocusViewController.shouldShowPhotoActions = true @@ -92,7 +92,8 @@ final class ChatViewController: SLKTextViewController { isKeyboardPanningEnabled = true shouldScrollToBottomAfterKeyboardShows = false - leftButton.setImage(UIImage(named: "Upload"), for: .normal) + leftButton.setImage(UIImage(named: "Upload")?.withRenderingMode(.alwaysTemplate), for: .normal) + leftButton.tintColor = UIColor.init(colorLiteralRed: 248/255, green: 139/255, blue: 47/255, alpha: 1.0) rightButton.isEnabled = false @@ -112,6 +113,8 @@ final class ChatViewController: SLKTextViewController { view.bringSubview(toFront: activityIndicatorContainer) view.bringSubview(toFront: buttonScrollToBottom) view.bringSubview(toFront: textInputbar) + + self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: UIView(frame: CGRect(x: 0, y: 0, width: 22, height: 22))) } internal func reconnect() { @@ -142,16 +145,6 @@ final class ChatViewController: SLKTextViewController { }) } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if let nav = segue.destination as? UINavigationController, segue.identifier == "Channel Info" { - if let controller = nav.viewControllers.first as? ChannelInfoViewController { - if let subscription = self.subscription { - controller.subscription = subscription - } - } - } - } - fileprivate func setupTextViewSettings() { textInputbar.autoHideRightButton = true @@ -169,9 +162,6 @@ final class ChatViewController: SLKTextViewController { let view = ChatTitleView.instantiateFromNib() self.navigationItem.titleView = view chatTitleView = view - - let gesture = UITapGestureRecognizer(target: self, action: #selector(chatTitleViewDidPressed)) - chatTitleView?.addGestureRecognizer(gesture) } fileprivate func setupScrollToBottomButton() { @@ -574,6 +564,7 @@ extension ChatViewController { guard let obj = dataController.itemAt(indexPath) else { return UICollectionViewCell() } if obj.type == .message { + print(obj) return cellForMessage(obj, at: indexPath) } diff --git a/Rocket.Chat/Controllers/Chat/MainChatViewController.swift b/Rocket.Chat/Controllers/Chat/MainChatViewController.swift index c6290e4bb9..6eaa6e99ef 100644 --- a/Rocket.Chat/Controllers/Chat/MainChatViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MainChatViewController.swift @@ -24,7 +24,7 @@ class MainChatViewController: SideMenuController, SideMenuControllerDelegate { } required init?(coder aDecoder: NSCoder) { - SideMenuController.preferences.drawing.menuButtonImage = UIImage(named: "Menu") + SideMenuController.preferences.drawing.menuButtonImage = UIImage(named: "MenuMod") SideMenuController.preferences.drawing.sidePanelPosition = .underCenterPanelLeft if UIDevice.current.userInterfaceIdiom == .pad { @@ -54,23 +54,23 @@ class MainChatViewController: SideMenuController, SideMenuControllerDelegate { func sideMenuControllerWillHide(_ sideMenuController: SideMenuController) { ChatViewController.sharedInstance()?.textView.resignFirstResponder() - SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() + //SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() } func sideMenuControllerDidHide(_ sideMenuController: SideMenuController) { ChatViewController.sharedInstance()?.textView.resignFirstResponder() - SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() + //SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() } func sideMenuControllerDidReveal(_ sideMenuController: SideMenuController) { ChatViewController.sharedInstance()?.textView.resignFirstResponder() - SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() + //SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() } func sideMenuControllerWillReveal(_ sideMenuController: SideMenuController) { ChatViewController.sharedInstance()?.textView.resignFirstResponder() - SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() + //SubscriptionsViewController.sharedInstance()?.textFieldSearch.resignFirstResponder() SubscriptionsViewController.sharedInstance()?.updateData() } diff --git a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsViewController.swift b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsViewController.swift index 8802b085da..2fcab3146b 100644 --- a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsViewController.swift +++ b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsViewController.swift @@ -13,6 +13,8 @@ final class SubscriptionsViewController: BaseViewController { @IBOutlet weak var tableView: UITableView! @IBOutlet weak var activityViewSearching: UIActivityIndicatorView! + @IBOutlet weak var userName: UILabel! + @IBOutlet weak var userIcon: UIImageView! let defaultButtonCancelSearchWidth = CGFloat(65) @IBOutlet weak var buttonCancelSearch: UIButton! { @@ -60,6 +62,15 @@ final class SubscriptionsViewController: BaseViewController { } } + // @IBOutlet weak var userAvatar: AvatarView! + @IBOutlet weak var userAvatar: AvatarView! { + didSet { + userAvatar.layer.cornerRadius = userAvatar.frame.size.width / 2 + userAvatar.layer.masksToBounds = true + userAvatar.labelInitialsFontSize = 15 + } + } + class func sharedInstance() -> SubscriptionsViewController? { if let main = UIApplication.shared.delegate?.window??.rootViewController as? MainChatViewController { if let nav = main.sideViewController as? UINavigationController { @@ -80,6 +91,7 @@ final class SubscriptionsViewController: BaseViewController { var groupInfomation: [[String: String]]? var groupSubscriptions: [[Subscription]]? + var directMessages: [Subscription]? override func awakeFromNib() { super.awakeFromNib() @@ -101,6 +113,23 @@ final class SubscriptionsViewController: BaseViewController { super.viewDidAppear(animated) registerKeyboardHandlers(tableView) } + + override func viewDidLoad() { + super.viewDidLoad() + /* + [self.navigationController.navigationBar setBarTintColor:[UIColor greenColor]]; + [self.navigationController.navigationBar setTranslucent:NO]; + */ + self.navigationController?.navigationBar.barTintColor = #colorLiteral(red: 0.2605174184, green: 0.2605243921, blue: 0.260520637, alpha: 1) + let titleFormatter = TitleFormatter() + self.userName.text = titleFormatter.replaceDotWithSpace(string: AuthManager.currentUser()?.username) + self.userAvatar.user = AuthManager.currentUser() + print(">>>>>>>>>>\n") + print(self.userAvatar.user) + } + override var prefersStatusBarHidden: Bool { + return false + } } extension SubscriptionsViewController { @@ -303,7 +332,7 @@ extension SubscriptionsViewController { groupInfomation?.append([ "name": String(format: "%@ (%d)", localized("subscriptions.channels"), channelGroup.count) ]) - + print(channelGroup) groupSubscriptions?.append(channelGroup) } @@ -313,6 +342,7 @@ extension SubscriptionsViewController { ]) groupSubscriptions?.append(directMessageGroup) + self.directMessages = directMessageGroup } } } @@ -336,22 +366,37 @@ extension SubscriptionsViewController: UITableViewDataSource { } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: SubscriptionCell.identifier) as? SubscriptionCell else { + guard let group = groupSubscriptions?[indexPath.section] else { return UITableViewCell() } + if self.directMessages == nil || group != self.directMessages! { + guard let cell = tableView.dequeueReusableCell(withIdentifier: SubscriptionCell.identifier) as? SubscriptionCell else { + return UITableViewCell() + } - if let subscription = subscription(for: indexPath) { - cell.subscription = subscription - } + if let subscription = subscription(for: indexPath) { + cell.subscription = subscription + } + return cell + } else if group == self.directMessages! { + guard let cell = tableView.dequeueReusableCell(withIdentifier: SubscriptionCell.directMessageIdentifier) as? SubscriptionCell else { + return UITableViewCell() + } - return cell + if let subscription = subscription(for: indexPath) { + cell.subscription = subscription + cell.userName = subscription.name + } + return cell + } + return UITableViewCell() } } extension SubscriptionsViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return section == 0 ? 50 : 60 + return 30 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { @@ -377,8 +422,8 @@ extension SubscriptionsViewController: UITableViewDelegate { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + //let user = AuthManager.currentUser() guard let subscription = subscription(for: indexPath) else { return } - let controller = ChatViewController.sharedInstance() controller?.closeSidebarAfterSubscriptionUpdate = true controller?.subscription = subscription @@ -478,16 +523,36 @@ extension SubscriptionsViewController: SubscriptionUserStatusViewProtocol { } func viewUserDidTap(sender: Any) { - textFieldSearch.resignFirstResponder() - - if viewUserMenu != nil { - dismissUserMenu() - } else { - presentUserMenu() - } +// textFieldSearch.resignFirstResponder() +// +// if viewUserMenu != nil { +// dismissUserMenu() +// } else { +// presentUserMenu() +// } } func userDidPressedOption() { dismissUserMenu() } + + @IBAction func buttonLogoutDidPressed(_ sender: Any) { + // RKS NOTE: I know that this isn't the best place, but we need to fix + // this crash ASAP. In the future we may have a centered place for all + // database notifications. + ChatViewController.sharedInstance()?.messagesToken?.stop() + SubscriptionsViewController.sharedInstance()?.usersToken?.stop() + SubscriptionsViewController.sharedInstance()?.subscriptionsToken?.stop() + + AuthManager.logout { + let storyboardChat = UIStoryboard(name: "Main", bundle: Bundle.main) + let controller = storyboardChat.instantiateInitialViewController() + let application = UIApplication.shared + + if let window = application.keyWindow { + window.rootViewController = controller + window.makeKeyAndVisible() + } + } + } } diff --git a/Rocket.Chat/HTTPResponse.swift b/Rocket.Chat/HTTPResponse.swift new file mode 100644 index 0000000000..756d1a481d --- /dev/null +++ b/Rocket.Chat/HTTPResponse.swift @@ -0,0 +1,13 @@ +// +// HTTPResponse.swift +// Rocket.Chat +// +// Created by Alexander Bugara on 8/23/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import Foundation + +public struct HTTPResponse { + var isError = false +} diff --git a/Rocket.Chat/Helpers/TitleFormatter.swift b/Rocket.Chat/Helpers/TitleFormatter.swift new file mode 100644 index 0000000000..ec34a1448c --- /dev/null +++ b/Rocket.Chat/Helpers/TitleFormatter.swift @@ -0,0 +1,45 @@ +// +// TitleFormatter.swift +// Rocket.Chat +// +// Created by Alexander Bugara on 8/11/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import Foundation + +class TitleFormatter { + private func stringFromHtml(string: String?, color: UIColor = .black, size: NSInteger = 4) -> NSAttributedString? { + do { + guard let string = string else { + return nil + } + let stringSize = String(size) + let modString = "" + string + "" + + let data = modString.data(using: String.Encoding.utf8, allowLossyConversion: true) + if let d = data { + let str = try NSAttributedString(data: d, + options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], + documentAttributes: nil) + return str + } + } catch { + } + return nil + } + + func replaceDotWithSpace(string: String?) -> String? { + guard let string = string else { + return nil + } + return string.replacingOccurrences(of: ".", with: " ", options: .literal, range: nil) + } + + func title(string: String?, color: UIColor = .black) -> NSAttributedString? { + return self.stringFromHtml(string: self.replaceDotWithSpace(string: string), color: #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)) + } + func navigationTitle(string: String?, color: UIColor = .black) -> NSAttributedString? { + return self.stringFromHtml(string: self.replaceDotWithSpace(string: string), color: #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), size: 5) + } +} diff --git a/Rocket.Chat/Info.plist b/Rocket.Chat/Info.plist index 20b541e1c8..e9219f2fb3 100644 --- a/Rocket.Chat/Info.plist +++ b/Rocket.Chat/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - Rocket.Chat+ + Marketplace CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.1 + 0.0.1 CFBundleSignature ???? CFBundleURLTypes @@ -32,7 +32,7 @@ CFBundleVersion - 82 + 4 Fabric APIKey @@ -74,6 +74,11 @@ To upload photos from your library RC_MIN_SERVER_VERSION 0.54.0 + TyphoonInitialAssemblies + + ApplicationAssembly + CoreComponentsAssembly + UIBackgroundModes fetch @@ -81,7 +86,7 @@ UILaunchStoryboardName LaunchScreen UIMainStoryboardFile - Main + Auth UIRequiredDeviceCapabilities armv7 @@ -100,6 +105,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/Rocket.Chat/Interactors/AuthInteractor.swift b/Rocket.Chat/Interactors/AuthInteractor.swift new file mode 100644 index 0000000000..a522d0ee04 --- /dev/null +++ b/Rocket.Chat/Interactors/AuthInteractor.swift @@ -0,0 +1,128 @@ +// +// AuthInteractor.swift +// Rocket.Chat +// +// Created by Alexander Bugara on 7/24/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import Foundation +import RxSwift +import SwiftyJSON +import semver + +public enum ErrorType { + case invalidURL + case wrongServerVersion(version: String, minVersion: String) + case connectionError +} + +public enum Result { + case success(Value) + case failure(ErrorType) +} + +class AuthInteractor: NSObject { + + func checkAuth() -> Observable? { + + return Observable.create { observer in + if let auth = AuthManager.isAuthenticated() { + AuthManager.persistAuthInformation(auth) + AuthManager.resume(auth, completion: { response in + guard !response.isError(), !(response is Error) else { + return observer.onNext(false) + } + SubscriptionManager.updateSubscriptions(auth, completion: { _ in + AuthManager.updatePublicSettings(auth, completion: { _ in + }) + + UserManager.userDataChanges() + UserManager.changes() + SubscriptionManager.changes(auth) + + if let userIdentifier = auth.userId { + PushManager.updateUser(userIdentifier) + } + observer.onNext(true) + }) + }) + } else { + observer.onNext(false) + } + return Disposables.create() + } + } + + func validate(URL: URL?) -> Observable>? { + return Observable.create { observer in + guard let url = URL else { + observer.onNext(Result.failure(.invalidURL)) + return Disposables.create() + } + guard let socketURL = url.socketURL() else { + observer.onNext(Result.failure(.invalidURL)) + return Disposables.create() + } + guard let validateURL = url.validateURL() else { + observer.onNext(Result.failure(.invalidURL)) + return Disposables.create() + } + let request = URLRequest(url: validateURL) + let session = URLSession.shared + + let task = session.dataTask(with: request, completionHandler: { (data, _, _) in + if let data = data { + let json = JSON(data: data) + Log.debug(json.rawString()) + + guard let version = json["version"].string else { + return observer.onNext(Result.failure(.invalidURL)) + } + + if let minVersion = Bundle.main.object(forInfoDictionaryKey: "RC_MIN_SERVER_VERSION") as? String { + if Semver.lt(version, minVersion) { + DispatchQueue.main.async(execute: { + observer.onNext(Result.failure(ErrorType.wrongServerVersion(version: version, minVersion: minVersion))) + observer.onCompleted() + }) + } + } + DispatchQueue.main.async(execute: { + observer.onNext(Result.success(socketURL)) + observer.onCompleted() + }) + } else { + DispatchQueue.main.async(execute: { + observer.onNext(Result.failure(.invalidURL)) + observer.onCompleted() + }) + } + }) + + task.resume() + return Disposables.create { + task.cancel() + } + } + } + + func connect(socketURL: URL!) -> Observable> { + return Observable.create { observer in + + SocketManager.connect(socketURL) { (_, _) in + AuthManager.updatePublicSettings(nil) { (settings) in + guard let settings = settings else { + observer.onNext(.failure(.connectionError)) + observer.onCompleted() + return + } + + observer.onNext(Result.success(settings!)) + observer.onCompleted() + } + } + return Disposables.create() + } + } +} diff --git a/Rocket.Chat/Managers/Model/AuthManager.swift b/Rocket.Chat/Managers/Model/AuthManager.swift index 4c7e92a553..b56a7233c3 100644 --- a/Rocket.Chat/Managers/Model/AuthManager.swift +++ b/Rocket.Chat/Managers/Model/AuthManager.swift @@ -16,7 +16,7 @@ struct AuthManagerPersistKeys { } struct AuthManager { - + /** - returns: Last auth object (sorted by lastAccess), if exists. */ @@ -125,35 +125,73 @@ extension AuthManager { Method that creates an User account. */ static func signup(with name: String, _ email: String, _ password: String, completion: @escaping MessageCompletion) { - let object = [ - "msg": "method", - "method": "registerUser", - "params": [[ - "email": email, - "pass": password, - "name": name - ]] - ] as [String : Any] +// let object = [ +// "msg": "method", +// "method": "registerUser", +// "params": [[ +// "email": email, +// "pass": password, +// "name": name +// ]] +// ] as [String : Any] +// +// SocketManager.send(object) { (response) in +// guard !response.isError() else { +// completion(response) +// return +// } +// let params = [ +// "email": email, +// "password": password +// ] +// self.auth(params: params, completion: completion) +// } + } - SocketManager.send(object) { (response) in - guard !response.isError() else { - completion(response) + /** + Generic method that authenticates the user. + */ + static func auth(params: [String: Any], completion: @escaping HTTPComplition) { + self.post(params : params, url : "https://staging.seekingalpha.com/authentication/rc_mobile_login", complition : { result in + + var httpResponse = HTTPResponse() + guard let rc_token = result?["rc_token"] as? String else { + httpResponse.isError = true + completion(httpResponse) + return + } + guard let user_id = result?["user_id"] as? String else { + httpResponse.isError = true + completion(httpResponse) return } - self.auth(email, password: password, completion: completion) - } + Realm.execute({ (realm) in + // Delete all the Auth objects, since we don't + // support multiple-server authentication yet + realm.delete(realm.objects(Auth.self)) + + let auth = Auth() + auth.lastSubscriptionFetch = nil + auth.lastAccess = Date() + auth.serverURL = "wss://rc.staging.seekingalpha.com/websocket" + auth.token = rc_token + auth.userId = user_id + PushManager.updatePushToken() + + realm.add(auth) + }, completion: { + completion(httpResponse) + }) + }) } - /** - Generic method that authenticates the user. - */ static func auth(params: [String: Any], completion: @escaping MessageCompletion) { let object = [ "msg": "method", "method": "login", "params": [params] - ] as [String : Any] + ] as [String : Any] SocketManager.send(object) { (response) in guard !response.isError() else { @@ -197,37 +235,34 @@ extension AuthManager { - parameter completion: The completion block that'll be called in case of success or error. */ - static func auth(_ username: String, password: String, code: String? = nil, completion: @escaping MessageCompletion) { - let usernameType = username.contains("@") ? "email" : "username" - var params: [String: Any]? - - if let code = code { - params = [ - "totp": [ - "login": [ - "user": [usernameType: username], - "password": [ - "digest": password.sha256(), - "algorithm": "sha-256" - ] - ], - "code": code - ] - ] - } else { - params = [ - "user": [usernameType: username], - "password": [ - "digest": password.sha256(), - "algorithm": "sha-256" - ] - ] - } - - if let params = params { - self.auth(params: params, completion: completion) - } - } +// static func auth(_ username: String, password: String, code: String? = nil, completion: @escaping MessageCompletion) { +// let usernameType = username.contains("@") ? "email" : "username" +// var params: [String: Any]? +// +// if let code = code { +// params = [ +// "totp": [ +// "login": [ +// "user": [usernameType: username], +// "password": [ +// "digest": password.sha256(), +// "algorithm": "sha-256" +// ] +// ], +// "code": code +// ] +// ] +// } else { +// params = [ +// "email": username, +// "password": password +// ] +// } +// +// if let params = params { +// self.auth(params: params, completion: completion) +// } +// } /** Returns the username suggestion for the logged in user. @@ -276,4 +311,67 @@ extension AuthManager { } } + static func updatePublicSettings(_ auth: Auth?, completion: @escaping MessageCompletionObject) { + let object = [ + "msg": "method", + "method": "public-settings/get" + ] as [String : Any] + + SocketManager.send(object) { (response) in + guard !response.isError() else { + completion(nil) + return + } + + Realm.executeOnMainThread({ realm in + let settings = AuthManager.isAuthenticated()?.settings ?? AuthSettings() + settings.map(response.result["result"], realm: realm) + realm.add(settings, update: true) + + if let auth = AuthManager.isAuthenticated() { + auth.settings = settings + realm.add(auth, update: true) + } + + let unmanagedSettings = AuthSettings(value: settings) + completion(unmanagedSettings) + }) + } + } + + static func post(params: [String: Any], url: String, complition: @escaping (_ result: NSDictionary?) -> Void ) { + + guard let serviceUrl = URL(string: url) else { return } + var request = URLRequest(url: serviceUrl) + request.httpMethod = "POST" + request.setValue("Application/json", forHTTPHeaderField: "Content-Type") + request.addValue("Basic c2Vla2luZ2FscGhhOmlwdmlwdg==", forHTTPHeaderField: "Authorization") + request.addValue("gzip, deflate, sdch", forHTTPHeaderField: "Accept-Encoding") + request.setValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_ 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36", forHTTPHeaderField: "User-Agent") + request.addValue("1", forHTTPHeaderField: "Fastly-Debug") + + guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else { + return + } + request.httpBody = httpBody + + let session = URLSession.shared + session.dataTask(with: request) { (data, response, error) in + if let response = response { + print(response) + } + if let data = data { + do { + let json = try JSONSerialization.jsonObject(with: data, options: []) + print(json) + + if let dict = json as? NSDictionary { + complition(dict) + } + } catch { + print(error) + } + } + }.resume() + } } diff --git a/Rocket.Chat/Managers/Model/UserManager.swift b/Rocket.Chat/Managers/Model/UserManager.swift index af0772d378..f8b41e726a 100644 --- a/Rocket.Chat/Managers/Model/UserManager.swift +++ b/Rocket.Chat/Managers/Model/UserManager.swift @@ -56,4 +56,13 @@ struct UserManager { } } +// static func getUserAvatar(completion: @escaping MessageCompletion) { +// let user = AuthManager.currentUser() +// let object = [ +// "msg": "method", +// "method": "users.getAvatar", +// "params": ["userId": user?.identifier] +// ] as [String : Any] +// SocketManager.send(object, completion: completion) +// } } diff --git a/Rocket.Chat/Managers/Socket/Response/SocketHandlers.swift b/Rocket.Chat/Managers/Socket/Response/SocketHandlers.swift index c00eb5df6d..6774a50a65 100644 --- a/Rocket.Chat/Managers/Socket/Response/SocketHandlers.swift +++ b/Rocket.Chat/Managers/Socket/Response/SocketHandlers.swift @@ -63,7 +63,6 @@ extension SocketManager { if result.event != nil { return handleEventSubscription(result, socket: socket) } - // Handle model updates if let collection = result.collection { guard let msg = result.msg else { return } diff --git a/Rocket.Chat/Managers/Socket/SocketManager.swift b/Rocket.Chat/Managers/Socket/SocketManager.swift index 0fdfd85567..14f7b45059 100644 --- a/Rocket.Chat/Managers/Socket/SocketManager.swift +++ b/Rocket.Chat/Managers/Socket/SocketManager.swift @@ -17,6 +17,7 @@ public typealias MessageCompletion = (SocketResponse) -> Void public typealias SocketCompletion = (WebSocket?, Bool) -> Void public typealias MessageCompletionObject = (T?) -> Void public typealias MessageCompletionObjectsList = ([T]) -> Void +public typealias HTTPComplition = (HTTPResponse) -> Void protocol SocketConnectionHandler { func socketDidConnect(socket: SocketManager) diff --git a/Rocket.Chat/Rocket.Chat-Bridge.h b/Rocket.Chat/Rocket.Chat-Bridge.h index f085da29ea..51c5576697 100644 --- a/Rocket.Chat/Rocket.Chat-Bridge.h +++ b/Rocket.Chat/Rocket.Chat-Bridge.h @@ -17,4 +17,5 @@ // Google Authentication #import +#import #endif /* Rocket_Chat_Bridge_h */ diff --git a/Rocket.Chat/Storyboards/Auth.storyboard b/Rocket.Chat/Storyboards/Auth.storyboard index 10b42c2984..1db3c2a837 100644 --- a/Rocket.Chat/Storyboards/Auth.storyboard +++ b/Rocket.Chat/Storyboards/Auth.storyboard @@ -1,11 +1,12 @@ - + - + + @@ -13,146 +14,21 @@ + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -164,215 +40,226 @@ - + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - - + + - - - - - - - - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + - + + + + + + - - - - - + + + + + - + + + + + + + + + @@ -643,128 +530,86 @@ - - + + - + - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +VGhlIFNlZWtpbmcgQWxwaGEgTWFya2V0cGxhY2UgYXBwIANpcyBvbmx5IGF2YWlsYWJsZSBmb3Igc3Vi +c2NyaWJlcnMuIANUaGUgYWNjb3VudCB5b3UgZW50ZXJlZCBoYXMgbm8gYWN0aXZlIHN1YnNjcmlwdGlv +bnMuIA1JZiB5b3UgZmVlbCB0aGlzIGlzIGFuIGVycm9yLCBwbGVhc2UgZW1haWwgA + + + + + + + + + + + + - + - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + - + - + - - - + + + - + + diff --git a/Rocket.Chat/Storyboards/Chat.storyboard b/Rocket.Chat/Storyboards/Chat.storyboard index bafe16be86..28d04db0cd 100644 --- a/Rocket.Chat/Storyboards/Chat.storyboard +++ b/Rocket.Chat/Storyboards/Chat.storyboard @@ -1,11 +1,11 @@ - + - + @@ -55,7 +55,6 @@ - @@ -80,10 +79,10 @@ - + - + - + - + - + - + - + - + diff --git a/Rocket.Chat/Views/Avatar/AvatarView.swift b/Rocket.Chat/Views/Avatar/AvatarView.swift index a6ca5f0c2b..c98d77d2ab 100644 --- a/Rocket.Chat/Views/Avatar/AvatarView.swift +++ b/Rocket.Chat/Views/Avatar/AvatarView.swift @@ -27,6 +27,12 @@ final class AvatarView: UIView { updateAvatar() } } + + var userName: String? { + didSet { + updateAvatar() + } + } @IBOutlet weak var labelInitials: UILabel! var labelInitialsFontSize: CGFloat? { @@ -38,10 +44,15 @@ final class AvatarView: UIView { @IBOutlet weak var imageView: UIImageView! private func userAvatarURL() -> URL? { - guard let username = user?.username else { return nil } + var userName = user?.username + if userName == nil { + userName = self.userName + } + if (userName == nil) {return nil} + //guard let username = user?.username else { return nil } guard let auth = AuthManager.isAuthenticated() else { return nil } guard let baseURL = auth.baseURL() else { return nil } - guard let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { return nil } + guard let encodedUsername = userName?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { return nil } return URL(string: "\(baseURL)/avatar/\(encodedUsername)") } @@ -56,6 +67,7 @@ final class AvatarView: UIView { } if let imageURL = imageURL { + print(">>>> " + imageURL.absoluteString) imageView?.sd_setImage(with: imageURL, completed: { [weak self] _, error, _, _ in guard error != nil else { self?.labelInitials.text = "" diff --git a/Rocket.Chat/Views/Avatar/AvatarView.xib b/Rocket.Chat/Views/Avatar/AvatarView.xib index 62be02c277..91a9ddeaff 100644 --- a/Rocket.Chat/Views/Avatar/AvatarView.xib +++ b/Rocket.Chat/Views/Avatar/AvatarView.xib @@ -1,11 +1,11 @@ - + - + diff --git a/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.swift b/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.swift index 2583fbf52d..21c461715c 100644 --- a/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.swift +++ b/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.swift @@ -27,7 +27,7 @@ final class AutocompleteCell: UITableViewCell { weak var avatarView: AvatarView! { didSet { - avatarView.layer.cornerRadius = 4 + avatarView.layer.cornerRadius = avatarView.frame.size.width / 2 avatarView.layer.masksToBounds = true avatarView.labelInitialsFontSize = 15 } diff --git a/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.xib b/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.xib index 607bdbb294..fa834effd4 100644 --- a/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.xib +++ b/Rocket.Chat/Views/Cells/Chat/AutocompleteCell.xib @@ -1,11 +1,11 @@ - + - + @@ -15,7 +15,7 @@ - + diff --git a/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift b/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift index b4feb9833e..c611d68e07 100644 --- a/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift +++ b/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift @@ -38,7 +38,7 @@ final class ChatMessageCell: UICollectionViewCell { weak var avatarView: AvatarView! { didSet { - avatarView.layer.cornerRadius = 4 + avatarView.layer.cornerRadius = avatarView.frame.size.width / 2 avatarView.layer.masksToBounds = true } } diff --git a/Rocket.Chat/Views/Cells/Chat/Info/ChannelInfoUserCell.swift b/Rocket.Chat/Views/Cells/Chat/Info/ChannelInfoUserCell.swift index 7c3cf2c500..0f8085d436 100644 --- a/Rocket.Chat/Views/Cells/Chat/Info/ChannelInfoUserCell.swift +++ b/Rocket.Chat/Views/Cells/Chat/Info/ChannelInfoUserCell.swift @@ -38,7 +38,7 @@ class ChannelInfoUserCell: UITableViewCell, ChannelInfoCellProtocol { weak var avatarView: AvatarView! { didSet { - avatarView.layer.cornerRadius = 4 + avatarView.layer.cornerRadius = avatarView.frame.size.width / 2 avatarView.layer.masksToBounds = true } } diff --git a/Rocket.Chat/Views/Cells/Subscription/SubscriptionCell.swift b/Rocket.Chat/Views/Cells/Subscription/SubscriptionCell.swift index a5859a24b9..69ee3482f9 100644 --- a/Rocket.Chat/Views/Cells/Subscription/SubscriptionCell.swift +++ b/Rocket.Chat/Views/Cells/Subscription/SubscriptionCell.swift @@ -11,57 +11,67 @@ import UIKit final class SubscriptionCell: UITableViewCell { static let identifier = "CellSubscription" + static let directMessageIdentifier = "DirectMessage" internal let labelSelectedTextColor = UIColor(rgb: 0xFFFFFF, alphaVal: 1) - internal let labelReadTextColor = UIColor(rgb: 0x9AB1BF, alphaVal: 1) + internal let labelReadTextColor = UIColor(rgb: 0xFFFFFFF, alphaVal: 1) internal let labelUnreadTextColor = UIColor(rgb: 0xFFFFFF, alphaVal: 1) internal let defaultBackgroundColor = UIColor.clear - internal let selectedBackgroundColor = UIColor(rgb: 0x0, alphaVal: 0.18) - internal let highlightedBackgroundColor = UIColor(rgb: 0x0, alphaVal: 0.27) + internal let selectedBackgroundColor = UIColor(rgb: 0x555555, alphaVal: 1)//0.18) + internal let highlightedBackgroundColor = UIColor(rgb: 0x555555, alphaVal: 1)// 0.27) - var subscription: Subscription? { + var subscription: Subscription! { didSet { updateSubscriptionInformatin() } } - @IBOutlet weak var imageViewIcon: UIImageView! + var userName: String! { + didSet { + self.userAvatar.userName = userName + self.userAvatar.layer.cornerRadius = self.userAvatar.frame.size.width / 2 + self.userAvatar.layer.masksToBounds = true + } + } + @IBOutlet weak var labelName: UILabel! + @IBOutlet weak var userAvatar: AvatarView! + @IBOutlet weak var counterConstraint: NSLayoutConstraint! @IBOutlet weak var labelUnread: UILabel! { didSet { - labelUnread.layer.cornerRadius = 2 + labelUnread.layer.cornerRadius = labelUnread.frame.size.height / 2 + labelUnread.layer.masksToBounds = true } } - func updateSubscriptionInformatin() { - guard let subscription = self.subscription else { return } - updateIconImage() - labelName.text = subscription.displayName() + let text = (subscription.roomDescription == "") ? subscription.name : subscription.roomDescription + + let titleFormatter = TitleFormatter() + labelName.attributedText = titleFormatter.title(string: text) if subscription.unread > 0 || subscription.alert { - labelName.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline) labelName.textColor = labelUnreadTextColor } else { - labelName.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body) labelName.textColor = labelReadTextColor } labelUnread.alpha = subscription.unread > 0 ? 1 : 0 - labelUnread.text = "\(subscription.unread)" + let unread = "\(subscription.unread)" + let size: CGSize = unread.size(attributes: [NSFontAttributeName: labelUnread.font]) + counterConstraint.constant = size.width + 10 + labelUnread.text = unread } func updateIconImage() { - guard let subscription = self.subscription else { return } - switch subscription.type { case .channel: - imageViewIcon.image = UIImage(named: "Hashtag")?.imageWithTint(.RCInvisible()) + // imageViewIcon.image = UIImage(named: "Hashtag")?.imageWithTint(.RCInvisible()) break case .directMessage: - var color: UIColor = .RCInvisible() + /*var color: UIColor = .RCInvisible() if let user = subscription.directMessageUser { color = { _ -> UIColor in @@ -72,12 +82,12 @@ final class SubscriptionCell: UITableViewCell { case .busy: return .RCBusy() } }() - } + }*/ - imageViewIcon.image = UIImage(named: "Mention")?.imageWithTint(color) + // imageViewIcon.image = UIImage(named: "Mention")?.imageWithTint(color) break case .group: - imageViewIcon.image = UIImage(named: "Lock")?.imageWithTint(.RCInvisible()) + // imageViewIcon.image = UIImage(named: "Lock")?.imageWithTint(.RCInvisible()) break } } diff --git a/Rocket.Chat/Views/Chat/ChatPreviewModeView.xib b/Rocket.Chat/Views/Chat/ChatPreviewModeView.xib index bf5673574e..338b01fe48 100644 --- a/Rocket.Chat/Views/Chat/ChatPreviewModeView.xib +++ b/Rocket.Chat/Views/Chat/ChatPreviewModeView.xib @@ -1,11 +1,11 @@ - + - + diff --git a/Rocket.Chat/Views/Chat/ChatTitleView.swift b/Rocket.Chat/Views/Chat/ChatTitleView.swift index fc47cd96ba..d00f9ab20f 100644 --- a/Rocket.Chat/Views/Chat/ChatTitleView.swift +++ b/Rocket.Chat/Views/Chat/ChatTitleView.swift @@ -10,10 +10,9 @@ import UIKit final class ChatTitleView: UIView { - @IBOutlet weak var icon: UIImageView! @IBOutlet weak var labelTitle: UILabel! { didSet { - labelTitle.textColor = .RCDarkGray() + labelTitle.textColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) } } @@ -25,11 +24,11 @@ final class ChatTitleView: UIView { var subscription: Subscription! { didSet { - labelTitle.text = subscription.displayName() - + let text = (subscription.roomDescription == "") ? subscription.name : subscription.roomDescription + let titleFormatter = TitleFormatter() + labelTitle.attributedText = titleFormatter.navigationTitle(string: text, color: UIColor.white) switch subscription.type { case .channel: - icon.image = UIImage(named: "Hashtag")?.imageWithTint(.RCGray()) break case .directMessage: var color = UIColor.RCGray() @@ -45,10 +44,8 @@ final class ChatTitleView: UIView { }() } - icon.image = UIImage(named: "Mention")?.imageWithTint(color) break case .group: - icon.image = UIImage(named: "Lock")?.imageWithTint(.RCGray()) break } } diff --git a/Rocket.Chat/Views/Chat/ChatTitleView.xib b/Rocket.Chat/Views/Chat/ChatTitleView.xib index 90d388aac4..eb8316c99a 100644 --- a/Rocket.Chat/Views/Chat/ChatTitleView.xib +++ b/Rocket.Chat/Views/Chat/ChatTitleView.xib @@ -1,11 +1,11 @@ - + - + @@ -15,52 +15,27 @@ - - - - - - - - - + - - - - - - + - - - - - - diff --git a/Rocket.Chat/Views/Loader/LoaderView.swift b/Rocket.Chat/Views/Loader/LoaderView.swift index afb1e5a591..25a7fe6759 100644 --- a/Rocket.Chat/Views/Loader/LoaderView.swift +++ b/Rocket.Chat/Views/Loader/LoaderView.swift @@ -11,7 +11,7 @@ import UIKit class LoaderView: UIView { var isAnimating = false - + var color: UIColor? public final func startAnimating() { isHidden = false isAnimating = true @@ -31,7 +31,10 @@ class LoaderView: UIView { let circleSpacing: CGFloat = 4 let circleSize: CGFloat = 10 let circleRadius = circleSize / 2 - let fillColor = UIColor.RCDarkBlue().cgColor + var fillColor = self.color?.cgColor + if fillColor == nil { + fillColor = UIColor.RCDarkBlue().cgColor + } let x: CGFloat = (layer.bounds.size.width - size.width) / 2 let y: CGFloat = (layer.bounds.size.height - circleSize) / 2 let duration: CFTimeInterval = 1.4 diff --git a/Rocket.Chat/Views/Sections/SubscriptionSectionView.swift b/Rocket.Chat/Views/Sections/SubscriptionSectionView.swift index 8cbf7674cf..a88ca168f2 100644 --- a/Rocket.Chat/Views/Sections/SubscriptionSectionView.swift +++ b/Rocket.Chat/Views/Sections/SubscriptionSectionView.swift @@ -17,6 +17,7 @@ final class SubscriptionSectionView: UIView { @IBOutlet fileprivate weak var iconWidthConstraint: NSLayoutConstraint! @IBOutlet fileprivate weak var labelTitle: UILabel! @IBOutlet fileprivate weak var labelTitleLeftSpacingConstraint: NSLayoutConstraint! + @IBOutlet fileprivate weak var subView: UIView! func setIconName(_ iconName: String?) { if let iconName = iconName { @@ -34,4 +35,9 @@ final class SubscriptionSectionView: UIView { labelTitle.text = title?.uppercased() } + override func awakeFromNib() { + super.awakeFromNib() + self.subView.backgroundColor = UIColor(red: 51/255, green: 51/255, blue: 51/255, alpha: 1) + self.labelTitle.textColor = UIColor(red: 153/255, green: 153/255, blue: 153/255, alpha: 1) + } } diff --git a/Rocket.Chat/Views/Sections/SubscriptionSectionView.xib b/Rocket.Chat/Views/Sections/SubscriptionSectionView.xib index f737d77eb9..273c2db4ae 100644 --- a/Rocket.Chat/Views/Sections/SubscriptionSectionView.xib +++ b/Rocket.Chat/Views/Sections/SubscriptionSectionView.xib @@ -1,43 +1,52 @@ - + - + - + + + + + - + - + - + - + + + + + + @@ -47,8 +56,9 @@ + - + diff --git a/Rocket.Chat/de.lproj/Localizable.strings b/Rocket.Chat/de.lproj/Localizable.strings index 409c222b08..6a74c82c02 100644 --- a/Rocket.Chat/de.lproj/Localizable.strings +++ b/Rocket.Chat/de.lproj/Localizable.strings @@ -34,7 +34,7 @@ "subscriptions.search.load_more_results" = "Mehr Ergebnisse..."; "subscriptions.unreads" = "Ungelesen"; "subscriptions.favorites" = "Favoriten"; -"subscriptions.channels" = "Kanäle"; +"subscriptions.channels" = "Abonnements"; "subscriptions.direct_messages" = "Direktnachrichten"; // User Menu diff --git a/Rocket.Chat/en.lproj/Localizable.strings b/Rocket.Chat/en.lproj/Localizable.strings index 98a92ddd3e..c4a20d4084 100644 --- a/Rocket.Chat/en.lproj/Localizable.strings +++ b/Rocket.Chat/en.lproj/Localizable.strings @@ -34,7 +34,7 @@ "subscriptions.search.load_more_results" = "Load more results"; "subscriptions.unreads" = "Unreads"; "subscriptions.favorites" = "Favorites"; -"subscriptions.channels" = "Channels"; +"subscriptions.channels" = "Subscriptions"; "subscriptions.direct_messages" = "Direct Messages"; // User Menu diff --git a/Rocket.Chat/pt-BR.lproj/Localizable.strings b/Rocket.Chat/pt-BR.lproj/Localizable.strings index 4ebdb93e0c..d89b8f8999 100644 --- a/Rocket.Chat/pt-BR.lproj/Localizable.strings +++ b/Rocket.Chat/pt-BR.lproj/Localizable.strings @@ -34,7 +34,7 @@ "subscriptions.search.load_more_results" = "Carregar mais"; "subscriptions.unreads" = "Não lidos"; "subscriptions.favorites" = "Favoritos"; -"subscriptions.channels" = "Canais"; +"subscriptions.channels" = "Assinaturas"; "subscriptions.direct_messages" = "Mensagens Diretas"; // User Menu