Format message statuses with date if possible.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 0b535ae811
commit d557817bb4

@ -4,11 +4,13 @@
#import "AppSettingsViewController.h"
#import "AttachmentSharing.h"
#import "DateUtil.h"
#import "DebugUIPage.h"
#import "Environment.h"
#import "FLAnimatedImage.h"
#import "FingerprintViewController.h"
#import "HomeViewController.h"
#import "NSAttributedString+OWS.h"
#import "NotificationsManager.h"
#import "OWSAnyTouchGestureRecognizer.h"
#import "OWSAudioAttachmentPlayer.h"

@ -8,6 +8,7 @@
#import "BlockListUIUtils.h"
#import "BlockListViewController.h"
#import "ContactsViewHelper.h"
#import "DateUtil.h"
#import "DebugUITableViewController.h"
#import "Environment.h"
#import "FingerprintViewController.h"
@ -2151,22 +2152,22 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
return [[NSAttributedString alloc]
initWithString:NSLocalizedString(@"MESSAGE_STATUS_FAILED", @"message footer for failed messages")];
} else if (outgoingMessage.messageState == TSOutgoingMessageStateSentToService) {
NSString *text = (outgoingMessage.wasDelivered
? NSLocalizedString(@"MESSAGE_STATUS_DELIVERED", @"message footer for delivered messages")
: NSLocalizedString(@"MESSAGE_STATUS_SENT", @"message footer for sent messages"));
NSAttributedString *result = [[NSAttributedString alloc] initWithString:text];
if ([OWSReadReceiptManager.sharedManager areReadReceiptsEnabled] && outgoingMessage.wasDelivered
&& outgoingMessage.recipientReadMap.count > 0) {
NSAttributedString *checkmark = [[NSAttributedString alloc]
initWithString:@"\uf00c "
attributes:@{
NSFontAttributeName : [UIFont ows_fontAwesomeFont:10.f],
NSForegroundColorAttributeName : [UIColor ows_materialBlueColor],
}];
NSAttributedString *spacing = [[NSAttributedString alloc] initWithString:@" "];
result = [[checkmark rtlSafeAppend:spacing referenceView:self.view] rtlSafeAppend:result
referenceView:self.view];
NSString *text;
if (outgoingMessage.wasDelivered) {
NSNumber *_Nullable firstRecipientReadTimestamp = [outgoingMessage firstRecipientReadTimestamp];
if ([OWSReadReceiptManager.sharedManager areReadReceiptsEnabled] && firstRecipientReadTimestamp) {
text = NSLocalizedString(@"MESSAGE_STATUS_READ", @"message footer for read messages");
text = [text rtlSafeAppend:@" " referenceView:self.view];
text = [text rtlSafeAppend:[DateUtil formatPastTimestampRelativeToNow:firstRecipientReadTimestamp
.unsignedLongLongValue]
referenceView:self.view];
} else {
text = NSLocalizedString(@"MESSAGE_STATUS_DELIVERED", @"message footer for delivered messages");
}
} else {
text = NSLocalizedString(@"MESSAGE_STATUS_SENT", @"message footer for sent messages");
}
NSAttributedString *result = [[NSAttributedString alloc] initWithString:text];
// Show when it's the last message in the thread
if (indexPath.item == [self.collectionView numberOfItemsInSection:indexPath.section] - 1) {

@ -21,14 +21,6 @@ class MessageMetadataViewController: OWSViewController {
var attachmentStream: TSAttachmentStream?
var messageBody: String?
static let dateFormatter: DateFormatter = CreateDateFormatter()
private class func CreateDateFormatter() -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .long
return dateFormatter
}
// MARK: Initializers
@available(*, unavailable, message:"use message: constructor instead.")
@ -127,16 +119,14 @@ class MessageMetadataViewController: OWSViewController {
}
}
let sentDate = NSDate.ows_date(withMillisecondsSince1970:message.timestamp)
rows.append(valueRow(name: NSLocalizedString("MESSAGE_METADATA_VIEW_SENT_DATE_TIME",
comment: "Label for the 'sent date & time' field of the 'message metadata' view."),
value:MessageMetadataViewController.dateFormatter.string(from:sentDate)))
value:DateUtil.formatPastTimestampRelative(toNow:message.timestamp)))
if let _ = message as? TSIncomingMessage {
let receivedDate = message.dateForSorting()
rows.append(valueRow(name: NSLocalizedString("MESSAGE_METADATA_VIEW_RECEIVED_DATE_TIME",
comment: "Label for the 'received date & time' field of the 'message metadata' view."),
value:MessageMetadataViewController.dateFormatter.string(from:receivedDate)))
value:DateUtil.formatPastTimestampRelative(toNow:message.timestampForSorting())))
}
// TODO: We could include the "disappearing messages" state here.
@ -287,19 +277,18 @@ class MessageMetadataViewController: OWSViewController {
let recipientReadMap = message.recipientReadMap
if let readTimestamp = recipientReadMap[recipientId] {
assert(message.messageState == .sentToService)
let readDate = NSDate.ows_date(withMillisecondsSince1970:readTimestamp.uint64Value)
return String(format:NSLocalizedString("MESSAGE_STATUS_READ_WITH_TIMESTAMP_FORMAT",
comment: "message status for messages read by the recipient. Embeds: {{the date and time the message was read}}."),
MessageMetadataViewController.dateFormatter.string(from:readDate))
return NSLocalizedString("MESSAGE_STATUS_READ", comment:"message footer for read messages").rtlSafeAppend(" ", referenceView:self.view)
.rtlSafeAppend(
DateUtil.formatPastTimestampRelative(toNow:readTimestamp.uint64Value), referenceView:self.view)
}
let recipientDeliveryMap = message.recipientDeliveryMap
if let deliveryTimestamp = recipientDeliveryMap[recipientId] {
assert(message.messageState == .sentToService)
let deliveryDate = NSDate.ows_date(withMillisecondsSince1970:deliveryTimestamp.uint64Value)
return String(format:NSLocalizedString("MESSAGE_STATUS_DELIVERED_WITH_TIMESTAMP_FORMAT",
comment: "message status for messages delivered to the recipient. Embeds: {{the date and time the message was delivered}}."),
MessageMetadataViewController.dateFormatter.string(from:deliveryDate))
return NSLocalizedString("MESSAGE_STATUS_DELIVERED",
comment:"message status for message delivered to their recipient.").rtlSafeAppend(" ", referenceView:self.view)
.rtlSafeAppend(
DateUtil.formatPastTimestampRelative(toNow:deliveryTimestamp.uint64Value), referenceView:self.view)
}
if message.wasDelivered {

@ -5,10 +5,12 @@
@interface DateUtil : NSObject
+ (NSDateFormatter *)dateFormatter;
+ (NSDateFormatter *)weekdayFormatter;
//+ (NSDateFormatter *)weekdayFormatter;
+ (NSDateFormatter *)timeFormatter;
+ (BOOL)dateIsOlderThanOneDay:(NSDate *)date;
+ (BOOL)dateIsOlderThanOneWeek:(NSDate *)date;
+ (BOOL)dateIsToday:(NSDate *)date;
+ (NSString *)formatPastTimestampRelativeToNow:(uint64_t)pastTimestamp;
@end

@ -53,4 +53,36 @@ static NSString *const DATE_FORMAT_WEEKDAY = @"EEEE";
return [self date:[NSDate date] isEqualToDateIgnoringTime:date];
}
+ (NSString *)formatPastTimestampRelativeToNow:(uint64_t)pastTimestamp
{
OWSCAssert(pastTimestamp > 0);
uint64_t nowTimestamp = [NSDate ows_millisecondTimeStamp];
if (pastTimestamp >= nowTimestamp) {
OWSCFail(@"%@ Unexpected timestamp", self.tag);
return NSLocalizedString(@"TIME_NOW", @"Indicates that the event happened now.");
}
NSDate *pastDate = [NSDate ows_dateWithMillisecondsSince1970:pastTimestamp];
if ([self dateIsToday:pastDate]) {
return [[self timeFormatter] stringFromDate:pastDate];
} else if (![self dateIsOlderThanOneWeek:pastDate]) {
return [[self weekdayFormatter] stringFromDate:pastDate];
} else {
return [[self dateFormatter] stringFromDate:pastDate];
}
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end

@ -4,6 +4,12 @@
NS_ASSUME_NONNULL_BEGIN
@interface NSString (OWS)
- (NSString *)rtlSafeAppend:(NSString *)string referenceView:(UIView *)referenceView;
@end
@interface NSAttributedString (OWS)
- (NSAttributedString *)rtlSafeAppend:(NSAttributedString *)string referenceView:(UIView *)referenceView;

@ -7,6 +7,22 @@
NS_ASSUME_NONNULL_BEGIN
@implementation NSString (OWS)
- (NSString *)rtlSafeAppend:(NSString *)string referenceView:(UIView *)referenceView
{
OWSAssert(string);
OWSAssert(referenceView);
if ([referenceView isRTL]) {
return [string stringByAppendingString:self];
} else {
return [self stringByAppendingString:string];
}
}
@end
@implementation NSAttributedString (OWS)
- (NSAttributedString *)rtlSafeAppend:(NSAttributedString *)string referenceView:(UIView *)referenceView

@ -839,6 +839,9 @@
/* message footer for failed messages */
"MESSAGE_STATUS_FAILED" = "Sending failed. Tap for info.";
/* message footer for read messages */
"MESSAGE_STATUS_READ" = "Read";
/* message status for messages read by the recipient. Embeds: {{the date and time the message was read}}. */
"MESSAGE_STATUS_READ_WITH_TIMESTAMP_FORMAT" = "Read %@";
@ -1520,6 +1523,9 @@
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Indicates that the event happened now. */
"TIME_NOW" = "Now";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Cancel";

@ -187,6 +187,7 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
- (void)updateWithReadRecipientId:(NSString *)recipientId
readTimestamp:(uint64_t)readTimestamp
transaction:(YapDatabaseReadWriteTransaction *)transaction;
- (nullable NSNumber *)firstRecipientReadTimestamp;
#pragma mark - Sent Recipients

@ -435,6 +435,17 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
}];
}
- (nullable NSNumber *)firstRecipientReadTimestamp
{
NSNumber *result = nil;
for (NSNumber *timestamp in self.recipientReadMap.allValues) {
if (!result || (result.unsignedLongLongValue > timestamp.unsignedLongLongValue)) {
result = timestamp;
}
}
return result;
}
#pragma mark -
- (OWSSignalServiceProtosDataMessageBuilder *)dataMessageBuilder

@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSDate *)ows_dateWithMillisecondsSince1970:(uint64_t)milliseconds;
+ (uint64_t)ows_millisecondsSince1970ForDate:(NSDate *)date;
+ (NSString *)formatPastTimestampRelativeToNow:(uint64_t)timestamp;
@end
NS_ASSUME_NONNULL_END

Loading…
Cancel
Save