diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index afc0af7e01..a45689b8a4 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -186,9 +186,7 @@ 34684DB125C2228D00C5A93C /* indeterminate_spinner_blue.json in Resources */ = {isa = PBXBuildFile; fileRef = 34684DAD25C2228D00C5A93C /* indeterminate_spinner_blue.json */; }; 34684DB225C2228D00C5A93C /* indeterminate_spinner_white.json in Resources */ = {isa = PBXBuildFile; fileRef = 34684DAE25C2228D00C5A93C /* indeterminate_spinner_white.json */; }; 346941A1215D2EE400B5BFAD /* Theme.h in Headers */ = {isa = PBXBuildFile; fileRef = 3469419D215D2EE400B5BFAD /* Theme.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 346941A2215D2EE400B5BFAD /* OWSConversationColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3469419E215D2EE400B5BFAD /* OWSConversationColor.m */; }; 346941A3215D2EE400B5BFAD /* Theme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3469419F215D2EE400B5BFAD /* Theme.m */; }; - 346941A4215D2EE400B5BFAD /* OWSConversationColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 346B4A772369BFC600B56007 /* PermissiveGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B4A762369BFC600B56007 /* PermissiveGestureRecognizer.swift */; }; 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; }; 346C19DF25ACDF0B00061D3A /* DataSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */; }; @@ -599,7 +597,6 @@ 4C10B1BC23176D250099396B /* test-mp3.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A71FA0E46F00D35993 /* test-mp3.mp3 */; }; 4C10B1C723176DD60099396B /* SDSPerformanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C10B1C623176DD60099396B /* SDSPerformanceTest.swift */; }; 4C10B1C9231778880099396B /* PerformanceBaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C10B1C8231778880099396B /* PerformanceBaseTest.swift */; }; - 4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C13C9F520E57BA30089A98B /* ColorPickerViewController.swift */; }; 4C1885D2218F8E1C00B67051 /* PhotoGridViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1885D1218F8E1C00B67051 /* PhotoGridViewCell.swift */; }; 4C19A0FC227B356F007A0C7F /* DebugUIMessages+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C19A0FB227B356F007A0C7F /* DebugUIMessages+OWS.swift */; }; 4C20B2B720CA0034001BAC90 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */; }; @@ -1225,9 +1222,7 @@ 34684DAD25C2228D00C5A93C /* indeterminate_spinner_blue.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = indeterminate_spinner_blue.json; sourceTree = ""; }; 34684DAE25C2228D00C5A93C /* indeterminate_spinner_white.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = indeterminate_spinner_white.json; sourceTree = ""; }; 3469419D215D2EE400B5BFAD /* Theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Theme.h; sourceTree = ""; }; - 3469419E215D2EE400B5BFAD /* OWSConversationColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSConversationColor.m; sourceTree = ""; }; 3469419F215D2EE400B5BFAD /* Theme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Theme.m; sourceTree = ""; }; - 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationColor.h; sourceTree = ""; }; 346B4A762369BFC600B56007 /* PermissiveGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PermissiveGestureRecognizer.swift; sourceTree = ""; }; 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = ""; }; 346C19DE25ACDF0B00061D3A /* DataSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataSettingsTableViewController.swift; sourceTree = ""; }; @@ -1658,7 +1653,6 @@ 4C10B1C323176D250099396B /* SignalPerformanceTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignalPerformanceTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4C10B1C623176DD60099396B /* SDSPerformanceTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDSPerformanceTest.swift; sourceTree = ""; }; 4C10B1C8231778880099396B /* PerformanceBaseTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerformanceBaseTest.swift; sourceTree = ""; }; - 4C13C9F520E57BA30089A98B /* ColorPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = ""; }; 4C1885D1218F8E1C00B67051 /* PhotoGridViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoGridViewCell.swift; sourceTree = ""; }; 4C19A0FB227B356F007A0C7F /* DebugUIMessages+OWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DebugUIMessages+OWS.swift"; sourceTree = ""; }; 4C1D2333218B692800A0598F /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = translations/ko.lproj/Localizable.strings; sourceTree = ""; }; @@ -2680,8 +2674,6 @@ isa = PBXGroup; children = ( 343DA0002645CA720000833C /* ChatColors.swift */, - 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */, - 3469419E215D2EE400B5BFAD /* OWSConversationColor.m */, 3469419D215D2EE400B5BFAD /* Theme.h */, 3469419F215D2EE400B5BFAD /* Theme.m */, 4C29587F233AE23000AAB2AA /* Theme+OWS.swift */, @@ -2881,7 +2873,6 @@ 34D5CCA71EAE3D30005515DB /* AvatarViewHelper.h */, 34D5CCA81EAE3D30005515DB /* AvatarViewHelper.m */, 4C46361022EB98EC00185951 /* CameraFirstNavigationController.swift */, - 4C13C9F520E57BA30089A98B /* ColorPickerViewController.swift */, 348BB25C20A0C5530047AEC2 /* ContactShareViewHelper.swift */, 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */, 34E88D252098C5AE00A608F4 /* ContactViewController.swift */, @@ -4150,7 +4141,6 @@ 346941A1215D2EE400B5BFAD /* Theme.h in Headers */, 346129E21FD5C0BE00532771 /* VersionMigrations.h in Headers */, 453518961FC63DBF00210559 /* SignalMessaging.h in Headers */, - 346941A4215D2EE400B5BFAD /* OWSConversationColor.h in Headers */, 3461295A1FD1D74C00532771 /* Environment.h in Headers */, 450C801020AD1AE400F3A091 /* OWSWindowManager.h in Headers */, 34480B631FD0A98800BC14EF /* UIView+OWS.h in Headers */, @@ -4893,7 +4883,6 @@ 3498A0A824DC936300CA492C /* ContactsViewHelper.swift in Sources */, 88EFF4F625AD1C82000FAFBA /* ThemeHeaderView.swift in Sources */, 4C046AA7236148880035B234 /* OWSGroupSyncProcessingJobQueue.swift in Sources */, - 346941A2215D2EE400B5BFAD /* OWSConversationColor.m in Sources */, 34AC0A17211B39EA00997B47 /* VideoPlayerView.swift in Sources */, 4C9D347F23689E06006A4307 /* IncomingContactSyncJobQueue.swift in Sources */, 4C35B08A23F8A9D2003EB937 /* MessageRequestPendingReceipts.swift in Sources */, @@ -5378,7 +5367,6 @@ 34848D6325D44EBD00E5034B /* PaymentsTransferInViewController.swift in Sources */, 4C21D5D8223AC60F00EF8A77 /* PhotoCapture.swift in Sources */, 8871B16F25F007DE00D4E070 /* ProfileSettingsViewController.swift in Sources */, - 4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */, 4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */, 4C30E226234FB033009558B7 /* SecondaryLinkingQRCodeViewController.swift in Sources */, 3448E16022134C89004B052E /* OnboardingSplashViewController.swift in Sources */, diff --git a/Signal/src/Calls/UserInterface/Group/GroupCallMemberView.swift b/Signal/src/Calls/UserInterface/Group/GroupCallMemberView.swift index 9cf7628a40..332e2c53d7 100644 --- a/Signal/src/Calls/UserInterface/Group/GroupCallMemberView.swift +++ b/Signal/src/Calls/UserInterface/Group/GroupCallMemberView.swift @@ -212,8 +212,8 @@ class GroupCallLocalMemberView: GroupCallMemberView { return owsFailDebug("missing local address") } - let conversationColorName = databaseStorage.uiRead { transaction in - return self.contactsManager.conversationColorName(for: localAddress, transaction: transaction) + let chatColorValue = databaseStorage.read { transaction in + ChatColors.chatColorForRendering(address: localAddress, transaction: transaction) } backgroundAvatarView.image = profileManager.localProfileAvatarImage() diff --git a/Signal/src/ViewControllers/ColorPickerViewController.swift b/Signal/src/ViewControllers/ColorPickerViewController.swift deleted file mode 100644 index b84a089d7e..0000000000 --- a/Signal/src/ViewControllers/ColorPickerViewController.swift +++ /dev/null @@ -1,245 +0,0 @@ -// -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. -// - -import Foundation - -@objc -class OWSColorPickerAccessoryView: NeverClearView { - override var intrinsicContentSize: CGSize { - return CGSize(square: kSwatchSize) - } - - override func sizeThatFits(_ size: CGSize) -> CGSize { - return self.intrinsicContentSize - } - - let kSwatchSize: CGFloat = 24 - - @objc - required init(color: UIColor) { - super.init(frame: .zero) - - let circleView = CircleView(diameter: kSwatchSize) - circleView.backgroundColor = color - addSubview(circleView) - circleView.autoPinEdgesToSuperviewEdges() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -// MARK: - - -protocol ColorViewDelegate: class { - func colorViewWasTapped(_ colorView: ColorView) -} - -class ColorView: UIView { - public weak var delegate: ColorViewDelegate? - public let conversationColor: OWSConversationColor - - private let swatchView: CircleView - private let selectedRing: CircleView - public var isSelected: Bool = false { - didSet { - self.selectedRing.isHidden = !isSelected - } - } - - required init(conversationColor: OWSConversationColor) { - self.conversationColor = conversationColor - self.swatchView = CircleView() - self.selectedRing = CircleView() - - super.init(frame: .zero) - self.addSubview(selectedRing) - self.addSubview(swatchView) - - // Selected Ring - let cellHeight: CGFloat = ScaleFromIPhone5(60) - selectedRing.autoSetDimensions(to: CGSize(square: cellHeight)) - - selectedRing.layer.borderColor = Theme.secondaryTextAndIconColor.cgColor - selectedRing.layer.borderWidth = 2 - selectedRing.autoPinEdgesToSuperviewEdges() - selectedRing.isHidden = true - - // Color Swatch - swatchView.backgroundColor = conversationColor.primaryColor - - let swatchSize: CGFloat = ScaleFromIPhone5(46) - swatchView.autoSetDimensions(to: CGSize(square: swatchSize)) - - swatchView.autoCenterInSuperview() - - // gestures - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap)) - self.addGestureRecognizer(tapGesture) - } - - required init?(coder aDecoder: NSCoder) { - notImplemented() - } - - // MARK: Actions - - @objc - func didTap() { - delegate?.colorViewWasTapped(self) - } -} - -@objc -protocol ColorPickerDelegate: class { - func colorPicker(_ colorPicker: ColorPicker, didPickConversationColor conversationColor: OWSConversationColor) -} - -@objc(OWSColorPicker) -class ColorPicker: NSObject, ColorPickerViewDelegate { - - @objc - public weak var delegate: ColorPickerDelegate? - - @objc - let sheetViewController: SheetViewController - - @objc - init(thread: TSThread) { - let colorName = thread.conversationColorName - let currentConversationColor = OWSConversationColor.conversationColorOrDefault(colorName: colorName) - sheetViewController = SheetViewController() - - super.init() - - let colorPickerView = ColorPickerView(thread: thread) - colorPickerView.delegate = self - colorPickerView.select(conversationColor: currentConversationColor) - - sheetViewController.contentView.addSubview(colorPickerView) - colorPickerView.autoPinEdgesToSuperviewEdges() - } - - // MARK: ColorPickerViewDelegate - - func colorPickerView(_ colorPickerView: ColorPickerView, didPickConversationColor conversationColor: OWSConversationColor) { - self.delegate?.colorPicker(self, didPickConversationColor: conversationColor) - } -} - -protocol ColorPickerViewDelegate: class { - func colorPickerView(_ colorPickerView: ColorPickerView, didPickConversationColor conversationColor: OWSConversationColor) -} - -class ColorPickerView: UIView, ColorViewDelegate { - - private let thread: TSThread - private let colorViews: [ColorView] - weak var delegate: ColorPickerViewDelegate? - - let mockConversationView = MockConversationView( - model: MockConversationView.MockModel(items: [ - .incoming(text: NSLocalizedString( - "COLOR_PICKER_DEMO_MESSAGE_2", - comment: "The second of two messages demonstrating the chosen conversation color, by rendering this message in an incoming message bubble." - )), - .outgoing(text: NSLocalizedString( - "COLOR_PICKER_DEMO_MESSAGE_1", - comment: "The first of two messages demonstrating the chosen conversation color, by rendering this message in an outgoing message bubble." - )) - ]), - hasWallpaper: false, - customChatColor: nil - ) - - init(thread: TSThread) { - - self.thread = thread - - let allConversationColors = OWSConversationColor.conversationColorNames.map { OWSConversationColor.conversationColorOrDefault(colorName: $0) } - - self.colorViews = allConversationColors.map { ColorView(conversationColor: $0) } - - super.init(frame: .zero) - - mockConversationView.conversationColor = thread.conversationColorName - - colorViews.forEach { $0.delegate = self } - - let headerView = self.buildHeaderView() - - let paletteView = self.buildPaletteView(colorViews: colorViews) - - let rowsStackView = UIStackView(arrangedSubviews: [headerView, mockConversationView, paletteView]) - rowsStackView.axis = .vertical - addSubview(rowsStackView) - rowsStackView.autoPinEdgesToSuperviewEdges() - } - - required init?(coder aDecoder: NSCoder) { - notImplemented() - } - - // MARK: ColorViewDelegate - - func colorViewWasTapped(_ colorView: ColorView) { - self.select(conversationColor: colorView.conversationColor) - self.delegate?.colorPickerView(self, didPickConversationColor: colorView.conversationColor) - mockConversationView.conversationColor = colorView.conversationColor.name - } - - fileprivate func select(conversationColor selectedConversationColor: OWSConversationColor) { - colorViews.forEach { colorView in - colorView.isSelected = colorView.conversationColor == selectedConversationColor - } - } - - // MARK: View Building - - private func buildHeaderView() -> UIView { - let headerView = UIView() - headerView.layoutMargins = UIEdgeInsets(top: 15, left: 16, bottom: 15, right: 16) - - let titleLabel = UILabel() - titleLabel.text = NSLocalizedString("COLOR_PICKER_SHEET_TITLE", comment: "Modal Sheet title when picking a conversation color.") - titleLabel.textAlignment = .center - titleLabel.font = UIFont.ows_dynamicTypeBody.ows_semibold - titleLabel.textColor = Theme.primaryTextColor - - headerView.addSubview(titleLabel) - titleLabel.autoPinEdgesToSuperviewMargins() - - let bottomBorderView = UIView() - bottomBorderView.backgroundColor = Theme.hairlineColor - headerView.addSubview(bottomBorderView) - bottomBorderView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .top) - bottomBorderView.autoSetDimension(.height, toSize: CGHairlineWidth()) - - return headerView - } - - private func buildPaletteView(colorViews: [ColorView]) -> UIView { - let paletteView = UIView() - let paletteMargin = ScaleFromIPhone5(12) - paletteView.layoutMargins = UIEdgeInsets(top: paletteMargin, left: paletteMargin, bottom: 0, right: paletteMargin) - - let kRowLength = 4 - let rows: [UIView] = colorViews.chunked(by: kRowLength).map { colorViewsInRow in - let row = UIStackView(arrangedSubviews: colorViewsInRow) - row.distribution = UIStackView.Distribution.equalSpacing - return row - } - let rowsStackView = UIStackView(arrangedSubviews: rows) - rowsStackView.axis = .vertical - rowsStackView.spacing = ScaleFromIPhone5To7Plus(12, 30) - - paletteView.addSubview(rowsStackView) - rowsStackView.autoPinEdgesToSuperviewMargins() - - // no-op gesture to keep taps from dismissing SheetView - paletteView.addGestureRecognizer(UITapGestureRecognizer(target: nil, action: nil)) - return paletteView - } -} diff --git a/Signal/src/ViewControllers/ConversationView/CV/CVAvatarBuilder.swift b/Signal/src/ViewControllers/ConversationView/CV/CVAvatarBuilder.swift index d7a4edcd75..aa655f11c8 100644 --- a/Signal/src/ViewControllers/ConversationView/CV/CVAvatarBuilder.swift +++ b/Signal/src/ViewControllers/ConversationView/CV/CVAvatarBuilder.swift @@ -36,9 +36,9 @@ public class CVAvatarBuilder: Dependencies { if let avatar = cache[cacheKey] { return avatar } - let colorName = contactsManager.conversationColorName(for: address, transaction: transaction) + let avatarColor = ChatColors.avatarColor(forAddress: address, transaction: transaction) guard let rawAvatar = OWSContactAvatarBuilder(address: address, - colorName: colorName, + avatarColor: avatarColor, diameter: diameter, localUserDisplayMode: localUserDisplayMode, transaction: transaction).build(with: transaction) else { diff --git a/Signal/src/ViewControllers/GroupInviteLinksUI.swift b/Signal/src/ViewControllers/GroupInviteLinksUI.swift index c4f22895fe..d524709d9d 100644 --- a/Signal/src/ViewControllers/GroupInviteLinksUI.swift +++ b/Signal/src/ViewControllers/GroupInviteLinksUI.swift @@ -201,8 +201,12 @@ class GroupInviteLinksActionSheet: ActionSheetController { } private func loadDefaultContent() { + let avatarColor = databaseStorage.read { transaction in + ChatColors.avatarColor(forGroupId: groupV2ContextInfo.groupId, + transaction: transaction) + } avatarView.image = OWSGroupAvatarBuilder.defaultAvatar(forGroupId: groupV2ContextInfo.groupId, - conversationColorName: ConversationColorName.default.rawValue, + avatarColor: avatarColor, diameter: Self.avatarSize) groupTitleLabel.text = NSLocalizedString("GROUP_LINK_ACTION_SHEET_VIEW_LOADING_TITLE", comment: "Label indicating that the group info is being loaded in the 'group invite link' action sheet.") diff --git a/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift b/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift index 046890a217..1020527de1 100644 --- a/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift +++ b/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift @@ -67,10 +67,6 @@ extension ConversationSettingsViewController { addSystemContactItemIfNecessary(to: mainSection) addSafetyNumberItemIfNecessary(to: mainSection) - if DebugFlags.shouldShowColorPicker { - addColorPickerItems(to: mainSection) - } - contents.addSection(mainSection) addAllMediaSectionIfNecessary(to: contents) @@ -313,27 +309,6 @@ extension ConversationSettingsViewController { )) } - private func addColorPickerItems(to section: OWSTableSection) { - section.add(OWSTableItem(customCellBlock: { [weak self] in - guard let self = self else { - owsFailDebug("Missing self") - return OWSTableItem.newCell() - } - - let colorName = self.thread.conversationColorName - let currentColor = OWSConversationColor.conversationColorOrDefault(colorName: colorName).themeColor - let title = NSLocalizedString("CONVERSATION_SETTINGS_CONVERSATION_COLOR", - comment: "Label for table cell which leads to picking a new conversation color") - return self.buildCell(name: title, - icon: .settingsColorPalette, - disclosureIconColor: currentColor, - accessibilityIdentifier: UIView.accessibilityIdentifier(in: self, name: "conversation_color")) - }, - actionBlock: { [weak self] in - self?.showColorPicker() - })) - } - private func buildBlockAndLeaveSection() -> OWSTableSection { let section = OWSTableSection() diff --git a/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController.swift b/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController.swift index a2f1af08fc..210de804a3 100644 --- a/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController.swift +++ b/Signal/src/ViewControllers/ThreadSettings/ConversationSettingsViewController.swift @@ -61,9 +61,6 @@ class ConversationSettingsViewController: OWSTableViewController2 { var disappearingMessagesConfiguration: OWSDisappearingMessagesConfiguration var avatarView: UIImageView? - // This is currently disabled behind a feature flag. - private var colorPicker: ColorPicker? - var isShowingAllGroupMembers = false var isShowingAllMutualGroups = false @@ -158,12 +155,6 @@ class ConversationSettingsViewController: OWSTableViewController2 { backgroundTopView.autoSetDimension(.height, toSize: backgroundTopSize) backgroundTopView.autoPinEdge(.bottom, to: .top, of: tableView, withOffset: 0) - if DebugFlags.shouldShowColorPicker { - let colorPicker = ColorPicker(thread: self.thread) - colorPicker.delegate = self - self.colorPicker = colorPicker - } - tableView.register(ContactTableViewCell.self, forCellReuseIdentifier: ContactTableViewCell.reuseIdentifier) observeNotifications() @@ -946,43 +937,6 @@ extension ConversationSettingsViewController: CNContactViewControllerDelegate { // MARK: - -extension ConversationSettingsViewController: ColorPickerDelegate { - - func showColorPicker() { - guard let colorPicker = colorPicker else { - owsFailDebug("Missing colorPicker.") - return - } - let sheetViewController = colorPicker.sheetViewController - sheetViewController.dismissHandler = { [weak self] _ in - self?.dismiss(animated: true) - } - self.present(sheetViewController, animated: true) { - Logger.info("presented sheet view") - } - } - - public func colorPicker(_ colorPicker: ColorPicker, didPickConversationColor conversationColor: OWSConversationColor) { - Logger.debug("picked color: \(conversationColor.name)") - databaseStorage.write { transaction in - self.thread.updateConversationColorName(conversationColor.name, transaction: transaction) - } - - contactsManagerImpl.removeAllFromAvatarCache() - contactsManagerImpl.clearColorNameCache() - updateTableContents() - conversationSettingsViewDelegate?.conversationColorWasUpdated() - - DispatchQueue.global().async { - let operation = ConversationConfigurationSyncOperation(thread: self.thread) - assert(operation.isReady) - operation.start() - } - } -} - -// MARK: - - extension ConversationSettingsViewController: GroupAttributesViewControllerDelegate { func groupAttributesDidUpdate() { reloadThreadAndUpdateContent() diff --git a/SignalMessaging/SignalMessaging.h b/SignalMessaging/SignalMessaging.h index 761bbf9d45..875da29072 100644 --- a/SignalMessaging/SignalMessaging.h +++ b/SignalMessaging/SignalMessaging.h @@ -25,7 +25,6 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[]; #import #import #import -#import #import #import #import diff --git a/SignalMessaging/Views/ConversationAvatarView.swift b/SignalMessaging/Views/ConversationAvatarView.swift index d239b6e512..ddf3c7f152 100644 --- a/SignalMessaging/Views/ConversationAvatarView.swift +++ b/SignalMessaging/Views/ConversationAvatarView.swift @@ -370,7 +370,7 @@ public class ConversationAvatarView: AvatarImageView { switch content { case .contact(let contactThread): return buildContactAvatar(address: contactThread.contactAddress, - conversationColorName: contactThread.conversationColorName, + avatarColor: ChatColors.avatarColor(forThread: contactThread), diameter: diameter, localUserDisplayMode: configuration.localUserDisplayMode, transaction: transaction) @@ -379,10 +379,9 @@ public class ConversationAvatarView: AvatarImageView { diameter: diameter, transaction: transaction) case .unknownContact(let contactAddress): - let conversationColorName = TSContactThread.conversationColorName(forContactAddress: contactAddress, - transaction: transaction) + let avatarColor = ChatColors.avatarColor(forAddress: contactAddress, transaction: transaction) return buildContactAvatar(address: contactAddress, - conversationColorName: conversationColorName, + avatarColor: avatarColor, diameter: diameter, localUserDisplayMode: configuration.localUserDisplayMode, transaction: transaction) @@ -402,12 +401,12 @@ public class ConversationAvatarView: AvatarImageView { } private static func buildContactAvatar(address: SignalServiceAddress, - conversationColorName: ConversationColorName, + avatarColor: UIColor, diameter: UInt, localUserDisplayMode: LocalUserDisplayMode, transaction: SDSAnyReadTransaction) -> UIImage? { let builder = OWSContactAvatarBuilder(address: address, - colorName: conversationColorName, + avatarColor: avatarColor, diameter: diameter, localUserDisplayMode: localUserDisplayMode, transaction: transaction) diff --git a/SignalMessaging/Views/NonContactTableViewCell.swift b/SignalMessaging/Views/NonContactTableViewCell.swift index 3240653312..9f4da99b04 100644 --- a/SignalMessaging/Views/NonContactTableViewCell.swift +++ b/SignalMessaging/Views/NonContactTableViewCell.swift @@ -75,9 +75,12 @@ public class NonContactTableViewCell: UITableViewCell { if isRegistered { let address = SignalServiceAddress(phoneNumber: phoneNumber) + let avatarColor = databaseStorage.read { transaction in + ChatColors.avatarColor(forAddress: address, transaction: transaction) + } let avatarBuilder = OWSContactAvatarBuilder( address: address, - colorName: TSThread.stableColorNameForNewConversation(with: address.stringForDisplay), + avatarColor: avatarColor, diameter: 48, localUserDisplayMode: .asUser ) diff --git a/SignalMessaging/appearance/ChatColors.swift b/SignalMessaging/appearance/ChatColors.swift index 8676eab1e8..177ec82826 100644 --- a/SignalMessaging/appearance/ChatColors.swift +++ b/SignalMessaging/appearance/ChatColors.swift @@ -113,7 +113,7 @@ public struct ChatColorValue: Equatable, Codable { } public static var placeholderValue: ChatColorValue { - ChatColors.noWallpaperAutoChatColor + ChatColors.defaultChatColorValue } // MARK: - Equatable @@ -253,7 +253,7 @@ public class ChatColors: NSObject, Dependencies { } public static var allValuesSorted: [ChatColorValue] { Self.chatColors.allValuesSorted } - public static var noWallpaperAutoChatColor: ChatColorValue { Self.value_ultramarine } + public static var defaultChatColorValue: ChatColorValue { Self.value_ultramarine } public static func autoChatColor(forThread thread: TSThread?, transaction: SDSAnyReadTransaction) -> ChatColorValue { @@ -261,7 +261,7 @@ public class ChatColors: NSObject, Dependencies { wallpaper != .photo { return autoChatColor(forWallpaper: wallpaper) } else { - return Self.noWallpaperAutoChatColor + return Self.defaultChatColorValue } } @@ -304,6 +304,14 @@ public class ChatColors: NSObject, Dependencies { } } + public static func chatColorForRendering(address: SignalServiceAddress, + transaction: SDSAnyReadTransaction) -> ChatColorValue { + guard let thread = TSContactThread.getWithContactAddress(address, transaction: transaction) else { + return Self.defaultChatColorValue + } + return chatColorForRendering(thread: thread, transaction: transaction) + } + public static func setChatColorSetting(_ value: ChatColorValue?, thread: TSThread, transaction: SDSAnyWriteTransaction) { @@ -615,7 +623,12 @@ public extension ChatColors { return GroupNameColors(colorMap: colorMap, defaultColor: defaultColor) } - private struct GroupNameColorValue { + private static var defaultGroupNameColor: UIColor { + let isDarkThemeEnabled = Theme.isDarkThemeEnabled + return Self.groupNameColorValues.first!.color(isDarkThemeEnabled: isDarkThemeEnabled) + } + + fileprivate struct GroupNameColorValue { let lightTheme: UIColor let darkTheme: UIColor @@ -625,7 +638,7 @@ public extension ChatColors { } // In descending order of contrast with the other values. - private static let groupNameColorValues: [GroupNameColorValue] = [ + fileprivate static let groupNameColorValues: [GroupNameColorValue] = [ GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xD00B0B), darkTheme: UIColor(rgbHex: 0xF76E6E)), GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x067906), @@ -700,3 +713,52 @@ public extension ChatColors { darkTheme: UIColor(rgbHex: 0xF76E85)) ] } + +// MARK: - Avatar Colors + +@objc +public extension ChatColors { + static var defaultAvatarColor: UIColor { + Self.defaultGroupNameColor + } + + static func avatarColor(forAddress address: SignalServiceAddress, + transaction: SDSAnyReadTransaction) -> UIColor { + guard let thread = TSContactThread.getWithContactAddress(address, + transaction: transaction) else { + guard let seed = address.serviceIdentifier else { + owsFailDebug("Missing serviceIdentifier.") + return Self.defaultAvatarColor + } + return avatarColor(forSeed: seed) + } + return avatarColor(forThread: thread) + } + + static func avatarColor(forThread thread: TSThread) -> UIColor { + avatarColor(forSeed: thread.uniqueId) + } + + static func avatarColor(forGroupModel groupModel: TSGroupModel, + transaction: SDSAnyReadTransaction) -> UIColor { + avatarColor(forGroupId: groupModel.groupId, transaction: transaction) + } + + static func avatarColor(forGroupId groupId: Data, + transaction: SDSAnyReadTransaction) -> UIColor { + let threadUniqueId = TSGroupThread.threadId(forGroupId: groupId, + transaction: transaction) + return avatarColor(forSeed: groupId) + } + + static func avatarColor(forSeed seed: String) -> UIColor { + let hash = seed.hash + let values = Self.groupNameColorValues + guard let value = values[safe: hash % values.count] else { + owsFailDebug("Could not determine avatar color.") + return Self.defaultAvatarColor + } + let isDarkThemeEnabled = Theme.isDarkThemeEnabled + return value.color(isDarkThemeEnabled: isDarkThemeEnabled) + } +} diff --git a/SignalMessaging/appearance/OWSConversationColor.h b/SignalMessaging/appearance/OWSConversationColor.h deleted file mode 100644 index ade4a69690..0000000000 --- a/SignalMessaging/appearance/OWSConversationColor.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (c) 2019 Open Whisper Systems. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface OWSConversationColor : NSObject - -@property (nonatomic, readonly) ConversationColorName name; -@property (nonatomic, readonly) UIColor *primaryColor; -@property (nonatomic, readonly) UIColor *shadeColor; -@property (nonatomic, readonly) UIColor *tintColor; - -@property (nonatomic, readonly) UIColor *themeColor; - -+ (OWSConversationColor *)conversationColorWithName:(ConversationColorName)name - primaryColor:(UIColor *)primaryColor - shadeColor:(UIColor *)shadeColor - tintColor:(UIColor *)tintColor; -#pragma mark - Conversation Colors - -@property (class, readonly, nonatomic) UIColor *ows_crimsonColor; -@property (class, readonly, nonatomic) UIColor *ows_vermilionColor; -@property (class, readonly, nonatomic) UIColor *ows_burlapColor; -@property (class, readonly, nonatomic) UIColor *ows_forestColor; -@property (class, readonly, nonatomic) UIColor *ows_wintergreenColor; -@property (class, readonly, nonatomic) UIColor *ows_tealColor; -@property (class, readonly, nonatomic) UIColor *ows_blueColor; -@property (class, readonly, nonatomic) UIColor *ows_indigoColor; -@property (class, readonly, nonatomic) UIColor *ows_violetColor; -@property (class, readonly, nonatomic) UIColor *ows_plumColor; -@property (class, readonly, nonatomic) UIColor *ows_taupeColor; -@property (class, readonly, nonatomic) UIColor *ows_steelColor; - -#pragma mark - Conversation Colors (Tint) - -@property (class, readonly, nonatomic) UIColor *ows_crimsonTintColor; -@property (class, readonly, nonatomic) UIColor *ows_vermilionTintColor; -@property (class, readonly, nonatomic) UIColor *ows_burlapTintColor; -@property (class, readonly, nonatomic) UIColor *ows_forestTintColor; -@property (class, readonly, nonatomic) UIColor *ows_wintergreenTintColor; -@property (class, readonly, nonatomic) UIColor *ows_tealTintColor; -@property (class, readonly, nonatomic) UIColor *ows_blueTintColor; -@property (class, readonly, nonatomic) UIColor *ows_indigoTintColor; -@property (class, readonly, nonatomic) UIColor *ows_violetTintColor; -@property (class, readonly, nonatomic) UIColor *ows_plumTintColor; -@property (class, readonly, nonatomic) UIColor *ows_taupeTintColor; -@property (class, readonly, nonatomic) UIColor *ows_steelTintColor; - -#pragma mark - Conversation Colors (Shade) - -@property (class, readonly, nonatomic) UIColor *ows_crimsonShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_vermilionShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_burlapShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_forestShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_wintergreenShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_tealShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_blueShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_indigoShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_violetShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_plumShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_taupeShadeColor; -@property (class, readonly, nonatomic) UIColor *ows_steelShadeColor; - -#pragma mark - Conversation Colors - -+ (nullable OWSConversationColor *)conversationColorForColorName:(ConversationColorName)colorName - NS_SWIFT_NAME(conversationColor(colorName:)); - -// If the conversation color name is valid, return its colors. -// Otherwise return the "default" conversation colors. -+ (OWSConversationColor *)conversationColorOrDefaultForColorName:(ConversationColorName)conversationColorName - NS_SWIFT_NAME(conversationColorOrDefault(colorName:)); - -@property (class, readonly, nonatomic) NSArray *conversationColorNames; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/appearance/OWSConversationColor.m b/SignalMessaging/appearance/OWSConversationColor.m deleted file mode 100644 index 8d4712d1e9..0000000000 --- a/SignalMessaging/appearance/OWSConversationColor.m +++ /dev/null @@ -1,359 +0,0 @@ -// -// Copyright (c) 2020 Open Whisper Systems. All rights reserved. -// - -#import "OWSConversationColor.h" -#import "Theme.h" -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface OWSConversationColor () - -@property (nonatomic) ConversationColorName name; -@property (nonatomic) UIColor *primaryColor; -@property (nonatomic) UIColor *shadeColor; -@property (nonatomic) UIColor *tintColor; - -@end - -#pragma mark - - -@implementation OWSConversationColor - -+ (OWSConversationColor *)conversationColorWithName:(ConversationColorName)name - primaryColor:(UIColor *)primaryColor - shadeColor:(UIColor *)shadeColor - tintColor:(UIColor *)tintColor -{ - OWSConversationColor *instance = [OWSConversationColor new]; - instance.name = name; - instance.primaryColor = primaryColor; - instance.shadeColor = shadeColor; - instance.tintColor = tintColor; - return instance; -} - -#pragma mark - - -- (UIColor *)themeColor -{ - return Theme.isDarkThemeEnabled ? self.shadeColor : self.primaryColor; -} - -- (BOOL)isEqual:(id)other -{ - if (![other isKindOfClass:[OWSConversationColor class]]) { - return NO; - } - - OWSConversationColor *otherColor = (OWSConversationColor *)other; - return [self.name isEqual:otherColor.name]; -} - -#pragma mark - Conversation Color (Primary) - -+ (UIColor *)ows_crimsonColor -{ - return [UIColor colorWithRGBHex:0xCC163D]; -} - -+ (UIColor *)ows_vermilionColor -{ - return [UIColor colorWithRGBHex:0xC73800]; -} - -+ (UIColor *)ows_burlapColor -{ - return [UIColor colorWithRGBHex:0x746C53]; -} - -+ (UIColor *)ows_forestColor -{ - return [UIColor colorWithRGBHex:0x3B7845]; -} - -+ (UIColor *)ows_wintergreenColor -{ - return [UIColor colorWithRGBHex:0x1C8260]; -} - -+ (UIColor *)ows_tealColor -{ - return [UIColor colorWithRGBHex:0x067589]; -} - -+ (UIColor *)ows_blueColor -{ - return [UIColor colorWithRGBHex:0x336BA3]; -} - -+ (UIColor *)ows_indigoColor -{ - return [UIColor colorWithRGBHex:0x5951C8]; -} - -+ (UIColor *)ows_violetColor -{ - return [UIColor colorWithRGBHex:0x862CAF]; -} - -+ (UIColor *)ows_plumColor -{ - return [UIColor colorWithRGBHex:0xA23474]; -} - -+ (UIColor *)ows_taupeColor -{ - return [UIColor colorWithRGBHex:0x895D66]; -} - -+ (UIColor *)ows_steelColor -{ - return [UIColor colorWithRGBHex:0x6B6B78]; -} - -#pragma mark - Conversation Colors (Tint) - -+ (UIColor *)ows_crimsonTintColor -{ - return [UIColor colorWithRGBHex:0xEDA6AE]; -} - -+ (UIColor *)ows_vermilionTintColor -{ - return [UIColor colorWithRGBHex:0xEBA78E]; -} - -+ (UIColor *)ows_burlapTintColor -{ - return [UIColor colorWithRGBHex:0xC4B997]; -} - -+ (UIColor *)ows_forestTintColor -{ - return [UIColor colorWithRGBHex:0x8FCC9A]; -} - -+ (UIColor *)ows_wintergreenTintColor -{ - return [UIColor colorWithRGBHex:0x9BCFBD]; -} - -+ (UIColor *)ows_tealTintColor -{ - return [UIColor colorWithRGBHex:0xA5CAD5]; -} - -+ (UIColor *)ows_blueTintColor -{ - return [UIColor colorWithRGBHex:0xADC8E1]; -} - -+ (UIColor *)ows_indigoTintColor -{ - return [UIColor colorWithRGBHex:0xC2C1E7]; -} - -+ (UIColor *)ows_violetTintColor -{ - return [UIColor colorWithRGBHex:0xCDADDC]; -} - -+ (UIColor *)ows_plumTintColor -{ - return [UIColor colorWithRGBHex:0xDCB2CA]; -} - -+ (UIColor *)ows_taupeTintColor -{ - return [UIColor colorWithRGBHex:0xCFB5BB]; -} - -+ (UIColor *)ows_steelTintColor -{ - return [UIColor colorWithRGBHex:0xBEBEC6]; -} - -#pragma mark - Conversation Colors (Shade) - -+ (UIColor *)ows_crimsonShadeColor -{ - return [UIColor colorWithRGBHex:0x8A0F29]; -} - -+ (UIColor *)ows_vermilionShadeColor -{ - return [UIColor colorWithRGBHex:0x872600]; -} - -+ (UIColor *)ows_burlapShadeColor -{ - return [UIColor colorWithRGBHex:0x58513C]; -} - -+ (UIColor *)ows_forestShadeColor -{ - return [UIColor colorWithRGBHex:0x2B5934]; -} - -+ (UIColor *)ows_wintergreenShadeColor -{ - return [UIColor colorWithRGBHex:0x36544A]; -} - -+ (UIColor *)ows_tealShadeColor -{ - return [UIColor colorWithRGBHex:0x055968]; -} - -+ (UIColor *)ows_blueShadeColor -{ - return [UIColor colorWithRGBHex:0x285480]; -} - -+ (UIColor *)ows_indigoShadeColor -{ - return [UIColor colorWithRGBHex:0x4840A0]; -} - -+ (UIColor *)ows_violetShadeColor -{ - return [UIColor colorWithRGBHex:0x6B248A]; -} - -+ (UIColor *)ows_plumShadeColor -{ - return [UIColor colorWithRGBHex:0x881B5B]; -} - -+ (UIColor *)ows_taupeShadeColor -{ - return [UIColor colorWithRGBHex:0x6A4E54]; -} - -+ (UIColor *)ows_steelShadeColor -{ - return [UIColor colorWithRGBHex:0x5A5A63]; -} - -+ (NSArray *)allConversationColors -{ - static NSArray *allConversationColors; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - // Order here affects the order in the conversation color picker. - allConversationColors = @[ - [OWSConversationColor conversationColorWithName:ConversationColorNameCrimson - primaryColor:self.ows_crimsonColor - shadeColor:self.ows_crimsonShadeColor - tintColor:self.ows_crimsonTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameVermilion - primaryColor:self.ows_vermilionColor - shadeColor:self.ows_vermilionShadeColor - tintColor:self.ows_vermilionTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameBurlap - primaryColor:self.ows_burlapColor - shadeColor:self.ows_burlapShadeColor - tintColor:self.ows_burlapTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameForest - primaryColor:self.ows_forestColor - shadeColor:self.ows_forestShadeColor - tintColor:self.ows_forestTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameWintergreen - primaryColor:self.ows_wintergreenColor - shadeColor:self.ows_wintergreenShadeColor - tintColor:self.ows_wintergreenTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameTeal - primaryColor:self.ows_tealColor - shadeColor:self.ows_tealShadeColor - tintColor:self.ows_tealTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameBlue - primaryColor:self.ows_blueColor - shadeColor:self.ows_blueShadeColor - tintColor:self.ows_blueTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameIndigo - primaryColor:self.ows_indigoColor - shadeColor:self.ows_indigoShadeColor - tintColor:self.ows_indigoTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameViolet - primaryColor:self.ows_violetColor - shadeColor:self.ows_violetShadeColor - tintColor:self.ows_violetTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNamePlum - primaryColor:self.ows_plumColor - shadeColor:self.ows_plumShadeColor - tintColor:self.ows_plumTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameTaupe - primaryColor:self.ows_taupeColor - shadeColor:self.ows_taupeShadeColor - tintColor:self.ows_taupeTintColor], - [OWSConversationColor conversationColorWithName:ConversationColorNameSteel - primaryColor:self.ows_steelColor - shadeColor:self.ows_steelShadeColor - tintColor:self.ows_steelTintColor], - ]; - }); - - return allConversationColors; -} - -+ (NSDictionary *)conversationColorMap -{ - static NSDictionary *colorMap; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSMutableDictionary *mutableColorMap = [NSMutableDictionary new]; - for (OWSConversationColor *conversationColor in self.allConversationColors) { - mutableColorMap[conversationColor.name] = conversationColor; - } - colorMap = [mutableColorMap copy]; - }); - - return colorMap; -} - -+ (NSArray *)conversationColorNames -{ - NSMutableArray *names = [NSMutableArray new]; - for (OWSConversationColor *conversationColor in self.allConversationColors) { - [names addObject:conversationColor.name]; - } -#ifdef DEBUG - NSSet *colorNameSet = [NSSet setWithArray:names]; - // These constants are duplicated in two places. So this canary exists to make sure they stay in sync. - NSSet *threadColorNameSet = [NSSet setWithArray:TSThread.conversationColorNames]; - OWSAssertDebug([colorNameSet isEqual:threadColorNameSet]); -#endif - return [names copy]; -} - -+ (nullable OWSConversationColor *)conversationColorForColorName:(ConversationColorName)conversationColorName -{ - OWSConversationColor *_Nullable result = self.conversationColorMap[conversationColorName]; - - // Any mapping to colorNames should be done in TSThread before this method is called. - OWSAssertDebug(result != nil); - - return result; -} - -+ (OWSConversationColor *)conversationColorOrDefaultForColorName:(ConversationColorName)conversationColorName -{ - OWSConversationColor *_Nullable conversationColor = [self conversationColorForColorName:conversationColorName]; - if (conversationColor) { - return conversationColor; - } - return [self defaultConversationColor]; -} - -+ (OWSConversationColor *)defaultConversationColor -{ - return [self conversationColorForColorName:ConversationColorNameDefault]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/contacts/OWSContactsManager.h b/SignalMessaging/contacts/OWSContactsManager.h index e5622d6028..5956931eae 100644 --- a/SignalMessaging/contacts/OWSContactsManager.h +++ b/SignalMessaging/contacts/OWSContactsManager.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2020 Open Whisper Systems. All rights reserved. +// Copyright (c) 2021 Open Whisper Systems. All rights reserved. // #import @@ -100,8 +100,6 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; transaction:(SDSAnyReadTransaction *)transaction; - (nullable UIImage *)imageForAddressWithSneakyTransaction:(nullable SignalServiceAddress *)address; -- (void)clearColorNameCache; - @end NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/contacts/OWSContactsManager.m b/SignalMessaging/contacts/OWSContactsManager.m index 629d42f864..beba10fc79 100644 --- a/SignalMessaging/contacts/OWSContactsManager.m +++ b/SignalMessaging/contacts/OWSContactsManager.m @@ -42,7 +42,6 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan @property (nonatomic, readonly) SystemContactsFetcher *systemContactsFetcher; @property (nonatomic, readonly) NSCache *cnContactCache; @property (nonatomic, readonly) NSCache *cnContactAvatarCache; -@property (nonatomic, readonly) NSCache *colorNameCache; @property (atomic) BOOL isSetup; @end @@ -62,7 +61,6 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan // TODO: We need to configure the limits of this cache. _avatarCachePrivate = [ImageCache new]; - _colorNameCache = [NSCache new]; _allContacts = @[]; _allContactsMap = @{}; @@ -901,26 +899,6 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan return addressLabel.filterStringForDisplay; } -- (void)clearColorNameCache -{ - [self.colorNameCache removeAllObjects]; -} - -- (ConversationColorName)conversationColorNameForAddress:(SignalServiceAddress *)address - transaction:(SDSAnyReadTransaction *)transaction -{ - _Nullable ConversationColorName cachedColorName = [self.colorNameCache objectForKey:address]; - if (cachedColorName != nil) { - return cachedColorName; - } - - ConversationColorName colorName = [TSContactThread conversationColorNameForContactAddress:address - transaction:transaction]; - [self.colorNameCache setObject:colorName forKey:address]; - - return colorName; -} - - (BOOL)phoneNumber:(PhoneNumber *)phoneNumber1 matchesNumber:(PhoneNumber *)phoneNumber2 { return [phoneNumber1.toE164 isEqualToString:phoneNumber2.toE164]; diff --git a/SignalMessaging/utils/ConversationStyle.swift b/SignalMessaging/utils/ConversationStyle.swift index 817f5e8bc7..3e9a6eceda 100644 --- a/SignalMessaging/utils/ConversationStyle.swift +++ b/SignalMessaging/utils/ConversationStyle.swift @@ -140,7 +140,6 @@ public class ConversationStyle: NSObject { chatColor chatColorValue: ChatColorValue) { self.type = type - self.conversationColor = ConversationStyle.conversationColor(thread: thread) self.viewWidth = viewWidth self.isDarkThemeEnabled = Theme.isDarkThemeEnabled self.primaryTextColor = Theme.primaryTextColor @@ -203,15 +202,6 @@ public class ConversationStyle: NSObject { // MARK: Colors - @objc - public let conversationColor: OWSConversationColor - - private class func conversationColor(thread: TSThread) -> OWSConversationColor { - let colorName = thread.conversationColorName - - return OWSConversationColor.conversationColorOrDefault(colorName: colorName) - } - @objc public var bubbleColorIncoming: UIColor { if hasWallpaper { @@ -367,7 +357,6 @@ public class ConversationStyle: NSObject { (type.isValid == other.type.isValid && viewWidth == other.viewWidth && dynamicBodyTypePointSize == other.dynamicBodyTypePointSize && - conversationColor == other.conversationColor && isDarkThemeEnabled == other.isDarkThemeEnabled && hasWallpaper == other.hasWallpaper && maxMessageWidth == other.maxMessageWidth && @@ -390,7 +379,6 @@ public class ConversationStyle: NSObject { "type.isValid: \(type.isValid), " + "viewWidth: \(viewWidth), " + "dynamicBodyTypePointSize: \(dynamicBodyTypePointSize), " + - "conversationColor: \(conversationColor), " + "isDarkThemeEnabled: \(isDarkThemeEnabled), " + "maxMessageWidth: \(maxMessageWidth), " + "maxMediaMessageWidth: \(maxMediaMessageWidth), " + diff --git a/SignalMessaging/utils/OWSAvatarBuilder.m b/SignalMessaging/utils/OWSAvatarBuilder.m index b90596afbd..26ac6b0eec 100644 --- a/SignalMessaging/utils/OWSAvatarBuilder.m +++ b/SignalMessaging/utils/OWSAvatarBuilder.m @@ -48,9 +48,9 @@ typedef void (^OWSAvatarDrawBlock)(CGContextRef context); OWSAvatarBuilder *avatarBuilder; if ([thread isKindOfClass:[TSContactThread class]]) { TSContactThread *contactThread = (TSContactThread *)thread; - ConversationColorName colorName = thread.conversationColorName; + UIColor *avatarColor = [ChatColors avatarColorForThread:thread]; avatarBuilder = [[OWSContactAvatarBuilder alloc] initWithAddress:contactThread.contactAddress - colorName:colorName + avatarColor:avatarColor diameter:diameter localUserDisplayMode:localUserDisplayMode transaction:transaction]; diff --git a/SignalMessaging/utils/OWSContactAvatarBuilder.h b/SignalMessaging/utils/OWSContactAvatarBuilder.h index 87b92c97f1..10d2e303dd 100644 --- a/SignalMessaging/utils/OWSContactAvatarBuilder.h +++ b/SignalMessaging/utils/OWSContactAvatarBuilder.h @@ -25,11 +25,11 @@ NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(buildImageForNonLocalAddress(_:diameter:transaction:)); - (instancetype)initWithAddress:(SignalServiceAddress *)address - colorName:(ConversationColorName)colorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter localUserDisplayMode:(LocalUserDisplayMode)localUserDisplayMode; - (instancetype)initWithAddress:(SignalServiceAddress *)address - colorName:(ConversationColorName)colorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter localUserDisplayMode:(LocalUserDisplayMode)localUserDisplayMode transaction:(SDSAnyReadTransaction *)transaction; diff --git a/SignalMessaging/utils/OWSContactAvatarBuilder.m b/SignalMessaging/utils/OWSContactAvatarBuilder.m index 1a5c894667..3897cef399 100644 --- a/SignalMessaging/utils/OWSContactAvatarBuilder.m +++ b/SignalMessaging/utils/OWSContactAvatarBuilder.m @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, nullable) SignalServiceAddress *address; @property (nonatomic, readonly, nullable) NSPersonNameComponents *contactNameComponents; -@property (nonatomic, readonly) ConversationColorName colorName; +@property (nonatomic, readonly) UIColor *avatarColor; @property (nonatomic, readonly) NSUInteger diameter; @property (nonatomic, readonly) LocalUserDisplayMode localUserDisplayMode; @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithAddress:(nullable SignalServiceAddress *)address nameComponents:(nullable NSPersonNameComponents *)nameComponents - colorName:(ConversationColorName)colorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter localUserDisplayMode:(LocalUserDisplayMode)localUserDisplayMode { @@ -38,11 +38,9 @@ NS_ASSUME_NONNULL_BEGIN return self; } - OWSAssertDebug(colorName.length > 0); - _address = address; _contactNameComponents = nameComponents; - _colorName = colorName; + _avatarColor = avatarColor; _diameter = diameter; _localUserDisplayMode = localUserDisplayMode; @@ -56,7 +54,7 @@ NS_ASSUME_NONNULL_BEGIN } - (instancetype)initWithAddress:(SignalServiceAddress *)address - colorName:(ConversationColorName)colorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter localUserDisplayMode:(LocalUserDisplayMode)localUserDisplayMode { @@ -67,7 +65,7 @@ NS_ASSUME_NONNULL_BEGIN }]; return [self initWithAddress:address nameComponents:nameComponents - colorName:colorName + avatarColor:avatarColor diameter:diameter localUserDisplayMode:localUserDisplayMode]; } @@ -80,14 +78,14 @@ NS_ASSUME_NONNULL_BEGIN } - (instancetype)initWithAddress:(SignalServiceAddress *)address - colorName:(ConversationColorName)colorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter localUserDisplayMode:(LocalUserDisplayMode)localUserDisplayMode transaction:(SDSAnyReadTransaction *)transaction { return [self initWithAddress:address nameComponents:[OWSContactAvatarBuilder nameComponentsForAddress:address transaction:transaction] - colorName:colorName + avatarColor:avatarColor diameter:diameter localUserDisplayMode:localUserDisplayMode]; } @@ -96,10 +94,10 @@ NS_ASSUME_NONNULL_BEGIN colorSeed:(NSString *)colorSeed diameter:(NSUInteger)diameter { - ConversationColorName colorName = [TSThread stableColorNameForNewConversationWithString:colorSeed]; + UIColor *avatarColor = [ChatColors avatarColorForSeed:colorSeed]; return [self initWithAddress:nil nameComponents:nonSignalNameComponents - colorName:colorName + avatarColor:avatarColor diameter:diameter localUserDisplayMode:OWSContactAvatarBuilder.defaultLocalUserDisplayMode]; } @@ -116,7 +114,7 @@ NS_ASSUME_NONNULL_BEGIN instance = [self initWithAddress:address nameComponents:[OWSContactAvatarBuilder nameComponentsForAddress:address transaction:transaction] - colorName:ConversationColorNameDefault + avatarColor:ChatColors.defaultAvatarColor diameter:diameter localUserDisplayMode:localUserDisplayMode]; }]; @@ -133,7 +131,7 @@ NS_ASSUME_NONNULL_BEGIN SignalServiceAddress *address = TSAccountManager.localAddress; return [self initWithAddress:address nameComponents:[OWSContactAvatarBuilder nameComponentsForAddress:address transaction:transaction] - colorName:ConversationColorNameDefault + avatarColor:ChatColors.defaultAvatarColor diameter:diameter localUserDisplayMode:localUserDisplayMode]; } @@ -142,12 +140,11 @@ NS_ASSUME_NONNULL_BEGIN diameter:(NSUInteger)diameter transaction:(SDSAnyReadTransaction *)transaction { - ConversationColorName color = [self.contactsManager conversationColorNameForAddress:address - transaction:transaction]; + UIColor *avatarColor = [ChatColors avatarColorForAddress:address transaction:transaction]; OWSContactAvatarBuilder *avatarBuilder = [[self alloc] initWithAddress:address nameComponents:[OWSContactAvatarBuilder nameComponentsForAddress:address transaction:transaction] - colorName:color + avatarColor:avatarColor diameter:diameter localUserDisplayMode:OWSContactAvatarBuilder.defaultLocalUserDisplayMode]; return [avatarBuilder buildWithTransaction:transaction]; @@ -195,7 +192,7 @@ NS_ASSUME_NONNULL_BEGIN return cachedAvatar; } - UIImage *image = [self noteToSelfImageWithConversationColorName:self.colorName diameter:(CGFloat)self.diameter]; + UIImage *image = [self noteToSelfImageWithDiameter:(CGFloat)self.diameter]; if (!image) { OWSFailDebug(@"Could not generate avatar."); return nil; @@ -251,9 +248,7 @@ NS_ASSUME_NONNULL_BEGIN return cachedAvatar; } - UIColor *color = [OWSConversationColor conversationColorOrDefaultForColorName:self.colorName].themeColor; - OWSAssertDebug(color); - + UIColor *color = self.avatarColor; UIImage *_Nullable image; if (self.contactInitials.length == 0) { // We don't have a name for this contact, so we can't make an "initials" image. @@ -292,11 +287,10 @@ NS_ASSUME_NONNULL_BEGIN return image; } -- (nullable UIImage *)noteToSelfImageWithConversationColorName:(ConversationColorName)conversationColorName - diameter:(CGFloat)diameter +- (nullable UIImage *)noteToSelfImageWithDiameter:(CGFloat)diameter { UIImage *iconImage = [[UIImage imageNamed:@"note-112"] asTintedImageWithColor:UIColor.whiteColor]; - UIColor *backgroundColor = [OWSConversationColor conversationColorOrDefaultForColorName:conversationColorName].themeColor; + UIColor *backgroundColor = self.avatarColor; CGFloat circleWidth = diameter; UIGraphicsBeginImageContextWithOptions(CGSizeMake(circleWidth, circleWidth), NO, 0.0); diff --git a/SignalMessaging/utils/OWSGroupAvatarBuilder.h b/SignalMessaging/utils/OWSGroupAvatarBuilder.h index 2662310e0d..2bc1716f6c 100644 --- a/SignalMessaging/utils/OWSGroupAvatarBuilder.h +++ b/SignalMessaging/utils/OWSGroupAvatarBuilder.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2021 Open Whisper Systems. All rights reserved. // #import "OWSAvatarBuilder.h" @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithThread:(TSGroupThread *)thread diameter:(NSUInteger)diameter; + (nullable UIImage *)defaultAvatarForGroupId:(NSData *)groupId - conversationColorName:(NSString *)conversationColorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter; @end diff --git a/SignalMessaging/utils/OWSGroupAvatarBuilder.m b/SignalMessaging/utils/OWSGroupAvatarBuilder.m index 3c8d0eeff7..011844bc58 100644 --- a/SignalMessaging/utils/OWSGroupAvatarBuilder.m +++ b/SignalMessaging/utils/OWSGroupAvatarBuilder.m @@ -47,13 +47,14 @@ NS_ASSUME_NONNULL_BEGIN - (nullable UIImage *)buildDefaultImage { + UIColor *avatarColor = [ChatColors avatarColorForThread:self.thread]; return [self.class defaultAvatarForGroupId:self.thread.groupModel.groupId - conversationColorName:self.thread.conversationColorName + avatarColor:avatarColor diameter:self.diameter]; } + (nullable UIImage *)defaultAvatarForGroupId:(NSData *)groupId - conversationColorName:(NSString *)conversationColorName + avatarColor:(UIColor *)avatarColor diameter:(NSUInteger)diameter { NSString *cacheKey = [NSString @@ -65,14 +66,8 @@ NS_ASSUME_NONNULL_BEGIN return cachedAvatar; } -#ifdef SHOW_COLOR_PICKER - UIColor *backgroundColor = - [OWSConversationColor conversationColorOrDefaultForColorName:conversationColorName].themeColor; -#else - UIColor *backgroundColor = [OWSConversationColor ows_steelColor]; -#endif - UIImage *_Nullable image = - [OWSGroupAvatarBuilder groupAvatarImageWithBackgroundColor:backgroundColor diameter:diameter]; + UIImage *_Nullable image = [OWSGroupAvatarBuilder groupAvatarImageWithBackgroundColor:avatarColor + diameter:diameter]; if (!image) { OWSFailDebug(@"Could not create group avatar."); return nil; diff --git a/SignalServiceKit/src/Contacts/TSThread.h b/SignalServiceKit/src/Contacts/TSThread.h index ea83e1aa18..d2e1c41995 100644 --- a/SignalServiceKit/src/Contacts/TSThread.h +++ b/SignalServiceKit/src/Contacts/TSThread.h @@ -96,6 +96,7 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:conversationColorNa // --- CODE GENERATION MARKER +// TODO: Obsolete. @property (nonatomic) ConversationColorName conversationColorName; - (void)updateConversationColorName:(ConversationColorName)colorName transaction:(SDSAnyWriteTransaction *)transaction; diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h index 2b98ad9ee8..a9fde0ad2f 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h @@ -80,10 +80,6 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:conversationColorNa // This method should only be called by GroupManager. - (void)updateWithGroupModel:(TSGroupModel *)groupModel transaction:(SDSAnyWriteTransaction *)transaction; -#pragma mark - - -+ (ConversationColorName)defaultConversationColorNameForGroupId:(NSData *)groupId; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m index 2c5ae887ce..d49588ab37 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m @@ -187,14 +187,6 @@ lastVisibleSortIdOnScreenPercentageObsolete:lastVisibleSortIdOnScreenPercentageO userInfo:userInfo]; } -+ (ConversationColorName)defaultConversationColorNameForGroupId:(NSData *)groupId -{ - OWSAssertDebug(groupId.length > 0); - - NSString *threadUniqueId = [self defaultThreadIdForGroupId:groupId]; - return [self.class stableColorNameForNewConversationWithString:threadUniqueId]; -} - - (void)anyWillRemoveWithTransaction:(SDSAnyWriteTransaction *)transaction { if (self.isGroupV2Thread) { diff --git a/SignalServiceKit/src/Protocols/ContactsManagerProtocol.h b/SignalServiceKit/src/Protocols/ContactsManagerProtocol.h index 97dae778d6..20c71e1c9e 100644 --- a/SignalServiceKit/src/Protocols/ContactsManagerProtocol.h +++ b/SignalServiceKit/src/Protocols/ContactsManagerProtocol.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2020 Open Whisper Systems. All rights reserved. +// Copyright (c) 2021 Open Whisper Systems. All rights reserved. // NS_ASSUME_NONNULL_BEGIN @@ -14,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN @class TSThread; @class UIImage; -typedef NSString *ConversationColorName NS_STRING_ENUM; - @protocol ContactsManagerProtocol /// The name representing this address. @@ -43,9 +41,6 @@ typedef NSString *ConversationColorName NS_STRING_ENUM; - (NSString *)shortDisplayNameForAddress:(SignalServiceAddress *)address transaction:(SDSAnyReadTransaction *)transaction; -- (ConversationColorName)conversationColorNameForAddress:(SignalServiceAddress *)address - transaction:(SDSAnyReadTransaction *)transaction; - - (nullable NSPersonNameComponents *)nameComponentsForAddress:(SignalServiceAddress *)address; - (nullable NSPersonNameComponents *)nameComponentsForAddress:(SignalServiceAddress *)address transaction:(SDSAnyReadTransaction *)transaction; diff --git a/SignalServiceKit/src/Util/FeatureFlags.swift b/SignalServiceKit/src/Util/FeatureFlags.swift index f806a89a46..4552bfcb45 100644 --- a/SignalServiceKit/src/Util/FeatureFlags.swift +++ b/SignalServiceKit/src/Util/FeatureFlags.swift @@ -424,10 +424,6 @@ public class DebugFlags: BaseFlags { @objc public static let fakeLinkedDevices = false - // TODO: Remove - @objc - public static let shouldShowColorPicker = false - @objc public static let paymentsOnlyInContactThreads = true