Add typing indicators in home view.
This commit is contained in:
parent
b063a49d56
commit
50381cc94c
|
@ -216,6 +216,7 @@
|
|||
34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */; };
|
||||
34B3F8851E8DF1700035BE1A /* NewGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */; };
|
||||
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */; };
|
||||
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B6A902218B3F62007C4606 /* TypingIndicatorView.swift */; };
|
||||
34B6D27420F664C900765BE2 /* OWSUnreadIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 34B6D27220F664C800765BE2 /* OWSUnreadIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34B6D27520F664C900765BE2 /* OWSUnreadIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B6D27320F664C800765BE2 /* OWSUnreadIndicator.m */; };
|
||||
34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BECE2A1F74C12700D7438D /* DebugUIStress.m */; };
|
||||
|
@ -866,6 +867,7 @@
|
|||
34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewGroupViewController.m; sourceTree = "<group>"; };
|
||||
34B3F86D1E8DF1700035BE1A /* SignalsNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsNavigationController.h; sourceTree = "<group>"; };
|
||||
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = "<group>"; };
|
||||
34B6A902218B3F62007C4606 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = "<group>"; };
|
||||
34B6D27220F664C800765BE2 /* OWSUnreadIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSUnreadIndicator.h; sourceTree = "<group>"; };
|
||||
34B6D27320F664C800765BE2 /* OWSUnreadIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSUnreadIndicator.m; sourceTree = "<group>"; };
|
||||
34BECE291F74C12700D7438D /* DebugUIStress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIStress.h; sourceTree = "<group>"; };
|
||||
|
@ -2215,10 +2217,11 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
452EA09D1EA7ABE00078744B /* AttachmentPointerView.swift */,
|
||||
4C2F454E214C00E1004871FF /* AvatarTableViewCell.swift */,
|
||||
34E3E5671EC4B19400495BAC /* AudioProgressView.swift */,
|
||||
4C2F454E214C00E1004871FF /* AvatarTableViewCell.swift */,
|
||||
451764291DE939FD00EDB8B9 /* ContactCell.swift */,
|
||||
4523149F1F7E9E18003A428C /* DirectionalPanGestureRecognizer.swift */,
|
||||
4C4AEC4420EC343B0020E72B /* DismissableTextField.swift */,
|
||||
45A663C41F92EC760027B59E /* GroupTableViewCell.swift */,
|
||||
45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */,
|
||||
34386A53207D271C009F5D9C /* NeverClearView.swift */,
|
||||
|
@ -2234,8 +2237,8 @@
|
|||
45A6DAD51EBBF85500893231 /* ReminderView.swift */,
|
||||
450D19111F85236600970622 /* RemoteVideoView.h */,
|
||||
450D19121F85236600970622 /* RemoteVideoView.m */,
|
||||
4C4AEC4420EC343B0020E72B /* DismissableTextField.swift */,
|
||||
4CA5F792211E1F06008C2708 /* Toast.swift */,
|
||||
34B6A902218B3F62007C4606 /* TypingIndicatorView.swift */,
|
||||
);
|
||||
name = Views;
|
||||
path = views;
|
||||
|
@ -3382,6 +3385,7 @@
|
|||
457C87B82032645C008D52D6 /* DebugUINotifications.swift in Sources */,
|
||||
4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */,
|
||||
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */,
|
||||
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */,
|
||||
340FC8D0205BF2FA007AEB0F /* OWSBackupIO.m in Sources */,
|
||||
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
|
||||
4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */,
|
||||
|
|
|
@ -22,6 +22,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic) UILabel *snippetLabel;
|
||||
@property (nonatomic) UILabel *dateTimeLabel;
|
||||
@property (nonatomic) MessageStatusView *messageStatusView;
|
||||
@property (nonatomic) TypingIndicatorView *typingIndicatorView;
|
||||
@property (nonatomic) UIStackView *previewStackView;
|
||||
|
||||
@property (nonatomic) UIView *unreadBadge;
|
||||
@property (nonatomic) UILabel *unreadLabel;
|
||||
|
@ -45,6 +47,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return Environment.shared.contactsManager;
|
||||
}
|
||||
|
||||
- (id<OWSTypingIndicators>)typingIndicators
|
||||
{
|
||||
return SSKEnvironment.shared.typingIndicators;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
|
||||
|
@ -111,15 +118,25 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
self.snippetLabel.font = [self snippetFont];
|
||||
self.snippetLabel.numberOfLines = 1;
|
||||
self.snippetLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
[self.snippetLabel setContentHuggingHorizontalLow];
|
||||
[self.snippetLabel setCompressionResistanceHorizontalLow];
|
||||
|
||||
self.typingIndicatorView = [TypingIndicatorView new];
|
||||
|
||||
self.previewStackView = [[UIStackView alloc] initWithArrangedSubviews:@[
|
||||
self.snippetLabel,
|
||||
self.typingIndicatorView,
|
||||
]];
|
||||
self.previewStackView.axis = UILayoutConstraintAxisVertical;
|
||||
self.previewStackView.alignment = UIStackViewAlignmentLeading;
|
||||
[self.previewStackView setContentHuggingHorizontalLow];
|
||||
[self.previewStackView setCompressionResistanceHorizontalLow];
|
||||
|
||||
UIStackView *bottomRowView = [[UIStackView alloc] initWithArrangedSubviews:@[
|
||||
self.snippetLabel,
|
||||
self.previewStackView,
|
||||
self.messageStatusView,
|
||||
]];
|
||||
|
||||
bottomRowView.axis = UILayoutConstraintAxisHorizontal;
|
||||
bottomRowView.alignment = UIStackViewAlignmentLastBaseline;
|
||||
bottomRowView.alignment = UIStackViewAlignmentCenter;
|
||||
bottomRowView.spacing = 6.f;
|
||||
|
||||
UIStackView *vStackView = [[UIStackView alloc] initWithArrangedSubviews:@[
|
||||
|
@ -203,6 +220,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
selector:@selector(otherUsersProfileDidChange:)
|
||||
name:kNSNotificationName_OtherUsersProfileDidChange
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(typingIndicatorStateDidChange:)
|
||||
name:[OWSTypingIndicatorsImpl typingIndicatorStateDidChange]
|
||||
object:nil];
|
||||
[self updateNameLabel];
|
||||
[self updateAvatarView];
|
||||
|
||||
|
@ -215,7 +236,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
} else {
|
||||
self.snippetLabel.attributedText = [self attributedSnippetForThread:thread isBlocked:isBlocked];
|
||||
}
|
||||
|
||||
[self updatePreview];
|
||||
CGFloat previewHeight = MAX(self.snippetLabel.font.lineHeight,
|
||||
TypingIndicatorView.kMaxRadiusPt);
|
||||
[self.viewConstraints addObjectsFromArray:@[
|
||||
[self.previewStackView autoSetDimension:ALDimensionHeight
|
||||
toSize:previewHeight],
|
||||
]];
|
||||
self.dateTimeLabel.text
|
||||
= (overrideDate ? [self stringForDate:overrideDate] : [self stringForDate:thread.lastMessageDate]);
|
||||
|
||||
|
@ -500,6 +527,28 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
self.nameLabel.attributedText = name;
|
||||
}
|
||||
|
||||
#pragma mark - Typing Indicators
|
||||
|
||||
- (void)updatePreview
|
||||
{
|
||||
if ([self.typingIndicators typingIndicatorsForThread:self.thread.threadRecord] != nil) {
|
||||
self.snippetLabel.hidden = YES;
|
||||
self.typingIndicatorView.hidden = NO;
|
||||
[self.typingIndicatorView startAnimation];
|
||||
} else {
|
||||
self.snippetLabel.hidden = NO;
|
||||
self.typingIndicatorView.hidden = YES;
|
||||
[self.typingIndicatorView stopAnimation];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)typingIndicatorStateDidChange:(NSNotification *)notification
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
[self updatePreview];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
@objc class TypingIndicatorView: UIStackView {
|
||||
private let kDotMaxHSpacing: CGFloat = 8
|
||||
|
||||
@objc
|
||||
public static let kMinRadiusPt: CGFloat = 6
|
||||
@objc
|
||||
public static let kMaxRadiusPt: CGFloat = 8
|
||||
|
||||
private let dot1 = DotView(dotType: .dotType1)
|
||||
private let dot2 = DotView(dotType: .dotType2)
|
||||
private let dot3 = DotView(dotType: .dotType3)
|
||||
|
||||
override public var isHidden: Bool {
|
||||
didSet {
|
||||
Logger.verbose("\(oldValue) -> \(isHidden)")
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
override init(frame: CGRect) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
@objc
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
|
||||
// init(arrangedSubviews:...) is not a designated initializer.
|
||||
addArrangedSubview(dot1)
|
||||
addArrangedSubview(dot2)
|
||||
addArrangedSubview(dot3)
|
||||
|
||||
self.axis = .horizontal
|
||||
self.spacing = kDotMaxHSpacing
|
||||
self.alignment = .center
|
||||
}
|
||||
|
||||
@objc
|
||||
public func startAnimation() {
|
||||
}
|
||||
|
||||
@objc
|
||||
public func stopAnimation() {
|
||||
}
|
||||
|
||||
private enum DotType {
|
||||
case dotType1
|
||||
case dotType2
|
||||
case dotType3
|
||||
}
|
||||
|
||||
private class DotView: UIView {
|
||||
private let dotType: DotType
|
||||
|
||||
private let shapeLayer = CAShapeLayer()
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
@available(*, unavailable, message:"use other constructor instead.")
|
||||
override init(frame: CGRect) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
init(dotType: DotType) {
|
||||
self.dotType = dotType
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
autoSetDimension(.width, toSize: kMaxRadiusPt)
|
||||
autoSetDimension(.height, toSize: kMaxRadiusPt)
|
||||
|
||||
self.layer.addSublayer(shapeLayer)
|
||||
|
||||
updateLayer()
|
||||
// self.text = text
|
||||
//
|
||||
// setupSubviews()
|
||||
}
|
||||
|
||||
private func updateLayer() {
|
||||
shapeLayer.fillColor = UIColor.ows_signalBlue.cgColor
|
||||
|
||||
let margin = (TypingIndicatorView.kMaxRadiusPt - TypingIndicatorView.kMinRadiusPt) * 0.5
|
||||
let bezierPath = UIBezierPath(ovalIn: CGRect(x: margin, y: margin, width: TypingIndicatorView.kMinRadiusPt, height: TypingIndicatorView.kMinRadiusPt))
|
||||
shapeLayer.path = bezierPath.cgPath
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ public protocol TypingIndicators: class {
|
|||
//
|
||||
// TODO: Use this method.
|
||||
@objc
|
||||
func typingIndicators(forThread thread: TSThread, recipientId: String) -> String?
|
||||
func typingIndicators(forThread thread: TSThread) -> String?
|
||||
|
||||
@objc
|
||||
func setTypingIndicatorsEnabled(value: Bool)
|
||||
|
@ -45,7 +45,8 @@ public protocol TypingIndicators: class {
|
|||
@objc(OWSTypingIndicatorsImpl)
|
||||
public class TypingIndicatorsImpl: NSObject, TypingIndicators {
|
||||
|
||||
@objc public static let typingIndicatorStateDidChange = Notification.Name("typingIndicatorStateDidChange")
|
||||
@objc
|
||||
public static let typingIndicatorStateDidChange = Notification.Name("typingIndicatorStateDidChange")
|
||||
|
||||
private let kDatabaseCollection = "TypingIndicators"
|
||||
private let kDatabaseKey_TypingIndicatorsEnabled = "kDatabaseKey_TypingIndicatorsEnabled"
|
||||
|
@ -150,7 +151,7 @@ public class TypingIndicatorsImpl: NSObject, TypingIndicators {
|
|||
}
|
||||
|
||||
@objc
|
||||
public func typingIndicators(forThread thread: TSThread, recipientId: String) -> String? {
|
||||
public func typingIndicators(forThread thread: TSThread) -> String? {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
var firstRecipientId: String?
|
||||
|
|
Loading…
Reference in New Issue