Implement conversation screen subtitle

This commit is contained in:
nielsandriesse 2021-02-15 16:50:48 +11:00
parent f12d18f90e
commit ac41400ede
5 changed files with 122 additions and 17 deletions

View File

@ -563,6 +563,7 @@
C3645350252449260045C478 /* VoiceMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C364534F252449260045C478 /* VoiceMessageView.swift */; };
C364535C252467900045C478 /* AudioUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C364535B252467900045C478 /* AudioUtilities.swift */; };
C374EEE225DA26740073A857 /* LinkPreviewModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = C374EEE125DA26740073A857 /* LinkPreviewModal.swift */; };
C374EEEB25DA3CA70073A857 /* ConversationTitleViewV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = C374EEEA25DA3CA70073A857 /* ConversationTitleViewV2.swift */; };
C379DCF4256735770002D4EB /* VisibleMessage+Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C379DCF3256735770002D4EB /* VisibleMessage+Attachment.swift */; };
C37F5385255B94F6002AEA92 /* SelectRecipientViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF34E255B6DC8007E1867 /* SelectRecipientViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
C37F5396255B95BD002AEA92 /* OWSAnyTouchGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF302255B6DBE007E1867 /* OWSAnyTouchGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -1606,6 +1607,7 @@
C364534F252449260045C478 /* VoiceMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageView.swift; sourceTree = "<group>"; };
C364535B252467900045C478 /* AudioUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioUtilities.swift; sourceTree = "<group>"; };
C374EEE125DA26740073A857 /* LinkPreviewModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewModal.swift; sourceTree = "<group>"; };
C374EEEA25DA3CA70073A857 /* ConversationTitleViewV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleViewV2.swift; sourceTree = "<group>"; };
C379DCF3256735770002D4EB /* VisibleMessage+Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibleMessage+Attachment.swift"; sourceTree = "<group>"; };
C379DCFD25673DBC0002D4EB /* TSAttachmentPointer+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSAttachmentPointer+Conversion.swift"; sourceTree = "<group>"; };
C37F53E8255BA9BB002AEA92 /* Environment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = "<group>"; };
@ -2251,6 +2253,7 @@
C374EEE125DA26740073A857 /* LinkPreviewModal.swift */,
B82149C025D605C6009C0F2A /* InfoBanner.swift */,
B8214A2A25D63EB9009C0F2A /* MessagesTableView.swift */,
C374EEEA25DA3CA70073A857 /* ConversationTitleViewV2.swift */,
);
path = "Views & Modals";
sourceTree = "<group>";
@ -5056,6 +5059,7 @@
B8214A2B25D63EB9009C0F2A /* MessagesTableView.swift in Sources */,
B835246E25C38ABF0089A44F /* ConversationVC.swift in Sources */,
B821494625D4D6FF009C0F2A /* URLModal.swift in Sources */,
C374EEEB25DA3CA70073A857 /* ConversationTitleViewV2.swift in Sources */,
4CA485BB2232339F004B9E7D /* PhotoCaptureViewController.swift in Sources */,
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */,
344825C6211390C800DB4BD8 /* OWSOrphanDataCleaner.m in Sources */,

View File

