Merge branch 'release/2.28.1'

pull/1/head
Matthew Chen 6 years ago
commit 9b45a15c35

@ -186,7 +186,6 @@
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; }; 34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; };
34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */; }; 34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */; };
34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */; }; 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */; };
34B3F8781E8DF1700035BE1A /* ContactsPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */; };
34B3F87B1E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */; }; 34B3F87B1E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */; };
34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */; }; 34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */; };
34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */; }; 34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */; };
@ -832,7 +831,6 @@
34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AttachmentSharing.m; sourceTree = "<group>"; }; 34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AttachmentSharing.m; sourceTree = "<group>"; };
34B3F83B1E8DF1700035BE1A /* CallViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = "<group>"; }; 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = "<group>"; };
34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPicker.swift; sourceTree = "<group>"; }; 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPicker.swift; sourceTree = "<group>"; };
34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContactsPicker.xib; sourceTree = "<group>"; };
34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExperienceUpgradesPageViewController.swift; sourceTree = "<group>"; }; 34B3F8441E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExperienceUpgradesPageViewController.swift; sourceTree = "<group>"; };
34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteFlow.swift; sourceTree = "<group>"; }; 34B3F84C1E8DF1700035BE1A /* InviteFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteFlow.swift; sourceTree = "<group>"; };
34B3F84F1E8DF1700035BE1A /* NewContactThreadViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewContactThreadViewController.h; sourceTree = "<group>"; }; 34B3F84F1E8DF1700035BE1A /* NewContactThreadViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewContactThreadViewController.h; sourceTree = "<group>"; };
@ -1754,7 +1752,6 @@
34B3F83B1E8DF1700035BE1A /* CallViewController.swift */, 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */,
348BB25C20A0C5530047AEC2 /* ContactShareViewHelper.swift */, 348BB25C20A0C5530047AEC2 /* ContactShareViewHelper.swift */,
34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */, 34B3F83E1E8DF1700035BE1A /* ContactsPicker.swift */,
34B3F83F1E8DF1700035BE1A /* ContactsPicker.xib */,
34E88D252098C5AE00A608F4 /* ContactViewController.swift */, 34E88D252098C5AE00A608F4 /* ContactViewController.swift */,
3448BFC01EDF0EA7005B2D69 /* ConversationView */, 3448BFC01EDF0EA7005B2D69 /* ConversationView */,
346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */, 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */,
@ -2849,7 +2846,6 @@
AD83FF431A73426500B5C81A /* audio_play_button@2x.png in Resources */, AD83FF431A73426500B5C81A /* audio_play_button@2x.png in Resources */,
34661FB820C1C0D60056EDD6 /* message_sent.aiff in Resources */, 34661FB820C1C0D60056EDD6 /* message_sent.aiff in Resources */,
45CB2FA81CB7146C00E1B343 /* Launch Screen.storyboard in Resources */, 45CB2FA81CB7146C00E1B343 /* Launch Screen.storyboard in Resources */,
34B3F8781E8DF1700035BE1A /* ContactsPicker.xib in Resources */,
B633C5C31A1D190B0059AC12 /* mute_off@2x.png in Resources */, B633C5C31A1D190B0059AC12 /* mute_off@2x.png in Resources */,
AD83FF411A73426500B5C81A /* audio_play_button_blue@2x.png in Resources */, AD83FF411A73426500B5C81A /* audio_play_button_blue@2x.png in Resources */,
34C3C78D20409F320000134C /* Opening.m4r in Resources */, 34C3C78D20409F320000134C /* Opening.m4r in Resources */,

@ -21,7 +21,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.28.0</string> <string>2.28.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@ -38,7 +38,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2.28.0.15</string> <string>2.28.1.1</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LOGS_EMAIL</key> <key>LOGS_EMAIL</key>

@ -40,9 +40,8 @@ NS_ASSUME_NONNULL_BEGIN
_tableViewController = [OWSTableViewController new]; _tableViewController = [OWSTableViewController new];
[self.view addSubview:self.tableViewController.view]; [self.view addSubview:self.tableViewController.view];
[_tableViewController.view autoPinWidthToSuperview]; [self addChildViewController:self.tableViewController];
[_tableViewController.view autoPinToTopLayoutGuideOfViewController:self withInset:0]; [_tableViewController.view autoPinEdgesToSuperviewEdges];
[_tableViewController.view autoPinEdgeToSuperviewEdge:ALEdgeBottom];
self.tableViewController.tableView.rowHeight = UITableViewAutomaticDimension; self.tableViewController.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableViewController.tableView.estimatedRowHeight = 60; self.tableViewController.tableView.estimatedRowHeight = 60;

