From c5eb55d1e89cc8ded3f76481a8c997ad7e5b3127 Mon Sep 17 00:00:00 2001 From: Ryan ZHAO <> Date: Thu, 25 Jan 2024 09:30:10 +1100 Subject: [PATCH] WIP: implement start new conversation screen with SwiftUI --- Session.xcodeproj/project.pbxproj | 4 + Session/Home/HomeVC.swift | 6 +- .../StartConversationScreen.swift | 121 ++++++++++++++++++ .../Translations/en.lproj/Localizable.strings | 6 + Session/Settings/QRCodeScreen.swift | 6 +- Session/Settings/RecoveryPasswordScreen.swift | 10 +- .../Style Guide/Themes/SwiftUI+Theme.swift | 12 +- .../Utilities/SwiftUI+Utilities.swift | 14 ++ 8 files changed, 162 insertions(+), 17 deletions(-) create mode 100644 Session/Home/New Conversation/StartConversationScreen.swift diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 44ab85466..ad39b3591 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -172,6 +172,7 @@ 946B34472B5DF0B7004CB4A3 /* QRCodeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946B34462B5DF0B7004CB4A3 /* QRCodeScreen.swift */; }; 946B34492B5E04BB004CB4A3 /* CustomTopTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946B34482B5E04BB004CB4A3 /* CustomTopTabBar.swift */; }; 946B344B2B5E08F3004CB4A3 /* ScanQRCodeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946B344A2B5E08F3004CB4A3 /* ScanQRCodeScreen.swift */; }; + 946B344D2B5F67B4004CB4A3 /* StartConversationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946B344C2B5F67B4004CB4A3 /* StartConversationScreen.swift */; }; 99978E3F7A80275823CA9014 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29E827FDF6C1032BB985740C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework */; }; A11CD70D17FA230600A2D1B1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */; }; A163E8AB16F3F6AA0094D68B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; }; @@ -1311,6 +1312,7 @@ 946B34462B5DF0B7004CB4A3 /* QRCodeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScreen.swift; sourceTree = ""; }; 946B34482B5E04BB004CB4A3 /* CustomTopTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTopTabBar.swift; sourceTree = ""; }; 946B344A2B5E08F3004CB4A3 /* ScanQRCodeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanQRCodeScreen.swift; sourceTree = ""; }; + 946B344C2B5F67B4004CB4A3 /* StartConversationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartConversationScreen.swift; sourceTree = ""; }; A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; @@ -2417,6 +2419,7 @@ B8CCF63623961D6D0091D419 /* NewDMVC.swift */, 7B8C44C428B49DDA00FBE25F /* NewConversationVC.swift */, 7BB92B3E28C825FD0082762F /* NewConversationViewModel.swift */, + 946B344C2B5F67B4004CB4A3 /* StartConversationScreen.swift */, ); path = "New Conversation"; sourceTree = ""; @@ -6275,6 +6278,7 @@ 4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */, B82149C125D605C6009C0F2A /* InfoBanner.swift in Sources */, C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */, + 946B344D2B5F67B4004CB4A3 /* StartConversationScreen.swift in Sources */, 7B9F71D02852EEE2006DFE7B /* Emoji+Category.swift in Sources */, 7BAADFCC27B0EF23007BCF92 /* CallVideoView.swift in Sources */, B8CCF63F23975CFB0091D419 /* JoinOpenGroupVC.swift in Sources */, diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index eca3945b1..e7f5d552d 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -868,8 +868,10 @@ final class HomeVC: BaseVC, SessionUtilRespondingViewController, UITableViewData } @objc func createNewConversation() { - let newConversationVC = NewConversationVC() - let navigationController = StyledNavigationController(rootViewController: newConversationVC) + let viewController = SessionHostingViewController(rootView: StartConversationScreen()) + viewController.setNavBarTitle("start_conversation_screen_title".localized()) + let navigationController = StyledNavigationController(rootViewController: viewController) + navigationController.view.backgroundColor = .blue if UIDevice.current.isIPad { navigationController.modalPresentationStyle = .fullScreen } diff --git a/Session/Home/New Conversation/StartConversationScreen.swift b/Session/Home/New Conversation/StartConversationScreen.swift new file mode 100644 index 000000000..e889693a5 --- /dev/null +++ b/Session/Home/New Conversation/StartConversationScreen.swift @@ -0,0 +1,121 @@ +// Copyright © 2024 Rangeproof Pty Ltd. All rights reserved. + +import SwiftUI +import SessionUIKit +import SignalUtilitiesKit +import SessionUtilitiesKit + +struct StartConversationScreen: View { + var body: some View { + ZStack(alignment: .topLeading) { + ScrollView(.vertical, showsIndicators: false) { + VStack( + alignment: .leading, + spacing: Values.smallSpacing + ) { + VStack( + alignment: .center, + spacing: 0 + ) { + NewConversationCell( + image: "Message", + title: "vc_create_private_chat_title".localized() + ) { + + } + + Line(color: .borderSeparator) + .padding(.leading, 38 + Values.smallSpacing) + .padding(.trailing, -Values.largeSpacing) + + NewConversationCell( + image: "Group", + title: "vc_create_closed_group_title".localized() + ) { + + } + + Line(color: .borderSeparator) + .padding(.leading, 38 + Values.smallSpacing) + .padding(.trailing, -Values.largeSpacing) + + NewConversationCell( + image: "Globe", + title: "vc_join_public_chat_title".localized() + ) { + + } + + Line(color: .borderSeparator) + .padding(.leading, 38 + Values.smallSpacing) + .padding(.trailing, -Values.largeSpacing) + + NewConversationCell( + image: "icon_invite", + title: "vc_settings_invite_a_friend_button_title".localized() + ) { + + } + } + .padding(.bottom, Values.mediumSpacing) + + Text("your_account_id".localized()) + .font(.system(size: Values.mediumLargeFontSize)) + .foregroundColor(themeColor: .textPrimary) + + Text("account_id_qr_code_explanation".localized()) + .font(.system(size: Values.verySmallFontSize)) + .foregroundColor(themeColor: .textSecondary) + + QRCodeView( + string: getUserHexEncodedPublicKey(), + hasBackground: false, + logo: "SessionWhite40", + themeStyle: ThemeManager.currentTheme.interfaceStyle + ) + .aspectRatio(1, contentMode: .fit) + .padding(.vertical, Values.smallSpacing) + } + .padding(.all, Values.largeSpacing) + } + } + .backgroundColor(themeColor: .backgroundSecondary) + } +} + +fileprivate struct NewConversationCell: View { + let image: String + let title: String + let action: () -> () + + var body: some View { + HStack( + alignment: .center, + spacing: Values.smallSpacing + ) { + ZStack(alignment: .center) { + Image(image) + .renderingMode(.template) + .foregroundColor(themeColor: .textPrimary) + .frame(width: 25, height: 24, alignment: .bottom) + } + .frame(width: 38, height: 38, alignment: .leading) + + Text(title) + .font(.system(size: Values.mediumLargeFontSize)) + .foregroundColor(themeColor: .textPrimary) + .frame( + maxWidth: .infinity, + alignment: .leading + ) + } + .frame(height: 55) + .onTapGesture { + action() + } + } +} + +#Preview { + StartConversationScreen() +} diff --git a/Session/Meta/Translations/en.lproj/Localizable.strings b/Session/Meta/Translations/en.lproj/Localizable.strings index 8872d83db..7e945b0a7 100644 --- a/Session/Meta/Translations/en.lproj/Localizable.strings +++ b/Session/Meta/Translations/en.lproj/Localizable.strings @@ -863,7 +863,13 @@ The point that a message will disappear in a disappearing message update message "view_mnemonic_button_title" = "View Password"; "yes_button_title" = "Yes"; +//Settings "settings_view_qr_code_tab_title" = "View"; "settings_scan_qr_code_tab_title" = "Scan"; "settings_view_my_qr_code_explanation" = "This is your Account ID. Other users can scan it to start a conversation with you."; "invalid_account_id_from_qr_code_message" = "This QR code does not contain an Account ID."; + +//Start Conversation +"your_account_id" = "Your Account ID"; +"account_id_qr_code_explanation" = "Friends can message you by scanning your QR code."; +"start_conversation_screen_title" = "Start Conversation"; diff --git a/Session/Settings/QRCodeScreen.swift b/Session/Settings/QRCodeScreen.swift index 959239948..24f98d358 100644 --- a/Session/Settings/QRCodeScreen.swift +++ b/Session/Settings/QRCodeScreen.swift @@ -15,11 +15,6 @@ struct QRCodeScreen: View { var body: some View { ZStack(alignment: .topLeading) { - if #available(iOS 14.0, *) { - ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary).ignoresSafeArea() - } else { - ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary) - } VStack( spacing: 0 ){ @@ -43,6 +38,7 @@ struct QRCodeScreen: View { } } } + .backgroundColor(themeColor: .backgroundPrimary) } fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String, onError: (() -> ())?) { diff --git a/Session/Settings/RecoveryPasswordScreen.swift b/Session/Settings/RecoveryPasswordScreen.swift index 058ba7356..322a08c59 100644 --- a/Session/Settings/RecoveryPasswordScreen.swift +++ b/Session/Settings/RecoveryPasswordScreen.swift @@ -26,12 +26,6 @@ struct RecoveryPasswordScreen: View { var body: some View { ZStack(alignment: .center) { - if #available(iOS 14.0, *) { - ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary).ignoresSafeArea() - } else { - ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary) - } - ScrollView(.vertical, showsIndicators: false) { VStack( alignment: .leading, @@ -228,7 +222,9 @@ struct RecoveryPasswordScreen: View { .padding(.horizontal, Values.largeSpacing) .padding(.vertical, Values.mediumSpacing) } - }.onAppear { + } + .backgroundColor(themeColor: .backgroundPrimary) + .onAppear { Storage.shared.writeAsync { db in db[.hasViewedSeed] = true } } } diff --git a/SessionUIKit/Style Guide/Themes/SwiftUI+Theme.swift b/SessionUIKit/Style Guide/Themes/SwiftUI+Theme.swift index aad414acc..37b02cc9a 100644 --- a/SessionUIKit/Style Guide/Themes/SwiftUI+Theme.swift +++ b/SessionUIKit/Style Guide/Themes/SwiftUI+Theme.swift @@ -10,9 +10,15 @@ public extension View { } func backgroundColor(themeColor: ThemeValue) -> some View { - return self.background( - ThemeManager.currentTheme.colorSwiftUI(for: themeColor) - ) + if #available(iOSApplicationExtension 14.0, *) { + return self.background( + ThemeManager.currentTheme.colorSwiftUI(for: themeColor)?.ignoresSafeArea() + ) + } else { + return self.background( + ThemeManager.currentTheme.colorSwiftUI(for: themeColor) + ) + } } } diff --git a/SessionUIKit/Utilities/SwiftUI+Utilities.swift b/SessionUIKit/Utilities/SwiftUI+Utilities.swift index 550504629..c550d1e40 100644 --- a/SessionUIKit/Utilities/SwiftUI+Utilities.swift +++ b/SessionUIKit/Utilities/SwiftUI+Utilities.swift @@ -36,6 +36,20 @@ extension UIViewController { } } +public struct Line: View { + let color: ThemeValue + + public init(color: ThemeValue) { + self.color = color + } + + public var body: some View { + Rectangle() + .fill(themeColor: color) + .frame(height: 1) + } +} + struct EdgeBorder: Shape { var width: CGFloat