Merge branch 'hotfix/2.25.2'

pull/1/head
Matthew Chen 7 years ago
commit 08affb4400

@ -48,6 +48,13 @@
[informationSection addItem:[OWSTableItem labelItemWithText:NSLocalizedString(@"SETTINGS_VERSION", @"")
accessoryText:[[[NSBundle mainBundle] infoDictionary]
objectForKey:@"CFBundleVersion"]]];
[informationSection addItem:[OWSTableItem disclosureItemWithText:NSLocalizedString(@"SETTINGS_LEGAL_TERMS_CELL",
@"table cell label")
actionBlock:^{
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:kLegalTermsUrlString]];
}]];
[contents addSection:informationSection];
OWSTableSection *helpSection = [OWSTableSection new];

@ -72,42 +72,54 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
UIView *headerWrapper = [UIView containerView];
[self.view addSubview:headerWrapper];
headerWrapper.backgroundColor = UIColor.ows_signalBrandBlueColor;
UIView *headerContent = [UIView new];
[headerWrapper addSubview:headerContent];
[headerWrapper autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeBottom];
[headerContent autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[headerContent autoPinToTopLayoutGuideOfViewController:self withInset:0];
[headerContent autoPinWidthToSuperview];
UILabel *headerLabel = [UILabel new];
headerLabel.text = NSLocalizedString(@"REGISTRATION_TITLE_LABEL", @"");
headerLabel.textColor = [UIColor whiteColor];
headerLabel.font = [UIFont ows_mediumFontWithSize:ScaleFromIPhone5To7Plus(20.f, 24.f)];
[headerContent addSubview:headerLabel];
[headerLabel autoHCenterInSuperview];
[headerLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:14.f];
CGFloat screenHeight = MAX([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
if (screenHeight < 568) {
// iPhone 4s or smaller.
[headerContent autoSetDimension:ALDimensionHeight toSize:20];
headerLabel.hidden = YES;
} else if (screenHeight < 667) {
// iPhone 5 or smaller.
[headerContent autoSetDimension:ALDimensionHeight toSize:80];
} else {
[headerContent autoSetDimension:ALDimensionHeight toSize:220];
UIImage *logo = [UIImage imageNamed:@"logoSignal"];
OWSAssert(logo);
UIImageView *logoView = [UIImageView new];
logoView.image = logo;
[headerContent addSubview:logoView];
[logoView autoHCenterInSuperview];
[logoView autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:headerLabel withOffset:-14.f];
NSString *legalTopMatterFormat = NSLocalizedString(@"REGISTRATION_LEGAL_TOP_MATTER_FORMAT",
@"legal disclaimer, embeds a tappable {{link title}} which is styled as a hyperlink");
NSString *legalTopMatterLinkWord = NSLocalizedString(
@"REGISTRATION_LEGAL_TOP_MATTER_LINK_TITLE", @"embedded in legal topmatter, styled as a link");
NSString *legalTopMatter = [NSString stringWithFormat:legalTopMatterFormat, legalTopMatterLinkWord];
NSMutableAttributedString *attributedLegalTopMatter =
[[NSMutableAttributedString alloc] initWithString:legalTopMatter];
NSRange linkRange = [legalTopMatter rangeOfString:legalTopMatterLinkWord];
NSDictionary *linkStyleAttributes = @{
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid),
};
[attributedLegalTopMatter setAttributes:linkStyleAttributes range:linkRange];
UILabel *legalTopMatterLabel = [UILabel new];
legalTopMatterLabel.textColor = UIColor.whiteColor;
legalTopMatterLabel.font = UIFont.ows_dynamicTypeFootnoteFont;
legalTopMatterLabel.numberOfLines = 0;
legalTopMatterLabel.textAlignment = NSTextAlignmentCenter;
legalTopMatterLabel.attributedText = attributedLegalTopMatter;
legalTopMatterLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapLegalTerms:)];
[legalTopMatterLabel addGestureRecognizer:tapGesture];
UIStackView *headerContent = [[UIStackView alloc] initWithArrangedSubviews:@[ headerLabel, legalTopMatterLabel ]];
headerContent.axis = UILayoutConstraintAxisVertical;
headerContent.alignment = UIStackViewAlignmentCenter;
headerContent.spacing = ScaleFromIPhone5To7Plus(8, 16);
headerContent.layoutMarginsRelativeArrangement = YES;
{
CGFloat topMargin = ScaleFromIPhone5To7Plus(4, 16);
CGFloat bottomMargin = ScaleFromIPhone5To7Plus(8, 16);
headerContent.layoutMargins = UIEdgeInsetsMake(topMargin, 40, bottomMargin, 40);
}
[headerWrapper addSubview:headerContent];
[headerContent autoPinToTopLayoutGuideOfViewController:self withInset:0];
[headerContent autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeTop];
const CGFloat kRowHeight = 60.f;
const CGFloat kRowHMargin = 20.f;
const CGFloat kSeparatorHeight = 1.f;
@ -231,6 +243,25 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
[spinnerView autoSetDimension:ALDimensionHeight toSize:20.f];
[spinnerView autoPinTrailingToSuperviewMarginWithInset:20.f];
[spinnerView stopAnimating];
NSString *bottomTermsLinkText = NSLocalizedString(@"REGISTRATION_LEGAL_TERMS_LINK",
@"one line label below submit button on registration screen, which links to an external webpage.");
UIButton *bottomLegalLinkButton = [UIButton new];
bottomLegalLinkButton.titleLabel.font = UIFont.ows_dynamicTypeFootnoteFont;
[bottomLegalLinkButton setTitleColor:UIColor.ows_materialBlueColor forState:UIControlStateNormal];
[bottomLegalLinkButton setTitle:bottomTermsLinkText forState:UIControlStateNormal];
[contentView addSubview:bottomLegalLinkButton];
[bottomLegalLinkButton addTarget:self
action:@selector(didTapLegalTerms:)
forControlEvents:UIControlEventTouchUpInside];
[bottomLegalLinkButton autoPinLeadingAndTrailingToSuperviewMargin];
[bottomLegalLinkButton autoPinEdge:ALEdgeTop
toEdge:ALEdgeBottom
ofView:activateButton
withOffset:ScaleFromIPhone5To7Plus(8, 12)];
[bottomLegalLinkButton setCompressionResistanceHigh];
[bottomLegalLinkButton setContentHuggingHigh];
}
- (void)viewDidAppear:(BOOL)animated
@ -352,6 +383,11 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
}
}
- (void)didTapLegalTerms:(UIButton *)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:kLegalTermsUrlString]];
}
- (void)changeCountryCodeTapped
{
CountryCodeViewController *countryCodeController = [CountryCodeViewController new];

@ -129,7 +129,7 @@ public class MessageRecipientStatusUtils: NSObject {
if outgoingMessage.readRecipientIds().count > 0 {
return (.read, NSLocalizedString("MESSAGE_STATUS_READ", comment: "message footer for read messages"))
}
if outgoingMessage.deliveredRecipientIds().count > 0 {
if outgoingMessage.wasDeliveredToAnyRecipient {
return (.delivered, NSLocalizedString("MESSAGE_STATUS_DELIVERED",
comment: "message status for message delivered to their recipient."))
}

@ -1600,6 +1600,15 @@
/* alert body during registration */
"REGISTRATION_ERROR_BLANK_VERIFICATION_CODE" = "We can't activate your account until you verify the code we sent you.";
/* one line label below submit button on registration screen, which links to an external webpage. */
"REGISTRATION_LEGAL_TERMS_LINK" = "Terms & Privacy Policy";
/* legal disclaimer, embeds a tappable {{link title}} which is styled as a hyperlink */
"REGISTRATION_LEGAL_TOP_MATTER_FORMAT" = "By registering this device, you agree to Signal's %@";
/* embedded in legal topmatter, styled as a link */
"REGISTRATION_LEGAL_TOP_MATTER_LINK_TITLE" = "terms";
/* No comment provided by engineer. */
"REGISTRATION_NON_VALID_NUMBER" = "This phone number format is not supported, please contact support.";
@ -1888,6 +1897,9 @@
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* table cell label */
"SETTINGS_LEGAL_TERMS_CELL" = "Terms & Privacy Policy";
/* Title for settings activity */
"SETTINGS_NAV_BAR_TITLE" = "Settings";

@ -109,6 +109,7 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage;
@property (readonly) TSOutgoingMessageState messageState;
@property (readonly) BOOL wasDeliveredToAnyRecipient;
@property (atomic, readonly) BOOL hasSyncedTranscript;
@property (atomic, readonly) NSString *customMessage;

@ -79,6 +79,10 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
@property (atomic) BOOL isFromLinkedDevice;
@property (atomic) TSGroupMetaMessage groupMetaMessage;
@property (nonatomic, readonly) TSOutgoingMessageState legacyMessageState;
@property (nonatomic, readonly) BOOL legacyWasDelivered;
@property (nonatomic, readonly) BOOL hasLegacyMessageState;
@property (atomic, nullable) NSDictionary<NSString *, TSOutgoingMessageRecipientState *> *recipientStateMap;
@end
@ -116,6 +120,8 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
if (messageStateValue) {
oldMessageState = (TSOutgoingMessageState)messageStateValue.intValue;
}
_hasLegacyMessageState = YES;
_legacyMessageState = oldMessageState;
OWSOutgoingMessageRecipientState defaultState;
switch (oldMessageState) {
@ -140,6 +146,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
NSArray<NSString *> *_Nullable sentRecipients = [coder decodeObjectForKey:@"sentRecipients"];
NSMutableDictionary<NSString *, TSOutgoingMessageRecipientState *> *recipientStateMap = [NSMutableDictionary new];
__block BOOL isGroupThread = NO;
// Our default recipient list is the current thread members.
__block NSArray<NSString *> *recipientIds = @[];
// To avoid deadlock while migrating these records, we use a dedicated
@ -149,12 +156,25 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
// always accurate, so not using the same connection for both reads is
// acceptable.
[TSOutgoingMessage.dbMigrationConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
recipientIds = [[self threadWithTransaction:transaction] recipientIdentifiers];
TSThread *thread = [self threadWithTransaction:transaction];
recipientIds = [thread recipientIdentifiers];
isGroupThread = [thread isGroupThread];
}];
if (sentRecipients) {
NSNumber *_Nullable wasDelivered = [coder decodeObjectForKey:@"wasDelivered"];
_legacyWasDelivered = wasDelivered && wasDelivered.boolValue;
BOOL wasDeliveredToContact = NO;
if (isGroupThread) {
// If we have a `sentRecipients` list, prefer that as it is more accurate.
recipientIds = sentRecipients;
if (sentRecipients) {
recipientIds = sentRecipients;
}
} else {
// Special-case messages in contact threads; if "was delivered", we know
// it was delivered to the contact.
wasDeliveredToContact = _legacyWasDelivered;
}
NSString *_Nullable singleGroupRecipient = [coder decodeObjectForKey:@"singleGroupRecipient"];
if (singleGroupRecipient) {
OWSFail(@"%@ unexpected single group recipient message.", self.logTag);
@ -179,6 +199,11 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
// If we have a delivery timestamp for this recipient, mark it as delivered.
recipientState.state = OWSOutgoingMessageRecipientStateSent;
recipientState.deliveryTimestamp = deliveryTimestamp;
} else if (wasDeliveredToContact) {
OWSAssert(!isGroupThread);
recipientState.state = OWSOutgoingMessageRecipientStateSent;
// Use message time as an estimate of delivery time.
recipientState.deliveryTimestamp = @(self.timestamp);
} else if ([sentRecipients containsObject:recipientId]) {
// If this recipient is in `sentRecipients`, mark it as sent.
recipientState.state = OWSOutgoingMessageRecipientStateSent;
@ -330,7 +355,22 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
- (TSOutgoingMessageState)messageState
{
return [TSOutgoingMessage messageStateForRecipientStates:self.recipientStateMap.allValues];
TSOutgoingMessageState newMessageState =
[TSOutgoingMessage messageStateForRecipientStates:self.recipientStateMap.allValues];
if (self.hasLegacyMessageState) {
if (newMessageState == TSOutgoingMessageStateSent || self.legacyMessageState == TSOutgoingMessageStateSent) {
return TSOutgoingMessageStateSent;
}
}
return newMessageState;
}
- (BOOL)wasDeliveredToAnyRecipient
{
if ([self deliveredRecipientIds].count > 0) {
return YES;
}
return (self.hasLegacyMessageState && self.legacyWasDelivered && self.messageState == TSOutgoingMessageStateSent);
}
+ (TSOutgoingMessageState)messageStateForRecipientStates:(NSArray<TSOutgoingMessageRecipientState *> *)recipientStates
@ -381,16 +421,6 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
[super saveWithTransaction:transaction];
}
- (BOOL)hasSentToAnyRecipient
{
for (TSOutgoingMessageRecipientState *recipientState in self.recipientStateMap.allValues) {
if (recipientState.state == OWSOutgoingMessageRecipientStateSent) {
return YES;
}
}
return NO;
}
- (BOOL)shouldStartExpireTimerWithTransaction:(YapDatabaseReadTransaction *)transaction
{
// It's not clear if we should wait until _all_ recipients have reached "sent or later"
@ -402,8 +432,21 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
if (!self.isExpiringMessage) {
return NO;
} else if (self.messageState == TSOutgoingMessageStateSent) {
return YES;
} else {
return self.hasSentToAnyRecipient;
if (self.expireStartedAt > 0) {
// Our initial migration to populate the recipient state map was incomplete. It's since been
// addressed, but it's possible there are edge cases where a previously sent message would
// no longer be considered sent.
// So here we take extra care not to stop any expiration that had previously started.
// This can also happen under normal cirumstances with an outgoing group message.
DDLogWarn(@"%@ in %s expiration previously started", self.logTag, __PRETTY_FUNCTION__);
return YES;
}
return NO;
}
}

@ -17,6 +17,9 @@ typedef NS_ENUM(NSInteger, TSWhisperMessageType) {
#define textSecureHTTPTimeOut 10
// FIXME this is likely to change
#define kLegalTermsUrlString @"https://signal.org/signal/privacy/"
//#ifndef DEBUG
// Production

Loading…
Cancel
Save