@ -3,7 +3,6 @@
// Tapping replies
// Mentions
// Remaining send logic
// Subtitle
// Slight paging glitch
// Scrolling bug
// Scroll button bug
@ -47,6 +46,8 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
}()
// MARK: UI Components
private lazy var titleView = ConversationTitleViewV2(thread: thread)
lazy var messagesTableView: MessagesTableView = {
let result = MessagesTableView()
result.dataSource = self
@ -98,7 +99,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
setUpGradientBackground()
// Nav bar
setUpNavBarStyle()
setNavBarTitle(getTitle())
navigationItem.titleView = titleView
updateNavBarButtons()
// Constraints
view.addSubview(messagesTableView)
@ -390,21 +391,6 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
}
// MARK: Convenience
private func getTitle() -> String {
if let thread = thread as? TSGroupThread {
return thread.groupModel.groupName!
} else if thread.isNoteToSelf() {
return "Note to Self"
} else {
let sessionID = thread.contactIdentifier()!
var result = sessionID
Storage.read { transaction in
result = Storage.shared.getContact(with: sessionID)?.displayName ?? "Anonymous"
}
return result
}
}
private func getScrollButtonOpacity() -> CGFloat {
let contentOffsetY = messagesTableView.contentOffset.y
let x = (lastPageTop - ConversationVC.bottomInset - contentOffsetY).clamp(0, .greatestFiniteMagnitude)

View File

@ -0,0 +1,109 @@
final class ConversationTitleViewV2 : UIView {
private let thread: TSThread
override var intrinsicContentSize: CGSize {
return UIView.layoutFittingExpandedSize
}
// MARK: UI Components
private lazy var titleLabel: UILabel = {
let result = UILabel()
result.textColor = Colors.text
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.lineBreakMode = .byTruncatingTail
return result
}()
private lazy var subtitleLabel: UILabel = {
let result = UILabel()
result.textColor = Colors.text
result.font = .systemFont(ofSize: 13)
result.lineBreakMode = .byTruncatingTail
return result
}()
// MARK: Lifecycle
init(thread: TSThread) {
self.thread = thread
super.init(frame: CGRect.zero)
initialize()
}
override init(frame: CGRect) {
preconditionFailure("Use init(thread:) instead.")
}
required init?(coder: NSCoder) {
preconditionFailure("Use init(coder:) instead.")
}
private func initialize() {
let stackView = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
stackView.axis = .vertical
stackView.alignment = .center
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
addSubview(stackView)
stackView.pin(to: self)
NotificationCenter.default.addObserver(self, selector: #selector(update), name: Notification.Name.groupThreadUpdated, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(update), name: Notification.Name.muteSettingUpdated, object: nil)
update()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: Updating
@objc private func update() {
titleLabel.text = getTitle()
let subtitle = getSubtitle()
subtitleLabel.attributedText = subtitle
let titleFontSize = (subtitle != nil) ? Values.mediumFontSize : Values.veryLargeFontSize
titleLabel.font = .boldSystemFont(ofSize: titleFontSize)
}
// MARK: General
private func getTitle() -> String {
if let thread = thread as? TSGroupThread {
return thread.groupModel.groupName!
} else if thread.isNoteToSelf() {
return "Note to Self"
} else {
let sessionID = thread.contactIdentifier()!
var result = sessionID
Storage.read { transaction in
result = Storage.shared.getContact(with: sessionID)?.displayName ?? "Anonymous"
}
return result
}
}
private func getSubtitle() -> NSAttributedString? {
if let muteEndDate = thread.mutedUntilDate, thread.isMuted {
let result = NSMutableAttributedString()
result.append(NSAttributedString(string: "\u{e067} ", attributes: [ .font : UIFont.ows_elegantIconsFont(10), .foregroundColor : Colors.text ]))
let formatter = DateFormatter()
formatter.locale = Locale.current
formatter.timeStyle = .medium
formatter.dateStyle = .medium
result.append(NSAttributedString(string: "Muted until " + formatter.string(from: muteEndDate)))
return result
} else if let thread = self.thread as? TSGroupThread {
var userCount: Int?
switch thread.groupModel.groupType {
case .closedGroup: userCount = thread.groupModel.groupMemberIds.count
case .openGroup:
if let openGroup = Storage.shared.getOpenGroup(for: self.thread.uniqueId!) {
userCount = Storage.shared.getUserCount(forOpenGroupWithID: openGroup.id)
}
default: break
}
if let userCount = userCount {
return NSAttributedString(string: "\(userCount) members")
}
}
return nil
}
}

View File

@ -2,9 +2,11 @@
public extension Notification.Name {
static let groupThreadUpdated = Notification.Name("groupThreadUpdated")
static let muteSettingUpdated = Notification.Name("muteSettingUpdated")
}
@objc public extension NSNotification {
@objc static let groupThreadUpdated = Notification.Name.groupThreadUpdated.rawValue as NSString
@objc static let muteSettingUpdated = Notification.Name.muteSettingUpdated.rawValue as NSString
}

View File

@ -451,6 +451,10 @@ BOOL IsNoteToSelfEnabled(void)
changeBlock:^(TSThread *thread) {
[thread setMutedUntilDate:mutedUntilDate];
}];
[transaction addCompletionQueue:dispatch_get_main_queue() completionBlock:^{
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.muteSettingUpdated object:self.uniqueId];
}];
}
@end