mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Implement avatar sending
// FREEBIE
This commit is contained in:
parent
eb97e82d19
commit
77fc5571fb
|
@ -310,7 +310,7 @@
|
||||||
45360B901F9527DA00FA666C /* SearcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45360B8F1F9527DA00FA666C /* SearcherTest.swift */; };
|
45360B901F9527DA00FA666C /* SearcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45360B8F1F9527DA00FA666C /* SearcherTest.swift */; };
|
||||||
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */; };
|
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */; };
|
||||||
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
|
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
|
||||||
4541B71B209D2DAE0008608F /* ContactShareViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */; };
|
4541B71D209D3B7A0008608F /* ContactShareViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */; };
|
||||||
4542DF52208B82E9007B4E76 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */; };
|
4542DF52208B82E9007B4E76 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */; };
|
||||||
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF53208D40AC007B4E76 /* LoadingViewController.swift */; };
|
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF53208D40AC007B4E76 /* LoadingViewController.swift */; };
|
||||||
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
|
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
|
||||||
|
@ -1830,8 +1830,6 @@
|
||||||
45194F911FD7214600333B2C /* Models */ = {
|
45194F911FD7214600333B2C /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */,
|
|
||||||
459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */,
|
|
||||||
34C42D621F4734ED0072EC04 /* OWSContactOffersInteraction.h */,
|
34C42D621F4734ED0072EC04 /* OWSContactOffersInteraction.h */,
|
||||||
34C42D631F4734ED0072EC04 /* OWSContactOffersInteraction.m */,
|
34C42D631F4734ED0072EC04 /* OWSContactOffersInteraction.m */,
|
||||||
34C42D641F4734ED0072EC04 /* TSUnreadIndicatorInteraction.h */,
|
34C42D641F4734ED0072EC04 /* TSUnreadIndicatorInteraction.h */,
|
||||||
|
@ -1872,6 +1870,7 @@
|
||||||
453518931FC63DBF00210559 /* SignalMessaging */ = {
|
453518931FC63DBF00210559 /* SignalMessaging */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4541B71C209D3B4F0008608F /* ViewModels */,
|
||||||
45194F911FD7214600333B2C /* Models */,
|
45194F911FD7214600333B2C /* Models */,
|
||||||
451F8A361FD7115D005CB9DA /* ViewControllers */,
|
451F8A361FD7115D005CB9DA /* ViewControllers */,
|
||||||
454A96571FD600B4008D2A0E /* attachments */,
|
454A96571FD600B4008D2A0E /* attachments */,
|
||||||
|
@ -1893,7 +1892,16 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */,
|
4542DF51208B82E9007B4E76 /* ThreadViewModel.swift */,
|
||||||
|
);
|
||||||
|
path = ViewModels;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4541B71C209D3B4F0008608F /* ViewModels */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */,
|
4541B71A209D2DAE0008608F /* ContactShareViewModel.swift */,
|
||||||
|
459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */,
|
||||||
|
459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */,
|
||||||
);
|
);
|
||||||
path = ViewModels;
|
path = ViewModels;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3118,6 +3126,7 @@
|
||||||
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */,
|
4503F1C3204711D300CEE724 /* OWS107LegacySounds.m in Sources */,
|
||||||
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */,
|
3438226A209B63500094FEB7 /* EditContactShareNameViewController.swift in Sources */,
|
||||||
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */,
|
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */,
|
||||||
|
4541B71D209D3B7A0008608F /* ContactShareViewModel.swift in Sources */,
|
||||||
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */,
|
4598198F204E2F28009414F2 /* OWS108CallLoggingPreference.m in Sources */,
|
||||||
346129D21FD2085A00532771 /* CommonStrings.swift in Sources */,
|
346129D21FD2085A00532771 /* CommonStrings.swift in Sources */,
|
||||||
45F59A082028E4FB00E8D2B0 /* OWSAudioSession.swift in Sources */,
|
45F59A082028E4FB00E8D2B0 /* OWSAudioSession.swift in Sources */,
|
||||||
|
@ -3192,7 +3201,6 @@
|
||||||
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
|
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
|
||||||
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
|
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
|
||||||
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
|
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
|
||||||
4541B71B209D2DAE0008608F /* ContactShareViewModel.swift in Sources */,
|
|
||||||
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
|
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
|
||||||
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
||||||
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
|
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
|
||||||
|
|
|
@ -65,8 +65,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
|
|
||||||
var reachability: Reachability?
|
var reachability: Reachability?
|
||||||
|
|
||||||
// TODO rename this property to contactShare
|
private let contactShare: ContactShareViewModel
|
||||||
private let contact: ContactShareViewModel
|
|
||||||
|
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
|
|
||||||
required init(contactShare: ContactShareViewModel) {
|
required init(contactShare: ContactShareViewModel) {
|
||||||
contactsManager = Environment.current().contactsManager
|
contactsManager = Environment.current().contactsManager
|
||||||
self.contact = contactShare
|
self.contactShare = contactShare
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
|
@ -141,7 +140,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
private func updateMode() {
|
private func updateMode() {
|
||||||
SwiftAssertIsOnMainThread(#function)
|
SwiftAssertIsOnMainThread(#function)
|
||||||
|
|
||||||
guard phoneNumbersForContact().count > 0 else {
|
guard contactShare.phoneNumberStrings.count > 0 else {
|
||||||
viewMode = .noPhoneNumber
|
viewMode = .noPhoneNumber
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -160,7 +159,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
private func systemContactsWithSignalAccountsForContact() -> [String] {
|
private func systemContactsWithSignalAccountsForContact() -> [String] {
|
||||||
SwiftAssertIsOnMainThread(#function)
|
SwiftAssertIsOnMainThread(#function)
|
||||||
|
|
||||||
return phoneNumbersForContact().filter({ (phoneNumber) -> Bool in
|
return contactShare.phoneNumberStrings.filter({ (phoneNumber) -> Bool in
|
||||||
return contactsManager.hasSignalAccount(forRecipientId: phoneNumber)
|
return contactsManager.hasSignalAccount(forRecipientId: phoneNumber)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -168,21 +167,11 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
private func systemContactsForContact() -> [String] {
|
private func systemContactsForContact() -> [String] {
|
||||||
SwiftAssertIsOnMainThread(#function)
|
SwiftAssertIsOnMainThread(#function)
|
||||||
|
|
||||||
return phoneNumbersForContact().filter({ (phoneNumber) -> Bool in
|
return contactShare.phoneNumberStrings.filter({ (phoneNumber) -> Bool in
|
||||||
return contactsManager.allContactsMap[phoneNumber] != nil
|
return contactsManager.allContactsMap[phoneNumber] != nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func phoneNumbersForContact() -> [String] {
|
|
||||||
SwiftAssertIsOnMainThread(#function)
|
|
||||||
|
|
||||||
var result = [String]()
|
|
||||||
for phoneNumber in contact.phoneNumbers {
|
|
||||||
result.append(phoneNumber.phoneNumber)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateContent() {
|
private func updateContent() {
|
||||||
SwiftAssertIsOnMainThread(#function)
|
SwiftAssertIsOnMainThread(#function)
|
||||||
|
|
||||||
|
@ -265,8 +254,8 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
|
|
||||||
let avatarView = AvatarImageView()
|
let avatarView = AvatarImageView()
|
||||||
// TODO: What's the best colorSeed value to use?
|
// TODO: What's the best colorSeed value to use?
|
||||||
let avatarBuilder = OWSContactAvatarBuilder(nonSignalName: contact.displayName,
|
let avatarBuilder = OWSContactAvatarBuilder(nonSignalName: contactShare.displayName,
|
||||||
colorSeed: contact.displayName,
|
colorSeed: contactShare.displayName,
|
||||||
diameter: UInt(avatarSize),
|
diameter: UInt(avatarSize),
|
||||||
contactsManager: contactsManager)
|
contactsManager: contactsManager)
|
||||||
avatarView.image = avatarBuilder.build()
|
avatarView.image = avatarBuilder.build()
|
||||||
|
@ -277,7 +266,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
avatarView.autoSetDimension(.height, toSize: avatarSize)
|
avatarView.autoSetDimension(.height, toSize: avatarSize)
|
||||||
|
|
||||||
let nameLabel = UILabel()
|
let nameLabel = UILabel()
|
||||||
nameLabel.text = contact.displayName
|
nameLabel.text = contactShare.displayName
|
||||||
nameLabel.font = UIFont.ows_dynamicTypeTitle2.ows_bold()
|
nameLabel.font = UIFont.ows_dynamicTypeTitle2.ows_bold()
|
||||||
nameLabel.textColor = UIColor.black
|
nameLabel.textColor = UIColor.black
|
||||||
nameLabel.lineBreakMode = .byTruncatingTail
|
nameLabel.lineBreakMode = .byTruncatingTail
|
||||||
|
@ -289,7 +278,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
|
|
||||||
var lastView: UIView = nameLabel
|
var lastView: UIView = nameLabel
|
||||||
|
|
||||||
if let firstPhoneNumber = contact.phoneNumbers.first {
|
if let firstPhoneNumber = contactShare.phoneNumbers.first {
|
||||||
let phoneNumberLabel = UILabel()
|
let phoneNumberLabel = UILabel()
|
||||||
phoneNumberLabel.text = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: firstPhoneNumber.phoneNumber)
|
phoneNumberLabel.text = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: firstPhoneNumber.phoneNumber)
|
||||||
phoneNumberLabel.font = UIFont.ows_dynamicTypeCaption2
|
phoneNumberLabel.font = UIFont.ows_dynamicTypeCaption2
|
||||||
|
@ -388,7 +377,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
// action:#selector(didPressShareContact)))
|
// action:#selector(didPressShareContact)))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for phoneNumber in contact.phoneNumbers {
|
for phoneNumber in contactShare.phoneNumbers {
|
||||||
let formattedPhoneNumber = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: phoneNumber.phoneNumber)
|
let formattedPhoneNumber = PhoneNumber.bestEffortLocalizedPhoneNumber(withE164: phoneNumber.phoneNumber)
|
||||||
|
|
||||||
rows.append(createNameValueRow(name: phoneNumber.localizedLabel(),
|
rows.append(createNameValueRow(name: phoneNumber.localizedLabel(),
|
||||||
|
@ -402,7 +391,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
for email in contact.emails {
|
for email in contactShare.emails {
|
||||||
rows.append(createNameValueRow(name: email.localizedLabel(),
|
rows.append(createNameValueRow(name: email.localizedLabel(),
|
||||||
value: email.email,
|
value: email.email,
|
||||||
actionBlock: {
|
actionBlock: {
|
||||||
|
@ -600,7 +589,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
OWSAlerts.showErrorAlert(message: NSLocalizedString("UNSUPPORTED_FEATURE_ERROR", comment: ""))
|
OWSAlerts.showErrorAlert(message: NSLocalizedString("UNSUPPORTED_FEATURE_ERROR", comment: ""))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let phoneNumbers = phoneNumbersForContact()
|
let phoneNumbers = contactShare.phoneNumberStrings
|
||||||
guard phoneNumbers.count > 0 else {
|
guard phoneNumbers.count > 0 else {
|
||||||
owsFail("\(logTag) no phone numbers.")
|
owsFail("\(logTag) no phone numbers.")
|
||||||
return
|
return
|
||||||
|
@ -640,8 +629,8 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let systemContact = OWSContacts.systemContact(for: contact.dbRecord) else {
|
guard let systemContact = OWSContacts.systemContact(for: contactShare.dbRecord) else {
|
||||||
owsFail("\(logTag) Could not derive system contact.")
|
owsFail("\(logTag) Could not derive system contactShare.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +668,7 @@ class ContactViewController: OWSViewController, CNContactViewControllerDelegate
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let firstPhoneNumber = contact.phoneNumbers.first else {
|
guard let firstPhoneNumber = contactShare.phoneNumbers.first else {
|
||||||
owsFail("\(logTag) Missing phone number.")
|
owsFail("\(logTag) Missing phone number.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#import <SignalMessaging/ThreadUtil.h>
|
#import <SignalMessaging/ThreadUtil.h>
|
||||||
#import <SignalMessaging/UIUtil.h>
|
#import <SignalMessaging/UIUtil.h>
|
||||||
#import <SignalMessaging/UIViewController+OWS.h>
|
#import <SignalMessaging/UIViewController+OWS.h>
|
||||||
|
#import <SignalServiceKit/Contact.h>
|
||||||
#import <SignalServiceKit/ContactsUpdater.h>
|
#import <SignalServiceKit/ContactsUpdater.h>
|
||||||
#import <SignalServiceKit/MimeTypeUtil.h>
|
#import <SignalServiceKit/MimeTypeUtil.h>
|
||||||
#import <SignalServiceKit/NSDate+OWS.h>
|
#import <SignalServiceKit/NSDate+OWS.h>
|
||||||
|
@ -2948,7 +2949,7 @@ typedef enum : NSUInteger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendContactShare:(OWSContact *)contactShare
|
- (void)sendContactShare:(ContactShareViewModel *)contactShare
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssert(contactShare);
|
OWSAssert(contactShare);
|
||||||
|
@ -2956,12 +2957,20 @@ typedef enum : NSUInteger {
|
||||||
DDLogVerbose(@"%@ Sending contact share.", self.logTag);
|
DDLogVerbose(@"%@ Sending contact share.", self.logTag);
|
||||||
|
|
||||||
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
|
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
|
||||||
TSOutgoingMessage *message = [ThreadUtil sendMessageWithContactShare:contactShare
|
|
||||||
inThread:self.thread
|
|
||||||
messageSender:self.messageSender
|
|
||||||
completion:nil];
|
|
||||||
|
|
||||||
[self messageWasSent:message];
|
[self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||||
|
if (contactShare.avatarImage) {
|
||||||
|
[contactShare.dbRecord saveAvatarImage:contactShare.avatarImage transaction:transaction];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
completionBlock:^{
|
||||||
|
TSOutgoingMessage *message = [ThreadUtil sendMessageWithContactShare:contactShare.dbRecord
|
||||||
|
inThread:self.thread
|
||||||
|
messageSender:self.messageSender
|
||||||
|
completion:nil];
|
||||||
|
[self messageWasSent:message];
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
if (didAddToProfileWhitelist) {
|
if (didAddToProfileWhitelist) {
|
||||||
[self ensureDynamicInteractions];
|
[self ensureDynamicInteractions];
|
||||||
|
@ -4942,12 +4951,28 @@ interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransiti
|
||||||
|
|
||||||
DDLogDebug(@"%@ in %s with contact: %@", self.logTag, __PRETTY_FUNCTION__, contact);
|
DDLogDebug(@"%@ in %s with contact: %@", self.logTag, __PRETTY_FUNCTION__, contact);
|
||||||
|
|
||||||
OWSContact *_Nullable contactShare = [OWSContacts contactForSystemContact:contact.cnContact];
|
OWSContact *_Nullable contactShareRecord = [OWSContacts contactForSystemContact:contact.cnContact];
|
||||||
if (!contactShare) {
|
if (!contactShareRecord) {
|
||||||
DDLogError(@"%@ Could not convert system contact.", self.logTag);
|
DDLogError(@"%@ Could not convert system contact.", self.logTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL isProfileAvatar = NO;
|
||||||
|
UIImage *_Nullable avatarImage = contact.image;
|
||||||
|
if (!avatarImage) {
|
||||||
|
NSString *firstSignalId = contact.textSecureIdentifiers.firstObject;
|
||||||
|
if (firstSignalId) {
|
||||||
|
avatarImage = [self.contactsManager profileImageForPhoneIdentifier:firstSignalId];
|
||||||
|
if (avatarImage) {
|
||||||
|
isProfileAvatar = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactShareViewModel *contactShare =
|
||||||
|
[[ContactShareViewModel alloc] initWithContactShareRecord:contactShareRecord avatarImage:avatarImage];
|
||||||
|
contactShareRecord.isProfileAvatar = isProfileAvatar;
|
||||||
|
|
||||||
// TODO: We should probably show this in the same navigation view controller.
|
// TODO: We should probably show this in the same navigation view controller.
|
||||||
ApproveContactShareViewController *approveContactShare =
|
ApproveContactShareViewController *approveContactShare =
|
||||||
[[ApproveContactShareViewController alloc] initWithContactShare:contactShare
|
[[ApproveContactShareViewController alloc] initWithContactShare:contactShare
|
||||||
|
@ -4974,7 +4999,7 @@ interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransiti
|
||||||
#pragma mark - ApproveContactShareViewControllerDelegate
|
#pragma mark - ApproveContactShareViewControllerDelegate
|
||||||
|
|
||||||
- (void)approveContactShare:(ApproveContactShareViewController *)approveContactShare
|
- (void)approveContactShare:(ApproveContactShareViewController *)approveContactShare
|
||||||
didApproveContactShare:(OWSContact *)contactShare
|
didApproveContactShare:(ContactShareViewModel *)contactShare
|
||||||
{
|
{
|
||||||
DDLogInfo(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
|
DDLogInfo(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
@ -4985,7 +5010,7 @@ interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransiti
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)approveContactShare:(ApproveContactShareViewController *)approveContactShare
|
- (void)approveContactShare:(ApproveContactShareViewController *)approveContactShare
|
||||||
didCancelContactShare:(OWSContact *)contactShare
|
didCancelContactShare:(ContactShareViewModel *)contactShare
|
||||||
{
|
{
|
||||||
DDLogInfo(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
|
DDLogInfo(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
|
|
@ -3033,19 +3033,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
||||||
|
|
||||||
UIImage *avatarImage =
|
UIImage *avatarImage =
|
||||||
[OWSAvatarBuilder buildRandomAvatarWithDiameter:200];
|
[OWSAvatarBuilder buildRandomAvatarWithDiameter:200];
|
||||||
NSData *avatarImageData
|
[contact saveAvatarImage:avatarImage transaction:transaction];
|
||||||
= UIImageJPEGRepresentation(avatarImage, (CGFloat)0.9);
|
|
||||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc]
|
|
||||||
initWithContentType:OWSMimeTypeImageJpeg
|
|
||||||
byteCount:avatarImageData.length
|
|
||||||
sourceFilename:nil];
|
|
||||||
|
|
||||||
NSError *error;
|
|
||||||
BOOL success =
|
|
||||||
[attachmentStream writeData:avatarImageData error:&error];
|
|
||||||
OWSAssert(success && !error);
|
|
||||||
[attachmentStream saveWithTransaction:transaction];
|
|
||||||
[contact setAvatarAttachmentStream:attachmentStream];
|
|
||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
}]];
|
}]];
|
||||||
|
@ -3218,19 +3206,7 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
|
||||||
|
|
||||||
UIImage *avatarImage =
|
UIImage *avatarImage =
|
||||||
[OWSAvatarBuilder buildRandomAvatarWithDiameter:200];
|
[OWSAvatarBuilder buildRandomAvatarWithDiameter:200];
|
||||||
NSData *avatarImageData
|
[contact saveAvatarImage:avatarImage transaction:transaction];
|
||||||
= UIImageJPEGRepresentation(avatarImage, (CGFloat)0.9);
|
|
||||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc]
|
|
||||||
initWithContentType:OWSMimeTypeImageJpeg
|
|
||||||
byteCount:avatarImageData.length
|
|
||||||
sourceFilename:nil];
|
|
||||||
|
|
||||||
NSError *error;
|
|
||||||
BOOL success =
|
|
||||||
[attachmentStream writeData:avatarImageData error:&error];
|
|
||||||
OWSAssert(success && !error);
|
|
||||||
[attachmentStream saveWithTransaction:transaction];
|
|
||||||
[contact setAvatarAttachmentStream:attachmentStream];
|
|
||||||
|
|
||||||
return contact;
|
return contact;
|
||||||
}]];
|
}]];
|
||||||
|
|
40
Signal/src/ViewModels/ThreadViewModel.swift
Normal file
40
Signal/src/ViewModels/ThreadViewModel.swift
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
119
SignalMessaging/ViewModels/ContactShareViewModel.swift
Normal file
119
SignalMessaging/ViewModels/ContactShareViewModel.swift
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class ContactShareViewModel: NSObject {
|
||||||
|
|
||||||
|
public let dbRecord: OWSContact
|
||||||
|
public let avatarImage: UIImage?
|
||||||
|
|
||||||
|
public required init(contactShareRecord: OWSContact, avatarImage: UIImage?) {
|
||||||
|
self.dbRecord = contactShareRecord
|
||||||
|
self.avatarImage = avatarImage
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init(contactShareRecord: OWSContact, transaction: YapDatabaseReadTransaction) {
|
||||||
|
if let avatarAttachment = contactShareRecord.avatarAttachment(with: transaction) as? TSAttachmentStream {
|
||||||
|
self.init(contactShareRecord: contactShareRecord, avatarImage: avatarAttachment.image())
|
||||||
|
} else {
|
||||||
|
self.init(contactShareRecord: contactShareRecord, avatarImage: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Delegated -> dbRecord
|
||||||
|
|
||||||
|
public var addresses: [OWSContactAddress] {
|
||||||
|
get {
|
||||||
|
return dbRecord.addresses
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
return dbRecord.addresses = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var emails: [OWSContactEmail] {
|
||||||
|
get {
|
||||||
|
return dbRecord.emails
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
dbRecord.emails = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var phoneNumbers: [OWSContactPhoneNumber] {
|
||||||
|
get {
|
||||||
|
return dbRecord.phoneNumbers
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
dbRecord.phoneNumbers = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var phoneNumberStrings: [String] {
|
||||||
|
return phoneNumbers.map { $0.phoneNumber }
|
||||||
|
}
|
||||||
|
|
||||||
|
public var displayName: String {
|
||||||
|
return dbRecord.displayName
|
||||||
|
}
|
||||||
|
|
||||||
|
public var ows_isValid: Bool {
|
||||||
|
return dbRecord.ows_isValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
public var namePrefix: String? {
|
||||||
|
return dbRecord.namePrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
public var givenName: String? {
|
||||||
|
return dbRecord.givenName
|
||||||
|
}
|
||||||
|
|
||||||
|
public var middleName: String? {
|
||||||
|
return dbRecord.middleName
|
||||||
|
}
|
||||||
|
|
||||||
|
public var familyName: String? {
|
||||||
|
return dbRecord.familyName
|
||||||
|
}
|
||||||
|
|
||||||
|
public var nameSuffix: String? {
|
||||||
|
return dbRecord.nameSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
public var isProfileAvatar: Bool {
|
||||||
|
return dbRecord.isProfileAvatar
|
||||||
|
}
|
||||||
|
|
||||||
|
public func copy(withNamePrefix namePrefix: String?,
|
||||||
|
givenName: String?,
|
||||||
|
middleName: String?,
|
||||||
|
familyName: String?,
|
||||||
|
nameSuffix: String?) -> ContactShareViewModel {
|
||||||
|
|
||||||
|
// TODO move the `copy` logic into the view model?
|
||||||
|
let newDbRecord = dbRecord.copy(withNamePrefix: namePrefix, givenName: givenName, middleName: middleName, familyName: familyName, nameSuffix: nameSuffix)
|
||||||
|
|
||||||
|
return ContactShareViewModel(contactShareRecord: newDbRecord, avatarImage: self.avatarImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func newContact(withNamePrefix namePrefix: String?,
|
||||||
|
givenName: String?,
|
||||||
|
middleName: String?,
|
||||||
|
familyName: String?,
|
||||||
|
nameSuffix: String?) -> ContactShareViewModel {
|
||||||
|
|
||||||
|
// TODO move the `newContact` logic into the view model?
|
||||||
|
let newDbRecord = dbRecord.newContact(withNamePrefix: namePrefix,
|
||||||
|
givenName: givenName,
|
||||||
|
middleName: middleName,
|
||||||
|
familyName: familyName,
|
||||||
|
nameSuffix: nameSuffix)
|
||||||
|
|
||||||
|
return ContactShareViewModel(contactShareRecord: newDbRecord, avatarImage: self.avatarImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,8 +7,8 @@ import SignalServiceKit
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public protocol ApproveContactShareViewControllerDelegate: class {
|
public protocol ApproveContactShareViewControllerDelegate: class {
|
||||||
func approveContactShare(_ approveContactShare: ApproveContactShareViewController, didApproveContactShare contactShare: OWSContact)
|
func approveContactShare(_ approveContactShare: ApproveContactShareViewController, didApproveContactShare contactShare: ContactShareViewModel)
|
||||||
func approveContactShare(_ approveContactShare: ApproveContactShareViewController, didCancelContactShare contactShare: OWSContact)
|
func approveContactShare(_ approveContactShare: ApproveContactShareViewController, didCancelContactShare contactShare: ContactShareViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol ContactShareField: class {
|
protocol ContactShareField: class {
|
||||||
|
@ -48,7 +48,7 @@ class ContactShareFieldBase<ContactFieldType: OWSContactField>: NSObject, Contac
|
||||||
isIncludedFlag = isIncluded
|
isIncludedFlag = isIncluded
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyToContact(contact: OWSContact) {
|
func applyToContact(contact: ContactShareViewModel) {
|
||||||
preconditionFailure("This method must be overridden")
|
preconditionFailure("This method must be overridden")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class ContactShareFieldBase<ContactFieldType: OWSContactField>: NSObject, Contac
|
||||||
|
|
||||||
class ContactSharePhoneNumber: ContactShareFieldBase<OWSContactPhoneNumber> {
|
class ContactSharePhoneNumber: ContactShareFieldBase<OWSContactPhoneNumber> {
|
||||||
|
|
||||||
override func applyToContact(contact: OWSContact) {
|
override func applyToContact(contact: ContactShareViewModel) {
|
||||||
assert(isIncluded())
|
assert(isIncluded())
|
||||||
|
|
||||||
var values = [OWSContactPhoneNumber]()
|
var values = [OWSContactPhoneNumber]()
|
||||||
|
@ -71,7 +71,7 @@ class ContactSharePhoneNumber: ContactShareFieldBase<OWSContactPhoneNumber> {
|
||||||
|
|
||||||
class ContactShareEmail: ContactShareFieldBase<OWSContactEmail> {
|
class ContactShareEmail: ContactShareFieldBase<OWSContactEmail> {
|
||||||
|
|
||||||
override func applyToContact(contact: OWSContact) {
|
override func applyToContact(contact: ContactShareViewModel) {
|
||||||
assert(isIncluded())
|
assert(isIncluded())
|
||||||
|
|
||||||
var values = [OWSContactEmail]()
|
var values = [OWSContactEmail]()
|
||||||
|
@ -85,7 +85,7 @@ class ContactShareEmail: ContactShareFieldBase<OWSContactEmail> {
|
||||||
|
|
||||||
class ContactShareAddress: ContactShareFieldBase<OWSContactAddress> {
|
class ContactShareAddress: ContactShareFieldBase<OWSContactAddress> {
|
||||||
|
|
||||||
override func applyToContact(contact: OWSContact) {
|
override func applyToContact(contact: ContactShareViewModel) {
|
||||||
assert(isIncluded())
|
assert(isIncluded())
|
||||||
|
|
||||||
var values = [OWSContactAddress]()
|
var values = [OWSContactAddress]()
|
||||||
|
@ -185,7 +185,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
|
|
||||||
let contactsManager: OWSContactsManager
|
let contactsManager: OWSContactsManager
|
||||||
|
|
||||||
var contactShare: OWSContact
|
var contactShare: ContactShareViewModel
|
||||||
|
|
||||||
var fieldViews = [ContactShareFieldView]()
|
var fieldViews = [ContactShareFieldView]()
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
required public init(contactShare: OWSContact, contactsManager: OWSContactsManager, delegate: ApproveContactShareViewControllerDelegate) {
|
required public init(contactShare: ContactShareViewModel, contactsManager: OWSContactsManager, delegate: ApproveContactShareViewControllerDelegate) {
|
||||||
self.contactsManager = contactsManager
|
self.contactsManager = contactsManager
|
||||||
self.contactShare = contactShare
|
self.contactShare = contactShare
|
||||||
self.delegate = delegate
|
self.delegate = delegate
|
||||||
|
@ -277,7 +277,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
|
|
||||||
// TODO: Surface error with resolution to user if not.
|
// TODO: Surface error with resolution to user if not.
|
||||||
func canShareContact() -> Bool {
|
func canShareContact() -> Bool {
|
||||||
return contactShare.ows_isValid()
|
return contactShare.ows_isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNavigationBar() {
|
func updateNavigationBar() {
|
||||||
|
@ -471,7 +471,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
|
|
||||||
// MARK: -
|
// MARK: -
|
||||||
|
|
||||||
func filteredContactShare() -> OWSContact {
|
func filteredContactShare() -> ContactShareViewModel {
|
||||||
let result = self.contactShare.newContact(withNamePrefix: self.contactShare.namePrefix,
|
let result = self.contactShare.newContact(withNamePrefix: self.contactShare.namePrefix,
|
||||||
givenName: self.contactShare.givenName,
|
givenName: self.contactShare.givenName,
|
||||||
middleName: self.contactShare.middleName,
|
middleName: self.contactShare.middleName,
|
||||||
|
@ -498,7 +498,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
}
|
}
|
||||||
|
|
||||||
let filteredContactShare = self.filteredContactShare()
|
let filteredContactShare = self.filteredContactShare()
|
||||||
assert(filteredContactShare.ows_isValid())
|
assert(filteredContactShare.ows_isValid)
|
||||||
|
|
||||||
delegate.approveContactShare(self, didApproveContactShare: filteredContactShare)
|
delegate.approveContactShare(self, didApproveContactShare: filteredContactShare)
|
||||||
}
|
}
|
||||||
|
@ -523,7 +523,7 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh
|
||||||
|
|
||||||
// MARK: - EditContactShareNameViewControllerDelegate
|
// MARK: - EditContactShareNameViewControllerDelegate
|
||||||
|
|
||||||
public func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact) {
|
public func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: ContactShareViewModel) {
|
||||||
self.contactShare = contactShare
|
self.contactShare = contactShare
|
||||||
|
|
||||||
nameLabel.text = contactShare.displayName
|
nameLabel.text = contactShare.displayName
|
||||||
|
|
|
@ -109,7 +109,7 @@ class ContactNameFieldView: UIView {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
public protocol EditContactShareNameViewControllerDelegate: class {
|
public protocol EditContactShareNameViewControllerDelegate: class {
|
||||||
func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: OWSContact)
|
func editContactShareNameView(_ editContactShareNameView: EditContactShareNameViewController, didEditContactShare contactShare: ContactShareViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: -
|
// MARK: -
|
||||||
|
@ -118,7 +118,7 @@ public protocol EditContactShareNameViewControllerDelegate: class {
|
||||||
public class EditContactShareNameViewController: OWSViewController, ContactNameFieldViewDelegate {
|
public class EditContactShareNameViewController: OWSViewController, ContactNameFieldViewDelegate {
|
||||||
weak var delegate: EditContactShareNameViewControllerDelegate?
|
weak var delegate: EditContactShareNameViewControllerDelegate?
|
||||||
|
|
||||||
let contactShare: OWSContact
|
let contactShare: ContactShareViewModel
|
||||||
|
|
||||||
var namePrefixView: ContactNameFieldView!
|
var namePrefixView: ContactNameFieldView!
|
||||||
var givenNameView: ContactNameFieldView!
|
var givenNameView: ContactNameFieldView!
|
||||||
|
@ -136,7 +136,7 @@ public class EditContactShareNameViewController: OWSViewController, ContactNameF
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
required public init(contactShare: OWSContact, delegate: EditContactShareNameViewControllerDelegate) {
|
required public init(contactShare: ContactShareViewModel, delegate: EditContactShareNameViewControllerDelegate) {
|
||||||
self.contactShare = contactShare
|
self.contactShare = contactShare
|
||||||
self.delegate = delegate
|
self.delegate = delegate
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <SignalServiceKit/Contact.h>
|
#import <SignalServiceKit/Contact.h>
|
||||||
|
@ -77,6 +77,9 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
||||||
- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId;
|
- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId;
|
||||||
- (NSString *)stringForConversationTitleWithPhoneIdentifier:(NSString *)recipientId;
|
- (NSString *)stringForConversationTitleWithPhoneIdentifier:(NSString *)recipientId;
|
||||||
|
|
||||||
|
- (nullable UIImage *)systemContactImageForPhoneIdentifier:(nullable NSString *)identifier;
|
||||||
|
- (nullable UIImage *)profileImageForPhoneIdentifier:(nullable NSString *)identifier;
|
||||||
|
|
||||||
- (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier;
|
- (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier;
|
||||||
- (NSAttributedString *)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount font:(UIFont *_Nonnull)font;
|
- (NSAttributedString *)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount font:(UIFont *_Nonnull)font;
|
||||||
- (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font;
|
- (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font;
|
||||||
|
|
|
@ -707,19 +707,32 @@ NSString *const OWSContactsManagerSignalAccountsDidChangeNotification
|
||||||
return [self signalAccountForRecipientId:recipientId] != nil;
|
return [self signalAccountForRecipientId:recipientId] != nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIImage *_Nullable)imageForPhoneIdentifier:(NSString *_Nullable)identifier
|
|
||||||
|
- (UIImage *_Nullable)systemContactImageForPhoneIdentifier:(NSString *_Nullable)identifier
|
||||||
{
|
{
|
||||||
Contact *contact = self.allContactsMap[identifier];
|
Contact *contact = self.allContactsMap[identifier];
|
||||||
if (!contact) {
|
if (!contact) {
|
||||||
|
// If we haven't loaded system contacts yet, we may have a cached
|
||||||
|
// copy in the db
|
||||||
contact = [self signalAccountForRecipientId:identifier].contact;
|
contact = [self signalAccountForRecipientId:identifier].contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return contact.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable UIImage *)profileImageForPhoneIdentifier:(nullable NSString *)identifier
|
||||||
|
{
|
||||||
|
return [self.profileManager profileAvatarForRecipientId:identifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *_Nullable)imageForPhoneIdentifier:(NSString *_Nullable)identifier
|
||||||
|
{
|
||||||
// Prefer the contact image from the local address book if available
|
// Prefer the contact image from the local address book if available
|
||||||
UIImage *_Nullable image = contact.image;
|
UIImage *_Nullable image = [self systemContactImageForPhoneIdentifier:identifier];
|
||||||
|
|
||||||
// Else try to use the image from their profile
|
// Else try to use the image from their profile
|
||||||
if (image == nil) {
|
if (image == nil) {
|
||||||
image = [self.profileManager profileAvatarForRecipientId:identifier];
|
image = [self profileImageForPhoneIdentifier:identifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
|
|
|
@ -43,16 +43,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly) NSArray<NSString *> *recipientIdentifiers;
|
@property (nonatomic, readonly) NSArray<NSString *> *recipientIdentifiers;
|
||||||
|
|
||||||
#if TARGET_OS_IOS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the image representing the thread. Nil if not available.
|
|
||||||
*
|
|
||||||
* @return UIImage of the thread, or nil.
|
|
||||||
*/
|
|
||||||
- (nullable UIImage *)image;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma mark Interactions
|
#pragma mark Interactions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -120,15 +120,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
return [[TextSecureKitEnv sharedEnv].contactsManager displayNameForPhoneIdentifier:self.contactIdentifier];
|
return [[TextSecureKitEnv sharedEnv].contactsManager displayNameForPhoneIdentifier:self.contactIdentifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
|
|
||||||
- (nullable UIImage *)image
|
|
||||||
{
|
|
||||||
UIImage *image = [[TextSecureKitEnv sharedEnv].contactsManager imageForPhoneIdentifier:self.contactIdentifier];
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ (NSString *)threadIdFromContactId:(NSString *)contactId {
|
+ (NSString *)threadIdFromContactId:(NSString *)contactId {
|
||||||
return [TSContactThreadPrefix stringByAppendingString:contactId];
|
return [TSContactThreadPrefix stringByAppendingString:contactId];
|
||||||
|
|
|
@ -112,10 +112,9 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value);
|
||||||
@property (nonatomic, readonly) NSArray<OWSContactEmail *> *emails;
|
@property (nonatomic, readonly) NSArray<OWSContactEmail *> *emails;
|
||||||
@property (nonatomic, readonly) NSArray<OWSContactAddress *> *addresses;
|
@property (nonatomic, readonly) NSArray<OWSContactAddress *> *addresses;
|
||||||
|
|
||||||
// MJK
|
|
||||||
@property (nonatomic, readonly, nullable) NSString *avatarAttachmentId;
|
@property (nonatomic, readonly, nullable) NSString *avatarAttachmentId;
|
||||||
- (nullable TSAttachment *)avatarAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
- (nullable TSAttachment *)avatarAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
- (void)setAvatarAttachmentStream:(TSAttachmentStream *)attachmentStream;
|
- (void)saveAvatarImage:(UIImage *)image transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||||
// "Profile" avatars should _not_ be saved to device contacts.
|
// "Profile" avatars should _not_ be saved to device contacts.
|
||||||
@property (nonatomic, readonly) BOOL isProfileAvatar;
|
@property (nonatomic, readonly) BOOL isProfileAvatar;
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "OWSContact.h"
|
#import "OWSContact.h"
|
||||||
#import "NSString+SSK.h" OWSAttachmentInfo.h
|
#import "MimeTypeUtil.h"
|
||||||
|
#import "NSString+SSK.h"
|
||||||
#import "OWSContact+Private.h"
|
#import "OWSContact+Private.h"
|
||||||
#import "OWSSignalServiceProtos.pb.h"
|
#import "OWSSignalServiceProtos.pb.h"
|
||||||
#import "PhoneNumber.h"
|
#import "PhoneNumber.h"
|
||||||
|
|
||||||
//#import "Contact.h"
|
|
||||||
#import "TSAttachment.h"
|
#import "TSAttachment.h"
|
||||||
#import "TSAttachmentPointer.h"
|
#import "TSAttachmentPointer.h"
|
||||||
#import "TSAttachmentStream.h"
|
#import "TSAttachmentStream.h"
|
||||||
|
@ -459,18 +458,26 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Avatar
|
#pragma mark - Avatar
|
||||||
// MJK
|
|
||||||
|
|
||||||
- (nullable TSAttachment *)avatarAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction
|
- (nullable TSAttachment *)avatarAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||||
{
|
{
|
||||||
return [TSAttachment fetchObjectWithUniqueID:self.avatarAttachmentId transaction:transaction];
|
return [TSAttachment fetchObjectWithUniqueID:self.avatarAttachmentId transaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAvatarAttachmentStream:(TSAttachmentStream *)attachmentStream
|
|
||||||
{
|
|
||||||
OWSAssert([attachmentStream isKindOfClass:[TSAttachmentStream class]]);
|
|
||||||
OWSAssert(self.avatarAttachmentId == nil);
|
|
||||||
|
|
||||||
|
- (void)saveAvatarImage:(UIImage *)image transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||||
|
{
|
||||||
|
NSData *imageData = UIImageJPEGRepresentation(image, (CGFloat)0.9);
|
||||||
|
|
||||||
|
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:OWSMimeTypeImageJpeg
|
||||||
|
byteCount:imageData.length
|
||||||
|
sourceFilename:nil];
|
||||||
|
|
||||||
|
NSError *error;
|
||||||
|
BOOL success = [attachmentStream writeData:imageData error:&error];
|
||||||
|
OWSAssert(success && !error);
|
||||||
|
|
||||||
|
[attachmentStream saveWithTransaction:transaction];
|
||||||
self.avatarAttachmentId = attachmentStream.uniqueId;
|
self.avatarAttachmentId = attachmentStream.uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
- (nullable TSAttachment *)attachmentWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
- (nullable TSAttachment *)attachmentWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
||||||
- (void)setQuotedMessageThumbnailAttachmentStream:(TSAttachmentStream *)attachmentStream;
|
- (void)setQuotedMessageThumbnailAttachmentStream:(TSAttachmentStream *)attachmentStream;
|
||||||
- (void)setContactShareAvatarAttachmentStream:(TSAttachmentStream *)attachmentStream;
|
|
||||||
|
|
||||||
- (BOOL)shouldStartExpireTimer;
|
- (BOOL)shouldStartExpireTimer;
|
||||||
- (BOOL)shouldStartExpireTimerWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
- (BOOL)shouldStartExpireTimerWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
|
@ -332,13 +332,6 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
|
||||||
[self.quotedMessage setThumbnailAttachmentStream:attachmentStream];
|
[self.quotedMessage setThumbnailAttachmentStream:attachmentStream];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setContactShareAvatarAttachmentStream:(TSAttachmentStream *)attachmentStream
|
|
||||||
{
|
|
||||||
OWSAssert(self.contactShare);
|
|
||||||
|
|
||||||
[self.contactShare setAvatarAttachmentStream:attachmentStream];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Update With... Methods
|
#pragma mark - Update With... Methods
|
||||||
|
|
||||||
- (void)updateWithExpireStartedAt:(uint64_t)expireStartedAt transaction:(YapDatabaseReadWriteTransaction *)transaction
|
- (void)updateWithExpireStartedAt:(uint64_t)expireStartedAt transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||||
|
|
|
@ -314,11 +314,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||||
[message.quotedMessage createThumbnailAttachmentsIfNecessaryWithTransaction:transaction];
|
[message.quotedMessage createThumbnailAttachmentsIfNecessaryWithTransaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
// MJK TODO - don't generate the avatar attachment until here, when we've committed to sending it.
|
|
||||||
if (message.contactShare.avatarAttachmentId != nil) {
|
if (message.contactShare.avatarAttachmentId != nil) {
|
||||||
// contactShareAvatarAttachment = [message.contactShare
|
|
||||||
// createAvatarForUploadWithTransaction:transaction];
|
|
||||||
// TODO generate and save the attachment for upload here.
|
|
||||||
TSAttachment *avatarAttachment = [message.contactShare avatarAttachmentWithTransaction:transaction];
|
TSAttachment *avatarAttachment = [message.contactShare avatarAttachmentWithTransaction:transaction];
|
||||||
if ([avatarAttachment isKindOfClass:[TSAttachmentStream class]]) {
|
if ([avatarAttachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||||
contactShareAvatarAttachment = (TSAttachmentStream *)avatarAttachment;
|
contactShareAvatarAttachment = (TSAttachmentStream *)avatarAttachment;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
@class Contact;
|
@class Contact;
|
||||||
|
@ -12,8 +12,4 @@
|
||||||
- (NSString * _Nonnull)displayNameForPhoneIdentifier:(NSString * _Nullable)phoneNumber;
|
- (NSString * _Nonnull)displayNameForPhoneIdentifier:(NSString * _Nullable)phoneNumber;
|
||||||
- (NSArray<SignalAccount *> * _Nonnull)signalAccounts;
|
- (NSArray<SignalAccount *> * _Nonnull)signalAccounts;
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
- (UIImage * _Nullable)imageForPhoneIdentifier:(NSString * _Nullable)phoneNumber;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in a new issue