mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Sketch out TypingIndicatorCell.
This commit is contained in:
parent
eedc9f9a26
commit
63d88ef5cb
|
@ -53,6 +53,8 @@ typedef NS_OPTIONS(NSUInteger, OWSDirectionalRectCorner) {
|
||||||
|
|
||||||
- (CGFloat)minWidth;
|
- (CGFloat)minWidth;
|
||||||
|
|
||||||
|
- (CGFloat)minHeight;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -273,6 +273,11 @@ const CGFloat kOWSMessageCellCornerRadius_Small = 4;
|
||||||
return (kOWSMessageCellCornerRadius_Large * 2);
|
return (kOWSMessageCellCornerRadius_Large * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CGFloat)minHeight
|
||||||
|
{
|
||||||
|
return (kOWSMessageCellCornerRadius_Large * 2);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -10,28 +10,146 @@ public class TypingIndicatorCell: ConversationViewCell {
|
||||||
@objc
|
@objc
|
||||||
public static let cellReuseIdentifier = "TypingIndicatorCell"
|
public static let cellReuseIdentifier = "TypingIndicatorCell"
|
||||||
|
|
||||||
@available(*, unavailable, message:"use other constructor instead.")
|
@available(*, unavailable, message:"use other constructor instead.")
|
||||||
@objc
|
@objc
|
||||||
public required init(coder aDecoder: NSCoder) {
|
public required init(coder aDecoder: NSCoder) {
|
||||||
notImplemented()
|
notImplemented()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let kAvatarSize: CGFloat = 36
|
||||||
|
private let kAvatarHSpacing: CGFloat = 8
|
||||||
|
|
||||||
|
private let avatarView = AvatarImageView()
|
||||||
|
private let bubbleView = OWSBubbleView()
|
||||||
|
private let typingIndicatorView = TypingIndicatorView()
|
||||||
|
private var viewConstraints = [NSLayoutConstraint]()
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
commonInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func commonInit() {
|
||||||
|
self.layoutMargins = .zero
|
||||||
|
self.contentView.layoutMargins = .zero
|
||||||
|
|
||||||
|
bubbleView.layoutMargins = .zero
|
||||||
|
|
||||||
|
bubbleView.addSubview(typingIndicatorView)
|
||||||
|
contentView.addSubview(bubbleView)
|
||||||
|
|
||||||
|
avatarView.autoSetDimension(.width, toSize: kAvatarSize)
|
||||||
|
avatarView.autoSetDimension(.height, toSize: kAvatarSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public override func loadForDisplay() {
|
public override func loadForDisplay() {
|
||||||
|
guard let conversationStyle = self.conversationStyle else {
|
||||||
|
owsFailDebug("Missing conversationStyle")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bubbleView.bubbleColor = conversationStyle.bubbleColor(isIncoming: true)
|
||||||
|
typingIndicatorView.startAnimation()
|
||||||
|
typingIndicatorView.addBackgroundView(withBackgroundColor: UIColor.red)
|
||||||
|
|
||||||
|
viewConstraints.append(contentsOf: [
|
||||||
|
bubbleView.autoPinEdge(toSuperviewEdge: .leading, withInset: conversationStyle.gutterLeading),
|
||||||
|
bubbleView.autoPinEdge(toSuperviewEdge: .trailing, withInset: conversationStyle.gutterTrailing, relation: .greaterThanOrEqual),
|
||||||
|
bubbleView.autoPinTopToSuperviewMargin(withInset: 0),
|
||||||
|
bubbleView.autoPinBottomToSuperviewMargin(withInset: 0),
|
||||||
|
|
||||||
|
typingIndicatorView.autoPinEdge(toSuperviewEdge: .leading, withInset: conversationStyle.textInsetHorizontal),
|
||||||
|
typingIndicatorView.autoPinEdge(toSuperviewEdge: .trailing, withInset: conversationStyle.textInsetHorizontal),
|
||||||
|
typingIndicatorView.autoPinTopToSuperviewMargin(withInset: conversationStyle.textInsetTop),
|
||||||
|
typingIndicatorView.autoPinBottomToSuperviewMargin(withInset: conversationStyle.textInsetBottom)
|
||||||
|
])
|
||||||
|
|
||||||
|
if let avatarView = configureAvatarView() {
|
||||||
|
contentView.addSubview(avatarView)
|
||||||
|
viewConstraints.append(contentsOf: [
|
||||||
|
bubbleView.autoPinLeading(toTrailingEdgeOf: avatarView, offset: kAvatarHSpacing),
|
||||||
|
bubbleView.autoAlignAxis(.horizontal, toSameAxisOf: avatarView)
|
||||||
|
])
|
||||||
|
|
||||||
|
} else {
|
||||||
|
avatarView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func configureAvatarView() -> UIView? {
|
||||||
|
guard let viewItem = self.viewItem else {
|
||||||
|
owsFailDebug("Missing viewItem")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard let typingIndicators = viewItem.interaction as? TypingIndicatorInteraction else {
|
||||||
|
owsFailDebug("Missing typingIndicators")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard shouldShowAvatar() else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard let colorName = viewItem.authorConversationColorName else {
|
||||||
|
owsFailDebug("Missing authorConversationColorName")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard let authorAvatarImage =
|
||||||
|
OWSContactAvatarBuilder(signalId: typingIndicators.recipientId,
|
||||||
|
colorName: ConversationColorNameForString(colorName),
|
||||||
|
diameter: UInt(kAvatarSize)).build() else {
|
||||||
|
owsFailDebug("Could build avatar image")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
avatarView.image = authorAvatarImage
|
||||||
|
return avatarView
|
||||||
|
}
|
||||||
|
|
||||||
|
private func shouldShowAvatar() -> Bool {
|
||||||
|
guard let viewItem = self.viewItem else {
|
||||||
|
owsFailDebug("Missing viewItem")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return viewItem.isGroupThread
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public override func cellSize() -> CGSize {
|
public override func cellSize() -> CGSize {
|
||||||
return .zero
|
guard let conversationStyle = self.conversationStyle else {
|
||||||
|
owsFailDebug("Missing conversationStyle")
|
||||||
|
return .zero
|
||||||
|
}
|
||||||
|
|
||||||
|
let insetsSize = CGSize(width: conversationStyle.textInsetHorizontal * 2,
|
||||||
|
height: conversationStyle.textInsetTop + conversationStyle.textInsetBottom)
|
||||||
|
let typingIndicatorSize = typingIndicatorView.sizeThatFits(.zero)
|
||||||
|
let bubbleSize = CGSizeAdd(insetsSize, typingIndicatorSize)
|
||||||
|
|
||||||
|
if shouldShowAvatar() {
|
||||||
|
let avatarSize = CGSize(width: kAvatarSize, height: kAvatarSize)
|
||||||
|
return CGSizeCeil(CGSize(width: avatarSize.width + kAvatarHSpacing + bubbleSize.width,
|
||||||
|
height: max(avatarSize.height, bubbleSize.height)))
|
||||||
|
} else {
|
||||||
|
return bubbleSize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public override func prepareForReuse() {
|
public override func prepareForReuse() {
|
||||||
super.prepareForReuse()
|
super.prepareForReuse()
|
||||||
|
|
||||||
|
NSLayoutConstraint.deactivate(viewConstraints)
|
||||||
|
viewConstraints = [NSLayoutConstraint]()
|
||||||
|
|
||||||
|
avatarView.image = nil
|
||||||
|
avatarView.removeFromSuperview()
|
||||||
|
|
||||||
|
typingIndicatorView.stopAnimation()
|
||||||
|
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,14 +143,24 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||||
{
|
{
|
||||||
OWSAssertDebug(transaction);
|
OWSAssertDebug(transaction);
|
||||||
|
|
||||||
if (self.interaction.interactionType != OWSInteractionType_IncomingMessage) {
|
switch (self.interaction.interactionType) {
|
||||||
_authorConversationColorName = nil;
|
case OWSInteractionType_TypingIndicator: {
|
||||||
return;
|
OWSTypingIndicatorInteraction *typingIndicator = (OWSTypingIndicatorInteraction *)self.interaction;
|
||||||
|
_authorConversationColorName =
|
||||||
|
[TSContactThread conversationColorNameForRecipientId:typingIndicator.recipientId
|
||||||
|
transaction:transaction];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OWSInteractionType_IncomingMessage: {
|
||||||
|
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)self.interaction;
|
||||||
|
_authorConversationColorName =
|
||||||
|
[TSContactThread conversationColorNameForRecipientId:incomingMessage.authorId transaction:transaction];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
_authorConversationColorName = nil;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)self.interaction;
|
|
||||||
_authorConversationColorName =
|
|
||||||
[TSContactThread conversationColorNameForRecipientId:incomingMessage.authorId transaction:transaction];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)itemId
|
- (NSString *)itemId
|
||||||
|
|
|
@ -16,12 +16,6 @@
|
||||||
private let dot2 = DotView(dotType: .dotType2)
|
private let dot2 = DotView(dotType: .dotType2)
|
||||||
private let dot3 = DotView(dotType: .dotType3)
|
private let dot3 = DotView(dotType: .dotType3)
|
||||||
|
|
||||||
override public var isHidden: Bool {
|
|
||||||
didSet {
|
|
||||||
Logger.verbose("\(oldValue) -> \(isHidden)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(*, unavailable, message:"use other constructor instead.")
|
@available(*, unavailable, message:"use other constructor instead.")
|
||||||
required init(coder aDecoder: NSCoder) {
|
required init(coder aDecoder: NSCoder) {
|
||||||
notImplemented()
|
notImplemented()
|
||||||
|
@ -46,6 +40,11 @@
|
||||||
self.alignment = .center
|
self.alignment = .center
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||||
|
return CGSize(width: TypingIndicatorView.kMaxRadiusPt * 3 + kDotMaxHSpacing * 2, height: TypingIndicatorView.kMaxRadiusPt)
|
||||||
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public func startAnimation() {
|
public func startAnimation() {
|
||||||
}
|
}
|
||||||
|
@ -86,9 +85,6 @@
|
||||||
self.layer.addSublayer(shapeLayer)
|
self.layer.addSublayer(shapeLayer)
|
||||||
|
|
||||||
updateLayer()
|
updateLayer()
|
||||||
// self.text = text
|
|
||||||
//
|
|
||||||
// setupSubviews()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateLayer() {
|
private func updateLayer() {
|
||||||
|
|
|
@ -193,6 +193,11 @@ CG_INLINE CGSize CGSizeScale(CGSize size, CGFloat factor)
|
||||||
return CGSizeMake(size.width * factor, size.height * factor);
|
return CGSizeMake(size.width * factor, size.height * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CG_INLINE CGSize CGSizeAdd(CGSize left, CGSize right)
|
||||||
|
{
|
||||||
|
return CGSizeMake(left.width + right.width, left.height + right.height);
|
||||||
|
}
|
||||||
|
|
||||||
CGFloat CGHairlineWidth(void);
|
CGFloat CGHairlineWidth(void);
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -11,6 +11,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
@class TSInvalidIdentityKeyReceivingErrorMessage;
|
@class TSInvalidIdentityKeyReceivingErrorMessage;
|
||||||
|
|
||||||
typedef NSString *ConversationColorName NS_STRING_ENUM;
|
typedef NSString *ConversationColorName NS_STRING_ENUM;
|
||||||
|
|
||||||
|
ConversationColorName ConversationColorNameForString(NSString *value);
|
||||||
|
|
||||||
extern ConversationColorName const ConversationColorNameCrimson;
|
extern ConversationColorName const ConversationColorNameCrimson;
|
||||||
extern ConversationColorName const ConversationColorNameVermilion;
|
extern ConversationColorName const ConversationColorNameVermilion;
|
||||||
extern ConversationColorName const ConversationColorNameBurlap;
|
extern ConversationColorName const ConversationColorNameBurlap;
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
ConversationColorName ConversationColorNameForString(NSString *value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
ConversationColorName const ConversationColorNameCrimson = @"red";
|
ConversationColorName const ConversationColorNameCrimson = @"red";
|
||||||
ConversationColorName const ConversationColorNameVermilion = @"orange";
|
ConversationColorName const ConversationColorNameVermilion = @"orange";
|
||||||
ConversationColorName const ConversationColorNameBurlap = @"brown";
|
ConversationColorName const ConversationColorNameBurlap = @"brown";
|
||||||
|
|
Loading…
Reference in a new issue