Show downloaded contact avatar in thread

// FREEBIE
This commit is contained in:
Michael Kirk 2018-05-04 20:46:00 -04:00
parent 48b4791b13
commit 5ba5e98260
11 changed files with 69 additions and 79 deletions

View File

@ -310,7 +310,8 @@
45360B901F9527DA00FA666C /* SearcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45360B8F1F9527DA00FA666C /* SearcherTest.swift */; };
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */; };
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
4542DF52208B82E9007B4E76 /* ThreadModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadModel.swift */; };
4541B71B209D2DAE0008608F /* ContactShareViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */; };
4542DF52208B82E9007B4E76 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */; };
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF53208D40AC007B4E76 /* LoadingViewController.swift */; };
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454A84032059C787008B8C75 /* MediaTileViewController.swift */; };
@ -939,7 +940,8 @@
45360B8F1F9527DA00FA666C /* SearcherTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearcherTest.swift; sourceTree = "<group>"; };
4539B5851F79348F007141FF /* PushRegistrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushRegistrationManager.swift; sourceTree = "<group>"; };
453CC0361D08E1A60040EBA3 /* sn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sn; path = translations/sn.lproj/Localizable.strings; sourceTree = "<group>"; };
4542DF51208B82E9007B4E76 /* ThreadModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadModel.swift; sourceTree = "<group>"; };
4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactShareViewModel.swift; sourceTree = "<group>"; };
4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewModel.swift; sourceTree = "<group>"; };
4542DF53208D40AC007B4E76 /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = "<group>"; };
45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; };
454A84032059C787008B8C75 /* MediaTileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTileViewController.swift; sourceTree = "<group>"; };
@ -1806,6 +1808,7 @@
450DF2061E0DD28D003D14BE /* UserInterface */ = {
isa = PBXGroup;
children = (
4541B719209D2D860008608F /* ViewModels */,
450DF2071E0DD29E003D14BE /* Notifications */,
34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */,
34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */,
@ -1886,6 +1889,15 @@
path = SignalMessaging;
sourceTree = "<group>";
};
4541B719209D2D860008608F /* ViewModels */ = {
isa = PBXGroup;
children = (
4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */,
4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
};
45464DB81DFA03D8001D3FD6 /* Signaling */ = {
isa = PBXGroup;
children = (
@ -1931,7 +1943,6 @@
45DF5DF11DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift */,
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */,
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */,
4542DF51208B82E9007B4E76 /* ThreadModel.swift */,
);
path = Models;
sourceTree = "<group>";
@ -3147,7 +3158,7 @@
34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */,
34D99C931F2937CC00D284D6 /* OWSAnalytics.swift in Sources */,
340FC8B8204DAC8D007AEB0F /* AddToGroupViewController.m in Sources */,
4542DF52208B82E9007B4E76 /* ThreadModel.swift in Sources */,
4542DF52208B82E9007B4E76 /* ThreadViewModel.swift in Sources */,
341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */,
340FC8AF204DAC8D007AEB0F /* OWSLinkDeviceViewController.m in Sources */,
34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */,
@ -3181,6 +3192,7 @@
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
4541B71B209D2DAE0008608F /* ContactShareViewModel.swift in Sources */,
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,

View File

@ -1,40 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class ThreadViewModel: NSObject {
let hasUnreadMessages: Bool
let lastMessageDate: Date
let isGroupThread: Bool
let threadRecord: TSThread
let unreadCount: UInt
let contactIdentifier: String?
let name: String
let isMuted: Bool
var isContactThread: Bool {
return !isGroupThread
}
let lastMessageText: String?
init(thread: TSThread, transaction: YapDatabaseReadTransaction) {
self.threadRecord = thread
self.lastMessageDate = thread.lastMessageDate()
self.isGroupThread = thread.isGroupThread()
self.name = thread.name()
self.isMuted = thread.isMuted
self.lastMessageText = thread.lastMessageText(transaction: transaction)
if let contactThread = thread as? TSContactThread {
self.contactIdentifier = contactThread.contactIdentifier()
} else {
self.contactIdentifier = nil
}
self.unreadCount = thread.unreadMessageCount(transaction: transaction)
self.hasUnreadMessages = unreadCount > 0
}
}

View File

@ -65,7 +65,8 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
var reachability: Reachability?
private let contact: OWSContact
// TODO rename this property to contactShare
private let contact: ContactShareViewModel
// MARK: - Initializers
@ -74,9 +75,9 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
fatalError("Unimplemented")
}
required init(contact: OWSContact) {
required init(contactShare: ContactShareViewModel) {
contactsManager = Environment.current().contactsManager
self.contact = contact
self.contact = contactShare
super.init(nibName: nil, bundle: nil)
@ -639,7 +640,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
return
}
guard let systemContact = OWSContacts.systemContact(for: contact) else {
guard let systemContact = OWSContacts.systemContact(for: contact.dbRecord) else {
owsFail("\(logTag) Could not derive system contact.")
return
}

View File

@ -4,11 +4,11 @@
NS_ASSUME_NONNULL_BEGIN
@class OWSContact;
@class ContactShareViewModel;
@interface OWSContactShareView : UIView
- (instancetype)initWithContactShare:(OWSContact *)contactShare isIncoming:(BOOL)isIncoming;
- (instancetype)initWithContactShare:(ContactShareViewModel *)contactShare isIncoming:(BOOL)isIncoming;
- (void)createContents;

View File

@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSContactShareView ()
@property (nonatomic) OWSContact *contactShare;
@property (nonatomic) ContactShareViewModel *contactShare;
@property (nonatomic) BOOL isIncoming;
@end
@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSContactShareView
- (instancetype)initWithContactShare:(OWSContact *)contactShare isIncoming:(BOOL)isIncoming
- (instancetype)initWithContactShare:(ContactShareViewModel *)contactShare isIncoming:(BOOL)isIncoming
{
self = [super init];
@ -108,12 +108,18 @@ NS_ASSUME_NONNULL_BEGIN
// TODO: Use the contact's avatar if present and downloaded.
AvatarImageView *avatarView = [AvatarImageView new];
// TODO: What's the best colorSeed value to use?
OWSAvatarBuilder *avatarBuilder =
[[OWSContactAvatarBuilder alloc] initWithNonSignalName:self.contactShare.displayName
colorSeed:self.contactShare.displayName
diameter:(NSUInteger)self.iconSize
contactsManager:[Environment current].contactsManager];
avatarView.image = [avatarBuilder build];
UIImage *_Nullable avatarImage = self.contactShare.avatarImage;
if (!avatarImage) {
OWSAvatarBuilder *avatarBuilder =
[[OWSContactAvatarBuilder alloc] initWithNonSignalName:self.contactShare.displayName
colorSeed:self.contactShare.displayName
diameter:(NSUInteger)self.iconSize
contactsManager:[Environment current].contactsManager];
avatarImage = [avatarBuilder build];
}
avatarView.image = avatarImage;
[avatarView autoSetDimension:ALDimensionWidth toSize:self.iconSize];
[avatarView autoSetDimension:ALDimensionHeight toSize:self.iconSize];
[avatarView setCompressionResistanceHigh];

View File

@ -2087,7 +2087,7 @@ typedef enum : NSUInteger {
OWSAssert(conversationItem.contactShare);
OWSAssert([conversationItem.interaction isKindOfClass:[TSMessage class]]);
ContactViewController *view = [[ContactViewController alloc] initWithContact:conversationItem.contactShare];
ContactViewController *view = [[ContactViewController alloc] initWithContactShare:conversationItem.contactShare];
[self.navigationController pushViewController:view animated:YES];
}

View File

@ -24,10 +24,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
#pragma mark -
@class ContactShareViewModel;
@class ConversationViewCell;
@class DisplayableText;
@class OWSAudioMessageView;
@class OWSContact;
@class OWSQuotedReplyModel;
@class TSAttachmentPointer;
@class TSAttachmentStream;
@ -103,7 +103,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
// if a load has previously failed.
@property (nonatomic) BOOL didCellMediaFailToLoad;
- (nullable OWSContact *)contactShare;
@property (nonatomic, readonly, nullable) ContactShareViewModel *contactShare;
#pragma mark - UIMenuController

View File

@ -65,7 +65,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
@property (nonatomic, readonly, nullable) NSString *quotedRecipientId;
@property (nonatomic, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer;
@property (nonatomic, nullable) OWSContact *contactShare;
@property (nonatomic, nullable) ContactShareViewModel *contactShare;
@property (nonatomic) CGSize mediaSize;
@end
@ -406,7 +406,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
TSMessage *message = (TSMessage *)self.interaction;
if (message.contactShare) {
self.contactShare = message.contactShare;
self.contactShare =
[[ContactShareViewModel alloc] initWithContactShareRecord:message.contactShare transaction:transaction];
self.messageCellType = OWSMessageCellType_ContactShare;
return;
}

View File

@ -3039,11 +3039,11 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
NSData *avatarImageData
= UIImageJPEGRepresentation(avatarImage, (CGFloat)0.9);
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc]
initWithContentType:@"image/jpg"
initWithContentType:OWSMimeTypeImageJpeg
byteCount:avatarImageData.length
sourceFilename:nil];
NSError *error;
BOOL success =
[attachmentStream writeData:avatarImageData error:&error];
@ -3229,7 +3229,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
NSData *avatarImageData
= UIImageJPEGRepresentation(avatarImage, (CGFloat)0.9);
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc]
initWithContentType:@"image/jpg"
initWithContentType:OWSMimeTypeImageJpeg
byteCount:avatarImageData.length
sourceFilename:nil];

View File

@ -613,11 +613,11 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
}
func didTapContactShare(_ viewItem: ConversationViewItem) {
guard let contact = viewItem.contactShare() else {
guard let contactShare = viewItem.contactShare else {
owsFail("\(logTag) missing contact.")
return
}
let contactViewController = ContactViewController(contact: contact)
let contactViewController = ContactViewController(contactShare: contactShare)
self.navigationController?.pushViewController(contactViewController, animated: true)
}

View File

@ -4,6 +4,7 @@
#import "OWSOrphanedDataCleaner.h"
#import "NSDate+OWS.h"
#import "OWSContact.h"
#import "OWSPrimaryStorage.h"
#import "TSAttachmentStream.h"
#import "TSInteraction.h"
@ -82,18 +83,18 @@ NS_ASSUME_NONNULL_BEGIN
}];
}];
CleanupLogDebug(@"%@ fileCount: %zd", self.logTag, fileCount);
CleanupLogDebug(@"%@ fileCount: %tu", self.logTag, fileCount);
CleanupLogDebug(@"%@ totalFileSize: %lld", self.logTag, totalFileSize);
CleanupLogDebug(@"%@ attachmentStreams: %d", self.logTag, attachmentStreamCount);
CleanupLogDebug(@"%@ attachmentStreams with file paths: %zd", self.logTag, attachmentFilePaths.count);
CleanupLogDebug(@"%@ attachmentStreams with file paths: %tu", self.logTag, attachmentFilePaths.count);
NSMutableSet<NSString *> *orphanDiskFilePaths = [diskFilePaths mutableCopy];
[orphanDiskFilePaths minusSet:attachmentFilePaths];
NSMutableSet<NSString *> *missingAttachmentFilePaths = [attachmentFilePaths mutableCopy];
[missingAttachmentFilePaths minusSet:diskFilePaths];
CleanupLogDebug(@"%@ orphan disk file paths: %zd", self.logTag, orphanDiskFilePaths.count);
CleanupLogDebug(@"%@ missing attachment file paths: %zd", self.logTag, missingAttachmentFilePaths.count);
CleanupLogDebug(@"%@ orphan disk file paths: %tu", self.logTag, orphanDiskFilePaths.count);
CleanupLogDebug(@"%@ missing attachment file paths: %tu", self.logTag, missingAttachmentFilePaths.count);
[self printPaths:orphanDiskFilePaths.allObjects label:@"orphan disk file paths"];
[self printPaths:missingAttachmentFilePaths.allObjects label:@"missing attachment file paths"];
@ -106,6 +107,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableSet<NSString *> *orphanInteractionIds = [NSMutableSet new];
NSMutableSet<NSString *> *messageAttachmentIds = [NSMutableSet new];
NSMutableSet<NSString *> *quotedReplyThumbnailAttachmentIds = [NSMutableSet new];
NSMutableSet<NSString *> *contactShareAvatarAttachmentIds = [NSMutableSet new];
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[transaction enumerateKeysAndObjectsInCollection:TSMessage.collection
@ -129,22 +131,30 @@ NS_ASSUME_NONNULL_BEGIN
addObjectsFromArray:quotedMessage
.thumbnailAttachmentStreamIds];
}
OWSContact *_Nullable contactShare = message.contactShare;
if (contactShare && contactShare.avatarAttachmentId) {
[contactShareAvatarAttachmentIds
addObject:contactShare.avatarAttachmentId];
}
}];
}];
CleanupLogDebug(@"%@ attachmentIds: %zd", self.logTag, attachmentIds.count);
CleanupLogDebug(@"%@ messageAttachmentIds: %zd", self.logTag, messageAttachmentIds.count);
CleanupLogDebug(@"%@ quotedReplyThumbnailAttachmentIds: %zd", self.logTag, quotedReplyThumbnailAttachmentIds.count);
CleanupLogDebug(@"%@ attachmentIds: %tu", self.logTag, attachmentIds.count);
CleanupLogDebug(@"%@ messageAttachmentIds: %tu", self.logTag, messageAttachmentIds.count);
CleanupLogDebug(@"%@ quotedReplyThumbnailAttachmentIds: %tu", self.logTag, quotedReplyThumbnailAttachmentIds.count);
CleanupLogDebug(@"%@ contactShareAvatarAttachmentIds: %tu", self.logTag, contactShareAvatarAttachmentIds.count);
NSMutableSet<NSString *> *orphanAttachmentIds = [attachmentIds mutableCopy];
[orphanAttachmentIds minusSet:messageAttachmentIds];
[orphanAttachmentIds minusSet:quotedReplyThumbnailAttachmentIds];
[orphanAttachmentIds minusSet:contactShareAvatarAttachmentIds];
NSMutableSet<NSString *> *missingAttachmentIds = [messageAttachmentIds mutableCopy];
[missingAttachmentIds minusSet:attachmentIds];
CleanupLogDebug(@"%@ orphan attachmentIds: %zd", self.logTag, orphanAttachmentIds.count);
CleanupLogDebug(@"%@ missing attachmentIds: %zd", self.logTag, missingAttachmentIds.count);
CleanupLogDebug(@"%@ orphan interactions: %zd", self.logTag, orphanInteractionIds.count);
CleanupLogDebug(@"%@ orphan attachmentIds: %tu", self.logTag, orphanAttachmentIds.count);
CleanupLogDebug(@"%@ missing attachmentIds: %tu", self.logTag, missingAttachmentIds.count);
CleanupLogDebug(@"%@ orphan interactions: %tu", self.logTag, orphanInteractionIds.count);
// We need to avoid cleaning up new attachments and files that are still in the process of
// being created/written, so we don't clean up anything recent.