diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 3e3082d35..981986ddb 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -561,6 +561,7 @@ B821F2F82272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */; }; B821F2FA2272CEEE002C88C0 /* OnboardingKeyPairViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */; }; B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; }; + B89841E322B7579F00B1BDC6 /* NewConversationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */; }; B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; B9EB5ABD1884C002007CBB57 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; BFF3FB9730634F37D25903F4 /* Pods_Signal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D17BB5C25D615AB49813100C /* Pods_Signal.framework */; }; @@ -1349,6 +1350,7 @@ B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingAccountDetailsViewController.swift; sourceTree = ""; }; B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingKeyPairViewController.swift; sourceTree = ""; }; B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = ""; }; + B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewConversationViewController.swift; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = ""; }; B97940251832BD2400BD66CB /* UIUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIUtil.h; sourceTree = ""; }; @@ -2606,6 +2608,7 @@ children = ( B8162F0222891AD600D46544 /* FriendRequestView.swift */, B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */, + B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */, B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */, B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */, 24A830A12293CD0100F4CAC0 /* LokiP2PServer.swift */, @@ -3733,6 +3736,7 @@ 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */, 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */, 45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */, + B89841E322B7579F00B1BDC6 /* NewConversationViewController.swift in Sources */, 45FBC5C81DF8575700E9B410 /* CallKitCallManager.swift in Sources */, 4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */, 45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */, diff --git a/Signal/src/Loki/NewConversationViewController.swift b/Signal/src/Loki/NewConversationViewController.swift new file mode 100644 index 000000000..8b528627f --- /dev/null +++ b/Signal/src/Loki/NewConversationViewController.swift @@ -0,0 +1,84 @@ + +@objc(LKNewConversationViewController) +final class NewConversationViewController : OWSViewController { + + // MARK: Components + private lazy var publicKeyTextField: UITextField = { + let result = UITextField() + result.textColor = Theme.primaryColor + result.font = UIFont.ows_dynamicTypeBodyClamped + let placeholder = NSMutableAttributedString(string: NSLocalizedString("Enter a Public Key", comment: "")) + placeholder.addAttribute(.foregroundColor, value: Theme.placeholderColor, range: NSRange(location: 0, length: placeholder.length)) + result.attributedPlaceholder = placeholder + result.tintColor = UIColor.lokiGreen() + result.keyboardAppearance = .dark + return result + }() + + // MARK: Lifecycle + override func viewDidLoad() { + // Background color & margins + view.backgroundColor = Theme.backgroundColor + view.layoutMargins = .zero + // Navigation bar + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(close)) + title = NSLocalizedString("New Conversation", comment: "") + // Separator + let separator = UIView() + separator.autoSetDimension(.height, toSize: 1 / UIScreen.main.scale) + separator.backgroundColor = Theme.hairlineColor + // Explanation label + let explanationLabel = UILabel() + explanationLabel.textColor = Theme.primaryColor + explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped + explanationLabel.text = NSLocalizedString("For example: 059abcf223aa8c10e3dc2d623688b75dd25896794717e4a9c486772664fc95e41e.", comment: "") + explanationLabel.numberOfLines = 0 + explanationLabel.lineBreakMode = .byWordWrapping + // Button + let buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight() + let buttonHeight = buttonFont.pointSize * 48 / 17 + let startNewConversationButton = OWSFlatButton.button(title: NSLocalizedString("Next", comment: ""), font: buttonFont, titleColor: .white, backgroundColor: .lokiGreen(), target: self, selector: #selector(startNewConversationIfPossible)) + startNewConversationButton.autoSetDimension(.height, toSize: buttonHeight) + // Stack view + let stackView = UIStackView(arrangedSubviews: [ + publicKeyTextField, + UIView.spacer(withHeight: 8), + separator, + UIView.spacer(withHeight: 8), + explanationLabel, + UIView.vStretchingSpacer(), + startNewConversationButton + ]) + stackView.axis = .vertical + stackView.alignment = .fill + stackView.layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + stackView.isLayoutMarginsRelativeArrangement = true + view.addSubview(stackView) + stackView.autoPinWidthToSuperview() + stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0) + autoPinView(toBottomOfViewControllerOrKeyboard: stackView, avoidNotch: true) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + publicKeyTextField.becomeFirstResponder() + } + + // MARK: Interaction + @objc private func close() { + dismiss(animated: true, completion: nil) + } + + @objc private func startNewConversationIfPossible() { + let hexEncodedPublicKey = publicKeyTextField.text?.trimmingCharacters(in: .whitespaces) ?? "" + if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) { + let alert = UIAlertController(title: NSLocalizedString("Invalid Public Key", comment: ""), message: NSLocalizedString("Please check the public key you entered and try again.", comment: ""), preferredStyle: .alert) + alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil)) + presentAlert(alert) + } else { + let thread = TSContactThread.getOrCreateThread(contactId: hexEncodedPublicKey) + SignalApp.shared().presentConversation(for: thread, action: .compose, animated: false) + presentingViewController!.dismiss(animated: true, completion: nil) + } + } +} diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m index 6ba594f2e..4b9677630 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m @@ -190,7 +190,7 @@ const CGFloat kRemotelySourcedContentRowSpacing = 3; }]; innerBubbleView.layer.mask = maskLayer; if (self.isForPreview) { - innerBubbleView.backgroundColor = [UIColor.ows_signalBlueColor colorWithAlphaComponent:0.4f]; + innerBubbleView.backgroundColor = [UIColor.lokiGreen colorWithAlphaComponent:0.4f]; } else { innerBubbleView.backgroundColor = self.quoteBubbleBackgroundColor; } @@ -208,7 +208,7 @@ const CGFloat kRemotelySourcedContentRowSpacing = 3; UIView *stripeView = [UIView new]; if (self.isForPreview) { - stripeView.backgroundColor = UIColor.ows_signalBlueColor; + stripeView.backgroundColor = UIColor.lokiGreen; } else { stripeView.backgroundColor = [self.conversationStyle quotedReplyStripeColorWithIsIncoming:!self.isOutgoing]; } diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index 7fb2d2f49..bfcd77672 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -807,6 +807,11 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) { - (void)showNewConversationView { + LKNewConversationViewController *viewController = [LKNewConversationViewController new]; + OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:viewController]; + [self.navigationController presentViewController:navigationController animated:YES completion:nil]; + + /** OWSAssertIsOnMainThread(); OWSLogInfo(@""); @@ -825,6 +830,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) { OWSNavigationController *modal = [[OWSNavigationController alloc] initWithRootViewController:viewController]; [self.navigationController presentViewController:modal animated:YES completion:nil]; }]; + */ } - (void)viewWillAppear:(BOOL)animated diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 88e14d0c8..89ee4f5eb 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2592,3 +2592,8 @@ "Display Name" = "Display Name"; "Loki Messenger" = "Loki Messenger"; "Privacy Policy" = "Privacy Policy"; +"New Conversation" = "New Conversation"; +"Enter a Public Key" = "Enter a Public Key"; +"For example: 059abcf223aa8c10e3dc2d623688b75dd25896794717e4a9c486772664fc95e41e." = "For example: 059abcf223aa8c10e3dc2d623688b75dd25896794717e4a9c486772664fc95e41e."; +"Invalid Public Key" = "Invalid Public Key"; +"Please check the public key you entered and try again." = "Please check the public key you entered and try again."; diff --git a/SignalMessaging/Views/OWSSearchBar.m b/SignalMessaging/Views/OWSSearchBar.m index a24794d79..6c9e84816 100644 --- a/SignalMessaging/Views/OWSSearchBar.m +++ b/SignalMessaging/Views/OWSSearchBar.m @@ -62,11 +62,11 @@ NS_ASSUME_NONNULL_BEGIN { OWSAssertIsOnMainThread(); - UIColor *foregroundColor = Theme.placeholderColor; + UIColor *foregroundColor = UIColor.lokiLightestGray; searchBar.barTintColor = Theme.backgroundColor; searchBar.barStyle = Theme.barStyle; searchBar.tintColor = UIColor.lokiGreen; - + // Hide searchBar border. // Alternatively we could hide the border by using `UISearchBarStyleMinimal`, but that causes an issue when toggling // from light -> dark -> light theme wherein the textField background color appears darker than it should @@ -94,6 +94,12 @@ NS_ASSUME_NONNULL_BEGIN UITextField *textField = (UITextField *)view; textField.backgroundColor = Theme.searchFieldBackgroundColor; textField.textColor = Theme.primaryColor; + NSString *placeholder = textField.placeholder; + if (placeholder != nil) { + NSMutableAttributedString *attributedPlaceholder = [[NSMutableAttributedString alloc] initWithString:placeholder]; + [attributedPlaceholder addAttribute:NSForegroundColorAttributeName value:foregroundColor range:NSMakeRange(0, placeholder.length)]; + textField.attributedPlaceholder = attributedPlaceholder; + } textField.keyboardAppearance = Theme.keyboardAppearance; } }]; diff --git a/SignalMessaging/appearance/Theme.m b/SignalMessaging/appearance/Theme.m index 0351f9c11..df9e32120 100644 --- a/SignalMessaging/appearance/Theme.m +++ b/SignalMessaging/appearance/Theme.m @@ -113,7 +113,7 @@ NSString *const ThemeKeyThemeEnabled = @"ThemeKeyThemeEnabled"; + (UIColor *)placeholderColor { - return UIColor.lokiLightGray; + return UIColor.lokiGray; } + (UIColor *)hairlineColor diff --git a/SignalMessaging/categories/UIColor+OWS.h b/SignalMessaging/categories/UIColor+OWS.h index f03b4b3a7..1fd2d698d 100644 --- a/SignalMessaging/categories/UIColor+OWS.h +++ b/SignalMessaging/categories/UIColor+OWS.h @@ -60,6 +60,7 @@ NS_ASSUME_NONNULL_BEGIN + (UIColor *)lokiDarkGray; + (UIColor *)lokiGray; + (UIColor *)lokiLightGray; ++ (UIColor *)lokiLightestGray; @end diff --git a/SignalMessaging/categories/UIColor+OWS.m b/SignalMessaging/categories/UIColor+OWS.m index 1b408d7a4..902d956cf 100644 --- a/SignalMessaging/categories/UIColor+OWS.m +++ b/SignalMessaging/categories/UIColor+OWS.m @@ -210,6 +210,7 @@ NS_ASSUME_NONNULL_BEGIN + (UIColor *)lokiDarkGray { return [UIColor colorWithRGBHex:0x313131]; } + (UIColor *)lokiGray { return [UIColor colorWithRGBHex:0x363636]; } + (UIColor *)lokiLightGray { return [UIColor colorWithRGBHex:0x414141]; } ++ (UIColor *)lokiLightestGray { return [UIColor colorWithRGBHex:0x818181]; } @end