From 591f835811bf5ebe33d1932c4187f38c7ab7f0ea Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 20 Jun 2022 15:27:02 +0300 Subject: [PATCH] Minimal Settings screen UI (#85) * #37 Remove sign out button from home screen * #37 Move crash button visibility flag to BuildSettings, import BuildSettings from test targets * #37 Add log out button into the settings screen * #37 Add version into the settings screen * #37 enhance bug report parameters * #37 Remove sign out button from home screen * #37 Move crash button visibility flag to BuildSettings, import BuildSettings from test targets * #37 Add log out button into the settings screen * #37 Add version into the settings screen * #37 enhance bug report parameters * #37 Add changelog * #37 Fix code smells and PR remarks --- ElementX.xcodeproj/project.pbxproj | 48 +++++++++---------- ElementX/Sources/AppCoordinator.swift | 9 +++- .../Sources/AppCoordinatorStateMachine.swift | 4 +- ElementX/Sources/BuildSettings.swift | 3 ++ .../HomeScreen/HomeScreenCoordinator.swift | 3 -- .../Screens/HomeScreen/HomeScreenModels.swift | 2 - .../HomeScreen/HomeScreenViewModel.swift | 2 - .../Screens/HomeScreen/View/HomeScreen.swift | 5 -- .../Settings/SettingsCoordinator.swift | 7 +++ .../Screens/Settings/SettingsModels.swift | 3 +- .../Screens/Settings/SettingsViewModel.swift | 4 +- .../Screens/Settings/View/Settings.swift | 45 ++++++++++++----- .../Services/BugReport/BugReportService.swift | 25 +++++++--- UITests/Sources/SettingsUITests.swift | 3 +- UITests/SupportingFiles/target.yml | 3 +- UnitTests/SupportingFiles/target.yml | 1 + changelog.d/37.feature | 1 + 17 files changed, 104 insertions(+), 64 deletions(-) create mode 100644 changelog.d/37.feature diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 4d88df161..4426238a8 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -49,13 +49,13 @@ 297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; }; 29AEE68A604940180AB9EBFF /* MockRoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6BDAC8895AB2B77B47703AE /* MockRoomSummary.swift */; }; 29EE1791E0AFA1ABB7F23D2F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; }; - 2B2947F91E5FB9792D999331 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4519B90DE2F54443E5F43DA8 /* String.swift */; }; 2BA59D0AEFB4B82A2EC2A326 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; }; 2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; }; 2C0CE61E5DC177938618E0B1 /* RootRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90733775209F4D4D366A268F /* RootRouterType.swift */; }; 2E59008365E01F0AFB3A6B24 /* ImageRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF686BA36D0C2FA3C63DFDF /* ImageRoomMessage.swift */; }; 2E68C57E7D644E94778743D5 /* TemplateSimpleScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B66E05B6009B0EB1BDBFA6E /* TemplateSimpleScreenUITests.swift */; }; 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.swift */; }; + 2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; }; 2FE4EEF780553B25A446BBFB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFA5FD06AAAC4AF544B594E /* AppDelegate.swift */; }; 30122AB3484AC6C3A7F6A717 /* ActivityIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B64F3A3D0DF86ED5A241AB05 /* ActivityIndicatorView.xib */; }; 306CC09DF101E7E9CDE79AA5 /* LoginScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C8F70ADAFB63907B862E5D /* LoginScreenCoordinator.swift */; }; @@ -83,6 +83,7 @@ 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; }; 4669804D0369FBED4E8625D1 /* ToastViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4470B8CB654B097D807AA713 /* ToastViewPresenter.swift */; }; 490E606044B18985055FF690 /* SettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */; }; + 499A26EB06C97E48C27A2DB9 /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F87116470221880017CF522 /* BuildSettings.swift */; }; 49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */; }; 4A2E0DBB63919AC8309B6D40 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A191D3FDB995309C7E2DE7D /* SettingsViewModel.swift */; }; 4B8A2C45FF906ADBB1F5C3B4 /* UserIndicatorQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04E1273CC3BC3E471AF87BE5 /* UserIndicatorQueueTests.swift */; }; @@ -133,7 +134,6 @@ 7C9121245B11CA48307CB462 /* LoginScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FD25EB4DF66625B74E4505 /* LoginScreenViewModel.swift */; }; 7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */; }; 7DE5EB4CB2401C672257283C /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12969CEC0051BC750DA5068 /* WeakKeyDictionary.swift */; }; - 7E1EDBA3934E6C29E5BD045B /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */; }; 7F19E97E7985F518C9018B83 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF47564C584F614B7287F3EB /* RootRouter.swift */; }; 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; 7FA4227B2BAAA71560252866 /* UserIndicatorDismissal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D1532B5D9FB0C8461A1453 /* UserIndicatorDismissal.swift */; }; @@ -192,6 +192,7 @@ C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; }; C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; }; C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; }; + CA1E41AE5CDCB8D801DE0830 /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F87116470221880017CF522 /* BuildSettings.swift */; }; CB137BFB3E083C33E398A6CB /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; }; CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */; }; CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; }; @@ -209,6 +210,7 @@ DDB80FD2753FEAAE43CC2AAE /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A63815AD6A5C306453342F2 /* ImageRoomTimelineItem.swift */; }; DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; }; DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; }; + E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */; }; E9CEAF2C38E4E00459B811D9 /* LoginScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2082B5226B2A3A4D0798B6 /* LoginScreenModels.swift */; }; EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; }; @@ -331,6 +333,7 @@ 3F87116470221880017CF522 /* BuildSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildSettings.swift; sourceTree = ""; }; 3FAA6438B00FDB130F404E31 /* UserIndicatorStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorStore.swift; sourceTree = ""; }; 3FEE631F3A4AFDC6652DD9DA /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = ""; }; + 40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 4110685D9CA159F3FD2D6BA1 /* TextRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomMessage.swift; sourceTree = ""; }; 4112D04077F6709C5CA0A13E /* FullscreenLoadingViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullscreenLoadingViewPresenter.swift; sourceTree = ""; }; 434522ED2BDED08759048077 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; @@ -338,7 +341,6 @@ 4470B8CB654B097D807AA713 /* ToastViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastViewPresenter.swift; sourceTree = ""; }; 4488F5F92A64A137665C96CD /* pa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pa; path = pa.lproj/Localizable.strings; sourceTree = ""; }; 44AEEE13AC1BF303AE48CBF8 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Localizable.strings; sourceTree = ""; }; - 4519B90DE2F54443E5F43DA8 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 453E722A43D092C06FB8E3FA /* tzm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tzm; path = tzm.lproj/Localizable.strings; sourceTree = ""; }; 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = ""; }; 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = ""; }; @@ -500,6 +502,7 @@ B64F3A3D0DF86ED5A241AB05 /* ActivityIndicatorView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActivityIndicatorView.xib; sourceTree = ""; }; B695D0D12086158BAD1D9859 /* UserIndicatorPresenterSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorPresenterSpy.swift; sourceTree = ""; }; B6BDAC8895AB2B77B47703AE /* MockRoomSummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomSummary.swift; sourceTree = ""; }; + B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; B7E035C6AC137C9392D98814 /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = lv.lproj/Localizable.strings; sourceTree = ""; }; B80D1901BA0B095E27793EDE /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenCoordinator.swift; sourceTree = ""; }; @@ -546,7 +549,6 @@ D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = ""; }; D6D094C15E8DB424F1C6FC94 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; D6DC38E64A5ED3FDB201029A /* BugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportService.swift; sourceTree = ""; }; - D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = ""; }; DCE978A6118C131D7F2A04B3 /* SplashScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenModels.swift; sourceTree = ""; }; DD73FAAA4A76CE4A1F3014D9 /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = ""; }; @@ -807,6 +809,15 @@ path = Room; sourceTree = ""; }; + 44BBB96FAA2F0D53C507396B /* Extensions */ = { + isa = PBXGroup; + children = ( + B6E89E530A8E92EC44301CA1 /* Bundle.swift */, + 40B21E611DADDEF00307E7AC /* String.swift */, + ); + path = Extensions; + sourceTree = ""; + }; 4541090DFE1A5499BD67BD14 /* View */ = { isa = PBXGroup; children = ( @@ -1075,22 +1086,6 @@ path = UserSessionStore; sourceTree = ""; }; - 90F48FEF84016ED42A94BA24 /* LoginScreen */ = { - isa = PBXGroup; - children = ( - ); - path = LoginScreen; - sourceTree = ""; - }; - 91AC284E285B25BB00B7ADB9 /* Extensions */ = { - isa = PBXGroup; - children = ( - D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */, - 4519B90DE2F54443E5F43DA8 /* String.swift */, - ); - path = Extensions; - sourceTree = ""; - }; 9413F680ECDFB2B0DDB0DEF2 /* Packages */ = { isa = PBXGroup; children = ( @@ -1255,7 +1250,7 @@ 95CC95CD75B688E946438165 /* Coordinator.swift */, 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */, F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */, - 91AC284E285B25BB00B7ADB9 /* Extensions */, + 44BBB96FAA2F0D53C507396B /* Extensions */, 8F9A844EB44B6AD7CA18FD96 /* HTMLParsing */, 06501F0E978B2D5C92771DC7 /* Logging */, FE50232944F9E67ADD7A2D21 /* Routers */, @@ -1320,7 +1315,6 @@ children = ( D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */, 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */, - 90F48FEF84016ED42A94BA24 /* LoginScreen */, ); path = Authentication; sourceTree = ""; @@ -1476,7 +1470,7 @@ }; }; buildConfigurationList = 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */; - compatibilityVersion = "Xcode 11.0"; + compatibilityVersion = "Xcode 10.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -1661,6 +1655,7 @@ 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */, 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */, C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */, + CA1E41AE5CDCB8D801DE0830 /* BuildSettings.swift in Sources */, 9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */, F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */, 0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */, @@ -1704,7 +1699,7 @@ 86C2E93920FD15AD17E193A9 /* BugReportViewModel.swift in Sources */, 187E18F21EF4DA244E436E58 /* BugReportViewModelProtocol.swift in Sources */, 05776B005C57E92582F0CF08 /* BuildSettings.swift in Sources */, - 7E1EDBA3934E6C29E5BD045B /* Bundle.swift in Sources */, + E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */, 1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */, 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */, DCB781BD227CA958809AFADF /* Coordinator.swift in Sources */, @@ -1811,7 +1806,7 @@ 5E1FCC43B738941D5A5F1794 /* SplashScreenViewModelProtocol.swift in Sources */, FCB640C576292BEAF7FA3B2E /* SplashViewController.swift in Sources */, B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */, - 2B2947F91E5FB9792D999331 /* String.swift in Sources */, + 2F94054F50E312AF30BE07F3 /* String.swift in Sources */, A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */, 066A1E9B94723EE9F3038044 /* Strings.swift in Sources */, 5CABC57F620FBB39F4EC127C /* TemplateSimpleScreen.swift in Sources */, @@ -1857,6 +1852,7 @@ files = ( 7405B4824D45BA7C3D943E76 /* Application.swift in Sources */, 7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */, + 499A26EB06C97E48C27A2DB9 /* BuildSettings.swift in Sources */, 9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */, 5C8AFBF168A41E20835F3B86 /* LoginScreenUITests.swift in Sources */, 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */, diff --git a/ElementX/Sources/AppCoordinator.swift b/ElementX/Sources/AppCoordinator.swift index 11c855e78..0a50a6c9f 100644 --- a/ElementX/Sources/AppCoordinator.swift +++ b/ElementX/Sources/AppCoordinator.swift @@ -197,8 +197,6 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator { guard let self = self else { return } switch action { - case .logout: - self.stateMachine.processEvent(.attemptSignOut) case .presentRoom(let roomIdentifier): self.stateMachine.processEvent(.showRoomScreen(roomId: roomIdentifier)) case .presentSettings: @@ -218,6 +216,13 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator { let parameters = SettingsCoordinatorParameters(navigationRouter: navigationRouter, bugReportService: bugReportService) let coordinator = SettingsCoordinator(parameters: parameters) + coordinator.callback = { [weak self] action in + guard let self = self else { return } + switch action { + case .logout: + self.stateMachine.processEvent(.attemptSignOut) + } + } add(childCoordinator: coordinator) coordinator.start() diff --git a/ElementX/Sources/AppCoordinatorStateMachine.swift b/ElementX/Sources/AppCoordinatorStateMachine.swift index 71ecb668f..f4ebeec2e 100644 --- a/ElementX/Sources/AppCoordinatorStateMachine.swift +++ b/ElementX/Sources/AppCoordinatorStateMachine.swift @@ -80,10 +80,10 @@ class AppCoordinatorStateMachine { machine.addRoutes(event: .succeededRestoringSession, transitions: [ .restoringSession => .homeScreen ]) machine.addRoutes(event: .failedRestoringSession, transitions: [ .restoringSession => .signedOut ]) - machine.addRoutes(event: .attemptSignOut, transitions: [ .homeScreen => .signingOut ]) + machine.addRoutes(event: .attemptSignOut, transitions: [ .settingsScreen => .signingOut ]) machine.addRoutes(event: .succeededSigningOut, transitions: [ .signingOut => .signedOut ]) - machine.addRoutes(event: .failedSigningOut, transitions: [ .signingOut => .homeScreen ]) + machine.addRoutes(event: .failedSigningOut, transitions: [ .signingOut => .settingsScreen ]) machine.addRoutes(event: .showSettingsScreen, transitions: [ .homeScreen => .settingsScreen ]) machine.addRoutes(event: .dismissedSettingsScreen, transitions: [ .settingsScreen => .homeScreen ]) diff --git a/ElementX/Sources/BuildSettings.swift b/ElementX/Sources/BuildSettings.swift index 191be38df..77d837e31 100644 --- a/ElementX/Sources/BuildSettings.swift +++ b/ElementX/Sources/BuildSettings.swift @@ -19,4 +19,7 @@ final class BuildSettings { static let bugReportGHLabels: [String] = ["Element-X"] + // MARK: - Settings screen + static let settingsCrashButtonVisible: Bool = true + } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift index d9dd6b640..1c736d2d2 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenCoordinator.swift @@ -24,7 +24,6 @@ struct HomeScreenCoordinatorParameters { } enum HomeScreenCoordinatorAction { - case logout case presentRoom(roomIdentifier: String) case presentSettings } @@ -63,8 +62,6 @@ final class HomeScreenCoordinator: Coordinator, Presentable { guard let self = self else { return } switch action { - case .logout: - self.callback?(.logout) case .selectRoom(let roomIdentifier): self.callback?(.presentRoom(roomIdentifier: roomIdentifier)) case .tapUserAvatar: diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index 2cdbe62a5..0e3e8c06b 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -18,13 +18,11 @@ import Foundation import UIKit enum HomeScreenViewModelAction { - case logout case selectRoom(roomIdentifier: String) case tapUserAvatar } enum HomeScreenViewAction { - case logout case loadRoomData(roomIdentifier: String) case selectRoom(roomIdentifier: String) case tapUserAvatar diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 4bd010fac..6bc65ac17 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -45,8 +45,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol override func process(viewAction: HomeScreenViewAction) async { switch viewAction { - case .logout: - callback?(.logout) case .loadRoomData(let roomIdentifier): loadRoomDataForIdentifier(roomIdentifier) case .selectRoom(let roomIdentifier): diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index 304bc529b..6d6823da8 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -106,11 +106,6 @@ struct HomeScreen: View { .transition(.opacity) } } - ToolbarItem(placement: .navigationBarTrailing) { - Button("Logout") { - context.send(viewAction: .logout) - } - } } } } diff --git a/ElementX/Sources/Screens/Settings/SettingsCoordinator.swift b/ElementX/Sources/Screens/Settings/SettingsCoordinator.swift index e82a83cc3..82a560599 100644 --- a/ElementX/Sources/Screens/Settings/SettingsCoordinator.swift +++ b/ElementX/Sources/Screens/Settings/SettingsCoordinator.swift @@ -21,6 +21,10 @@ struct SettingsCoordinatorParameters { let bugReportService: BugReportServiceProtocol } +enum SettingsCoordinatorAction { + case logout +} + final class SettingsCoordinator: Coordinator, Presentable { // MARK: - Properties @@ -39,6 +43,7 @@ final class SettingsCoordinator: Coordinator, Presentable { // Must be used only internally var childCoordinators: [Coordinator] = [] + var callback: ((SettingsCoordinatorAction) -> Void)? // MARK: - Setup @@ -60,6 +65,8 @@ final class SettingsCoordinator: Coordinator, Presentable { self.presentBugReportScreen() case .crash: self.parameters.bugReportService.crash() + case .logout: + self.callback?(.logout) } } } diff --git a/ElementX/Sources/Screens/Settings/SettingsModels.swift b/ElementX/Sources/Screens/Settings/SettingsModels.swift index 03f4e4dc5..ee83d1f5e 100644 --- a/ElementX/Sources/Screens/Settings/SettingsModels.swift +++ b/ElementX/Sources/Screens/Settings/SettingsModels.swift @@ -23,12 +23,12 @@ import Foundation enum SettingsViewModelAction { case reportBug case crash + case logout } // MARK: View struct SettingsViewState: BindableState { - var crashButtonVisible: Bool var bindings: SettingsViewStateBindings } @@ -39,4 +39,5 @@ struct SettingsViewStateBindings { enum SettingsViewAction { case reportBug case crash + case logout } diff --git a/ElementX/Sources/Screens/Settings/SettingsViewModel.swift b/ElementX/Sources/Screens/Settings/SettingsViewModel.swift index 03ad7d9d6..0fe113863 100644 --- a/ElementX/Sources/Screens/Settings/SettingsViewModel.swift +++ b/ElementX/Sources/Screens/Settings/SettingsViewModel.swift @@ -34,7 +34,7 @@ class SettingsViewModel: SettingsViewModelType, SettingsViewModelProtocol { init() { let bindings = SettingsViewStateBindings() - super.init(initialViewState: .init(crashButtonVisible: true, bindings: bindings)) + super.init(initialViewState: .init(bindings: bindings)) } // MARK: - Public @@ -45,6 +45,8 @@ class SettingsViewModel: SettingsViewModelType, SettingsViewModelProtocol { callback?(.reportBug) case .crash: callback?(.crash) + case .logout: + callback?(.logout) } } } diff --git a/ElementX/Sources/Screens/Settings/View/Settings.swift b/ElementX/Sources/Screens/Settings/View/Settings.swift index d01e3bd2e..e9794790e 100644 --- a/ElementX/Sources/Screens/Settings/View/Settings.swift +++ b/ElementX/Sources/Screens/Settings/View/Settings.swift @@ -19,6 +19,8 @@ import SwiftUI struct Settings: View { // MARK: Private + + @State private var showingLogoutConfirmation = false // MARK: Public @@ -28,24 +30,45 @@ struct Settings: View { var body: some View { Form { - Button { context.send(viewAction: .reportBug) } label: { - Text(ElementL10n.sendBugReport) - } - .frame(maxWidth: .infinity) - .padding(.vertical, 16) - .accessibilityIdentifier("reportBugButton") + Section { + Button { context.send(viewAction: .reportBug) } label: { + Text(ElementL10n.sendBugReport) + } + .foregroundColor(Color.element.primaryContent) + .accessibilityIdentifier("reportBugButton") - if context.viewState.crashButtonVisible { - Button { context.send(viewAction: .crash) } label: { - Text("Crash the app") + if BuildSettings.settingsCrashButtonVisible { + Button("Crash the app", + role: .destructive) { context.send(viewAction: .crash) + } + .accessibilityIdentifier("crashButton") + } + } + + Section { + Button { showingLogoutConfirmation = true } label: { + Text(ElementL10n.actionSignOut) } .frame(maxWidth: .infinity) - .padding(.vertical, 16) - .accessibilityIdentifier("crashButton") + .foregroundColor(Color.element.primaryContent) + .accessibilityIdentifier("logoutButton") + .confirmationDialog(ElementL10n.actionSignOutConfirmationSimple, + isPresented: $showingLogoutConfirmation, + titleVisibility: .visible) { + Button(ElementL10n.actionSignOut, + role: .destructive) { context.send(viewAction: .logout) + } + } + } footer: { + versionText } } .navigationTitle(ElementL10n.settings) } + + var versionText: some View { + Text(ElementL10n.settingsVersion + ": " + ElementInfoPlist.cfBundleShortVersionString + " (" + ElementInfoPlist.cfBundleVersion + ")") + } } // MARK: - Previews diff --git a/ElementX/Sources/Services/BugReport/BugReportService.swift b/ElementX/Sources/Services/BugReport/BugReportService.swift index c8febdc6f..fa66a82ce 100644 --- a/ElementX/Sources/Services/BugReport/BugReportService.swift +++ b/ElementX/Sources/Services/BugReport/BugReportService.swift @@ -141,23 +141,34 @@ class BugReportService: BugReportServiceProtocol { // MARK: - Private private var defaultParams: [MultipartFormData] { - [ + let (localTime, utcTime) = localAndUTCTime(for: Date()) + return [ MultipartFormData(key: "user_agent", type: .text(value: "iOS")), MultipartFormData(key: "app", type: .text(value: applicationId)), - MultipartFormData(key: "version", type: .text(value: version)), + MultipartFormData(key: "version", type: .text(value: ElementInfoPlist.cfBundleShortVersionString)), + MultipartFormData(key: "build", type: .text(value: ElementInfoPlist.cfBundleVersion)), MultipartFormData(key: "os", type: .text(value: os)), - MultipartFormData(key: "client", type: .text(value: "Element-X")) + MultipartFormData(key: "resolved_language", type: .text(value: Bundle.preferredLanguages[0])), + MultipartFormData(key: "user_language", type: .text(value: Bundle.elementLanguage ?? "null")), + MultipartFormData(key: "fallback_language", type: .text(value: Bundle.elementFallbackLanguage ?? "null")), + MultipartFormData(key: "local_time", type: .text(value: localTime)), + MultipartFormData(key: "utc_time", type: .text(value: utcTime)) ] } + private func localAndUTCTime(for date: Date) -> (String, String) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" + let localTime = dateFormatter.string(from: date) + dateFormatter.timeZone = TimeZone(identifier: "UTC") + let utcTime = dateFormatter.string(from: date) + return (localTime, utcTime) + } + private var os: String { "\(UIDevice.current.systemName) \(UIDevice.current.systemVersion)" } - private var version: String { - ElementInfoPlist.cfBundleShortVersionString - } - private func zipFiles(includeLogs: Bool, includeCrashLog: Bool) async throws -> [URL] { MXLog.debug("[BugReportService] zipFiles: includeLogs: \(includeLogs), includeCrashLog: \(includeCrashLog)") diff --git a/UITests/Sources/SettingsUITests.swift b/UITests/Sources/SettingsUITests.swift index 337b871a0..a72149d4c 100644 --- a/UITests/Sources/SettingsUITests.swift +++ b/UITests/Sources/SettingsUITests.swift @@ -25,7 +25,8 @@ class SettingsUITests: XCTestCase { XCTAssert(app.navigationBars["Settings"].exists) XCTAssert(app.buttons["reportBugButton"].exists) - XCTAssert(app.buttons["crashButton"].exists) + XCTAssertEqual(app.buttons["crashButton"].exists, BuildSettings.settingsCrashButtonVisible) + XCTAssert(app.buttons["logoutButton"].exists) } } diff --git a/UITests/SupportingFiles/target.yml b/UITests/SupportingFiles/target.yml index 821716722..8df14491e 100644 --- a/UITests/SupportingFiles/target.yml +++ b/UITests/SupportingFiles/target.yml @@ -39,4 +39,5 @@ targets: sources: - path: ../Sources - path: ../SupportingFiles - - path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/UI \ No newline at end of file + - path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/UI + - path: ../../ElementX/Sources/BuildSettings.swift diff --git a/UnitTests/SupportingFiles/target.yml b/UnitTests/SupportingFiles/target.yml index 446f1df82..1812aee48 100644 --- a/UnitTests/SupportingFiles/target.yml +++ b/UnitTests/SupportingFiles/target.yml @@ -23,3 +23,4 @@ targets: - path: ../SupportingFiles - path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit - path: ../Resources + - path: ../../ElementX/Sources/BuildSettings.swift diff --git a/changelog.d/37.feature b/changelog.d/37.feature new file mode 100644 index 000000000..1021d8721 --- /dev/null +++ b/changelog.d/37.feature @@ -0,0 +1 @@ +Settings screen minimal implementation.