@ -28,12 +28,11 @@ public enum SubtitleCellValue: Int {
@objc @objc
public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate { public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
@IBOutlet var tableView: UITableView! var tableView: UITableView!
@IBOutlet var searchBar: UISearchBar! var searchBar: UISearchBar!
// MARK: - Properties // MARK: - Properties
private let TAG = "[ContactsPicker]"
private let contactCellReuseIdentifier = "contactCellReuseIdentifier" private let contactCellReuseIdentifier = "contactCellReuseIdentifier"
private var contactsManager: OWSContactsManager { private var contactsManager: OWSContactsManager {
@ -84,7 +83,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
required public init(allowsMultipleSelection: Bool, subtitleCellType: SubtitleCellValue) { required public init(allowsMultipleSelection: Bool, subtitleCellType: SubtitleCellValue) {
self.allowsMultipleSelection = allowsMultipleSelection self.allowsMultipleSelection = allowsMultipleSelection
self.subtitleCellType = subtitleCellType self.subtitleCellType = subtitleCellType
super.init(nibName: "ContactsPicker", bundle: nil) super.init(nibName: nil, bundle: nil)
} }
required public init?(coder aDecoder: NSCoder) { required public init?(coder aDecoder: NSCoder) {
@ -93,6 +92,26 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
// MARK: - Lifecycle Methods // MARK: - Lifecycle Methods
override public func loadView() {
self.view = UIView()
let tableView = UITableView()
self.tableView = tableView
view.addSubview(tableView)
tableView.autoPinEdgesToSuperviewEdges()
tableView.delegate = self
tableView.dataSource = self
let searchBar = UISearchBar()
self.searchBar = searchBar
searchBar.searchBarStyle = .minimal
searchBar.delegate = self
searchBar.backgroundColor = .white
searchBar.sizeToFit()
tableView.tableHeaderView = searchBar
}
override open func viewDidLoad() { override open func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -102,8 +121,6 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
self.searchBar.backgroundColor = Theme.backgroundColor self.searchBar.backgroundColor = Theme.backgroundColor
self.searchBar.barStyle = Theme.barStyle() self.searchBar.barStyle = Theme.barStyle()
searchBar.placeholder = NSLocalizedString("INVITE_FRIENDS_PICKER_SEARCHBAR_PLACEHOLDER", comment: "Search") searchBar.placeholder = NSLocalizedString("INVITE_FRIENDS_PICKER_SEARCHBAR_PLACEHOLDER", comment: "Search")
// Prevent content from going under the navigation bar
self.edgesForExtendedLayout = []
// Auto size cells for dynamic type // Auto size cells for dynamic type
tableView.estimatedRowHeight = 60.0 tableView.estimatedRowHeight = 60.0
@ -145,7 +162,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
private func reloadContacts() { private func reloadContacts() {
getContacts( onError: { error in getContacts( onError: { error in
Logger.error("\(self.TAG) failed to reload contacts with error:\(error)") Logger.error("\(self.logTag) failed to reload contacts with error:\(error)")
}) })
} }
@ -197,7 +214,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
} }
self.sections = collatedContacts(contacts) self.sections = collatedContacts(contacts)
} catch let error as NSError { } catch let error as NSError {
Logger.error("\(self.TAG) Failed to fetch contacts with error:\(error)") Logger.error("\(self.logTag) Failed to fetch contacts with error:\(error)")
} }
} }
} }
@ -336,7 +353,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
let filteredContacts = try contactStore.unifiedContacts(matching: predicate, keysToFetch: allowedContactKeys) let filteredContacts = try contactStore.unifiedContacts(matching: predicate, keysToFetch: allowedContactKeys)
filteredSections = collatedContacts(filteredContacts) filteredSections = collatedContacts(filteredContacts)
} catch let error as NSError { } catch let error as NSError {
Logger.error("\(self.TAG) updating search results failed with error: \(error)") Logger.error("\(self.logTag) updating search results failed with error: \(error)")
} }
} }
self.tableView.reloadData() self.tableView.reloadData()

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ContactsPicker" customModule="Signal" customModuleProvider="target">
<connections>
<outlet property="searchBar" destination="4gV-1B-8Mf" id="QBY-fF-wiP"/>
<outlet property="tableView" destination="oaw-nZ-Bd3" id="ovH-CY-TEZ"/>
<outlet property="view" destination="iN0-l3-epB" id="SV2-9h-0H0"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="375" height="603"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="oaw-nZ-Bd3">
<rect key="frame" x="0.0" y="44" width="375" height="559"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="dataSource" destination="-1" id="2Ke-sU-HF0"/>
<outlet property="delegate" destination="-1" id="yc6-lh-qbW"/>
</connections>
</tableView>
<searchBar contentMode="redraw" translatesAutoresizingMaskIntoConstraints="NO" id="4gV-1B-8Mf">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="fOA-ib-HG5"/>
</constraints>
<textInputTraits key="textInputTraits"/>
<connections>
<outlet property="delegate" destination="-1" id="xC3-pC-pNH"/>
</connections>
</searchBar>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="oaw-nZ-Bd3" firstAttribute="top" secondItem="4gV-1B-8Mf" secondAttribute="bottom" id="6xt-kc-7P8"/>
<constraint firstItem="4gV-1B-8Mf" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="topMargin" id="EXL-NQ-glZ"/>
<constraint firstItem="4gV-1B-8Mf" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Yep-bF-mvk"/>
<constraint firstItem="oaw-nZ-Bd3" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="oKu-gT-NC6"/>
<constraint firstAttribute="bottom" secondItem="oaw-nZ-Bd3" secondAttribute="bottom" id="ptG-2s-ieJ"/>
<constraint firstAttribute="trailing" secondItem="oaw-nZ-Bd3" secondAttribute="trailing" id="sB4-4w-vGM"/>
<constraint firstAttribute="trailing" secondItem="4gV-1B-8Mf" secondAttribute="trailing" id="w2q-bS-FII"/>
</constraints>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" translucent="NO" prompted="NO"/>
<point key="canvasLocation" x="-209.5" y="88.5"/>
</view>
</objects>
</document>

@ -228,29 +228,6 @@ NS_ASSUME_NONNULL_BEGIN
// Measure the actual current width, to be safe. // Measure the actual current width, to be safe.
CGFloat timestampLabelWidth = [self.timestampLabel sizeThatFits:CGSizeZero].width; CGFloat timestampLabelWidth = [self.timestampLabel sizeThatFits:CGSizeZero].width;
// Measuring the timestamp label's width is non-trivial since its
// contents can be relative the current time. We avoid having
// message bubbles' "visually vibrate" as their timestamp labels
// vary in width. So we try to leave enough space for all possible
// contents of this label _for the first hour of its lifetime_, when
// the timestamp is particularly volatile.
if ([DateUtil isTimestampFromLastHour:viewItem.interaction.timestamp]) {
// Measure the "now" case.
self.timestampLabel.text = [DateUtil exemplaryNowTimeFormat];
timestampLabelWidth = MAX(timestampLabelWidth, [self.timestampLabel sizeThatFits:CGSizeZero].width);
// Measure the "relative time" case.
// Since this case varies with time, we multiply to leave
// space for the worst case (whose exact value, due to localization,
// is unpredictable).
self.timestampLabel.text = [DateUtil exemplaryMinutesTimeFormat];
timestampLabelWidth = MAX(timestampLabelWidth,
[self.timestampLabel sizeThatFits:CGSizeZero].width + self.timestampLabel.font.lineHeight * 0.5f);
// Re-configure the labels with the current appropriate value in case
// we are configuring this view for display.
[self configureLabelsWithConversationViewItem:viewItem];
}
result.width = timestampLabelWidth; result.width = timestampLabelWidth;
if (viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) { if (viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
if (![self isFailedOutgoingMessage:viewItem]) { if (![self isFailedOutgoingMessage:viewItem]) {

@ -7,6 +7,14 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface OWSMessageTextView ()
@property (nonatomic, nullable) NSValue *cachedSize;
@end
#pragma mark -
@implementation OWSMessageTextView @implementation OWSMessageTextView
// Our message text views are never used for editing; // Our message text views are never used for editing;
@ -61,6 +69,61 @@ NS_ASSUME_NONNULL_BEGIN
return result; return result;
} }
- (void)setText:(nullable NSString *)text
{
if ([NSObject isNullableObject:text equalTo:self.text]) {
return;
}
[super setText:text];
self.cachedSize = nil;
}
- (void)setAttributedText:(nullable NSAttributedString *)attributedText
{
if ([NSObject isNullableObject:attributedText equalTo:self.attributedText]) {
return;
}
[super setAttributedText:attributedText];
self.cachedSize = nil;
}
- (void)setTextColor:(nullable UIColor *)textColor
{
if ([NSObject isNullableObject:textColor equalTo:self.textColor]) {
return;
}
[super setTextColor:textColor];
// No need to clear cached size here.
}
- (void)setFont:(nullable UIFont *)font
{
if ([NSObject isNullableObject:font equalTo:self.font]) {
return;
}
[super setFont:font];
self.cachedSize = nil;
}
- (void)setLinkTextAttributes:(nullable NSDictionary<NSString *, id> *)linkTextAttributes
{
if ([NSObject isNullableObject:linkTextAttributes equalTo:self.linkTextAttributes]) {
return;
}
[super setLinkTextAttributes:linkTextAttributes];
self.cachedSize = nil;
}
- (CGSize)sizeThatFits:(CGSize)size
{
if (self.cachedSize) {
return self.cachedSize.CGSizeValue;
}
CGSize result = [super sizeThatFits:size];
self.cachedSize = [NSValue valueWithCGSize:result];
return result;
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -234,6 +234,7 @@ typedef enum : NSUInteger {
@property (nonatomic) ContactShareViewHelper *contactShareViewHelper; @property (nonatomic) ContactShareViewHelper *contactShareViewHelper;
@property (nonatomic) NSTimer *reloadTimer; @property (nonatomic) NSTimer *reloadTimer;
@property (nonatomic, nullable) NSDate *lastReloadDate; @property (nonatomic, nullable) NSDate *lastReloadDate;
@property (nonatomic, nullable) NSDate *collapseCutoffDate;
@end @end
@ -713,6 +714,8 @@ typedef enum : NSUInteger {
[self updateBarButtonItems]; [self updateBarButtonItems];
[self updateNavigationTitle]; [self updateNavigationTitle];
[self resetContentAndLayout];
// We want to set the initial scroll state the first time we enter the view. // We want to set the initial scroll state the first time we enter the view.
if (!self.viewHasEverAppeared) { if (!self.viewHasEverAppeared) {
[self scrollToDefaultPosition]; [self scrollToDefaultPosition];
@ -809,9 +812,10 @@ typedef enum : NSUInteger {
- (void)resetContentAndLayout - (void)resetContentAndLayout
{ {
// Avoid layout corrupt issues and out-of-date message subtitles. // Avoid layout corrupt issues and out-of-date message subtitles.
self.lastReloadDate = [NSDate new];
[self reloadViewItems];
[self.collectionView.collectionViewLayout invalidateLayout]; [self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView reloadData]; [self.collectionView reloadData];
self.lastReloadDate = [NSDate new];
} }
- (void)setUserHasScrolled:(BOOL)userHasScrolled - (void)setUserHasScrolled:(BOOL)userHasScrolled
@ -3370,10 +3374,9 @@ typedef enum : NSUInteger {
// These errors seems to be very rare; they can only be reproduced // These errors seems to be very rare; they can only be reproduced
// using the more extreme actions in the debug UI. // using the more extreme actions in the debug UI.
OWSProdLogAndFail(@"%@ hasMalformedRowChange", self.logTag); OWSProdLogAndFail(@"%@ hasMalformedRowChange", self.logTag);
[self reloadViewItems]; [self resetContentAndLayout];
[self.collectionView reloadData];
self.lastReloadDate = [NSDate new];
[self updateLastVisibleTimestamp]; [self updateLastVisibleTimestamp];
[self scrollToBottomAnimated:NO];
return; return;
} }
@ -4346,8 +4349,7 @@ typedef enum : NSUInteger {
{ {
[self.conversationStyle updateProperties]; [self.conversationStyle updateProperties];
[self.headerView updateAvatar]; [self.headerView updateAvatar];
[self.collectionView reloadData]; [self resetContentAndLayout];
self.lastReloadDate = [NSDate new];
} }
- (void)groupWasUpdated:(TSGroupModel *)groupModel - (void)groupWasUpdated:(TSGroupModel *)groupModel
@ -4814,6 +4816,8 @@ typedef enum : NSUInteger {
// cell view models. // cell view models.
- (void)reloadViewItems - (void)reloadViewItems
{ {
self.collapseCutoffDate = [NSDate new];
NSMutableArray<ConversationViewItem *> *viewItems = [NSMutableArray new]; NSMutableArray<ConversationViewItem *> *viewItems = [NSMutableArray new];
NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache = [NSMutableDictionary new]; NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache = [NSMutableDictionary new];
@ -4858,6 +4862,8 @@ typedef enum : NSUInteger {
BOOL shouldShowDateOnNextViewItem = YES; BOOL shouldShowDateOnNextViewItem = YES;
uint64_t previousViewItemTimestamp = 0; uint64_t previousViewItemTimestamp = 0;
OWSUnreadIndicator *_Nullable unreadIndicator = self.dynamicInteractions.unreadIndicator; OWSUnreadIndicator *_Nullable unreadIndicator = self.dynamicInteractions.unreadIndicator;
uint64_t collapseCutoffTimestamp = [NSDate ows_millisecondsSince1970ForDate:self.collapseCutoffDate];
BOOL hasPlacedUnreadIndicator = NO; BOOL hasPlacedUnreadIndicator = NO;
for (ConversationViewItem *viewItem in viewItems) { for (ConversationViewItem *viewItem in viewItems) {
BOOL canShowDate = NO; BOOL canShowDate = NO;
@ -5067,6 +5073,10 @@ typedef enum : NSUInteger {
} }
} }
if (viewItem.interaction.timestampForSorting > collapseCutoffTimestamp) {
shouldHideFooter = NO;
}
viewItem.isFirstInCluster = isFirstInCluster; viewItem.isFirstInCluster = isFirstInCluster;
viewItem.isLastInCluster = isLastInCluster; viewItem.isLastInCluster = isLastInCluster;
viewItem.shouldShowSenderAvatar = shouldShowSenderAvatar; viewItem.shouldShowSenderAvatar = shouldShowSenderAvatar;

@ -259,14 +259,20 @@ static NSString *const DATE_FORMAT_WEEKDAY = @"EEEE";
+ (NSString *)formatDateShort:(NSDate *)date + (NSString *)formatDateShort:(NSDate *)date
{ {
OWSAssertIsOnMainThread();
OWSAssert(date); OWSAssert(date);
NSDate *now = [NSDate date];
NSInteger dayDifference = [self daysFromFirstDate:date toSecondDate:now];
BOOL dateIsOlderThanToday = dayDifference > 0;
BOOL dateIsOlderThanOneWeek = dayDifference > 6;
NSString *dateTimeString; NSString *dateTimeString;
if (![DateUtil dateIsThisYear:date]) { if (![DateUtil dateIsThisYear:date]) {
dateTimeString = [[DateUtil dateFormatter] stringFromDate:date]; dateTimeString = [[DateUtil dateFormatter] stringFromDate:date];
} else if ([DateUtil dateIsOlderThanOneWeek:date]) { } else if (dateIsOlderThanOneWeek) {
dateTimeString = [[DateUtil monthAndDayFormatter] stringFromDate:date]; dateTimeString = [[DateUtil monthAndDayFormatter] stringFromDate:date];
} else if ([DateUtil dateIsOlderThanToday:date]) { } else if (dateIsOlderThanToday) {
dateTimeString = [[DateUtil shortDayOfWeekFormatter] stringFromDate:date]; dateTimeString = [[DateUtil shortDayOfWeekFormatter] stringFromDate:date];
} else { } else {
dateTimeString = [[DateUtil timeFormatter] stringFromDate:date]; dateTimeString = [[DateUtil timeFormatter] stringFromDate:date];

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>XPC!</string> <string>XPC!</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.28.0</string> <string>2.28.1</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2.28.0.15</string> <string>2.28.1.1</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>

Loading…
Cancel
Save