Timer button with duration label

// FREEBIE
This commit is contained in:
Michael Kirk 2018-01-20 11:27:32 -05:00
parent 5c76d4c99c
commit baa312f449
32 changed files with 287 additions and 160 deletions

View File

@ -292,6 +292,7 @@
45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */; };
45BC829D1FD9C4B400011CF3 /* ShareViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BC829C1FD9C4B400011CF3 /* ShareViewDelegate.swift */; };
45BD60821DE9547E00A8F436 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45BD60811DE9547E00A8F436 /* Contacts.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
45BE4EA22012AD2000935E59 /* DisappearingTimerConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4EA12012AD2000935E59 /* DisappearingTimerConfigurationView.swift */; };
45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45C0DC1A1E68FE9000E04C47 /* UIApplication+OWS.swift */; };
45C0DC1E1E69011F00E04C47 /* UIStoryboard+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45C0DC1D1E69011F00E04C47 /* UIStoryboard+OWS.swift */; };
45C9DEB81DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45C9DEB71DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift */; };
@ -831,6 +832,7 @@
45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+featureSupport.swift"; sourceTree = "<group>"; };
45BC829C1FD9C4B400011CF3 /* ShareViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewDelegate.swift; sourceTree = "<group>"; };
45BD60811DE9547E00A8F436 /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; };
45BE4EA12012AD2000935E59 /* DisappearingTimerConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisappearingTimerConfigurationView.swift; sourceTree = "<group>"; };
45C0DC1A1E68FE9000E04C47 /* UIApplication+OWS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+OWS.swift"; sourceTree = "<group>"; };
45C0DC1D1E69011F00E04C47 /* UIStoryboard+OWS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+OWS.swift"; sourceTree = "<group>"; };
45C9DEB71DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebRTCCallMessageHandler.swift; sourceTree = "<group>"; };
@ -1255,6 +1257,7 @@
340CB2221EAC155C0001CAA1 /* ContactsViewHelper.h */,
340CB2231EAC155C0001CAA1 /* ContactsViewHelper.m */,
346129D11FD2085A00532771 /* CommonStrings.swift */,
45BE4EA12012AD2000935E59 /* DisappearingTimerConfigurationView.swift */,
346129CF1FD207F200532771 /* OWSAlerts.swift */,
454A965E1FD60EA2008D2A0E /* OWSFlatButton.swift */,
3400C7971EAFB772008A8584 /* ThreadViewHelper.h */,
@ -2752,6 +2755,7 @@
buildActionMask = 2147483647;
files = (
45194F951FD7216600333B2C /* TSUnreadIndicatorInteraction.m in Sources */,
45BE4EA22012AD2000935E59 /* DisappearingTimerConfigurationView.swift in Sources */,
346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */,
45194F931FD7215C00333B2C /* OWSContactOffersInteraction.m in Sources */,
450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */,

View File

@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "61D54E7EB87D07B55A29BE2A5A7F463A"
BlueprintIdentifier = "B57ACF2237BE640621E2E2CF12637CFE"
BuildableName = "SignalServiceKit.framework"
BlueprintName = "SignalServiceKit"
ReferencedContainer = "container:Pods/Pods.xcodeproj">

View File

@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_timer_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_timer_white@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_timer_white@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

View File

@ -2,17 +2,17 @@
"images" : [
{
"idiom" : "universal",
"filename" : "table_ic_timer.png",
"filename" : "ic_timer.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "table_ic_timer@2x.png",
"filename" : "ic_timer@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "table_ic_timer@3x.png",
"filename" : "ic_timer@3x.png",
"scale" : "3x"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_timer_white.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_timer_white@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_timer_white@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,26 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "table_ic_timer.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "table_ic_timer@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "table_ic_timer@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSSystemMessageCell.h"
@ -154,7 +154,7 @@ NS_ASSUME_NONNULL_BEGIN
result = [UIImage imageNamed:@"system_message_group"];
break;
case TSInfoMessageTypeDisappearingMessagesUpdate:
result = [UIImage imageNamed:@"system_message_timer"];
result = [UIImage imageNamed:@"ic_timer"];
break;
case TSInfoMessageVerificationStateChange:
result = [UIImage imageNamed:@"system_message_verified"];

View File

@ -128,6 +128,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
ContactsViewHelperDelegate,
ContactEditingDelegate,
CNContactViewControllerDelegate,
DisappearingTimerConfigurationViewDelegate,
OWSConversationSettingsViewDelegate,
ConversationViewLayoutDelegate,
ConversationViewCellDelegate,
@ -1240,34 +1241,22 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
}
if (self.disappearingMessagesConfiguration.isEnabled) {
UIButton *timerButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [UIImage imageNamed:@"button_timer_white"];
[timerButton setImage:image forState:UIControlStateNormal];
UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero;
// We normally would want to use left and right insets that ensure the button
// is square and the icon is centered. However UINavigationBar doesn't offer us
// control over the margins and spacing of its content, and the buttons end up
// too far apart and too far from the edge of the screen. So we use a smaller
// right inset tighten up the layout.
imageEdgeInsets.left = round((kBarButtonSize - image.size.width) * 0.5f);
imageEdgeInsets.right = round((kBarButtonSize - (image.size.width + imageEdgeInsets.left)) * 0.5f);
imageEdgeInsets.top = round((kBarButtonSize - image.size.height) * 0.5f);
imageEdgeInsets.bottom = round(kBarButtonSize - (image.size.height + imageEdgeInsets.top));
timerButton.imageEdgeInsets = imageEdgeInsets;
timerButton.accessibilityLabel
= NSLocalizedString(@"DISAPPEARING_MESSAGES_LABEL", @"Accessibility label for disappearing messages");
NSString *formatString = NSLocalizedString(
@"DISAPPEARING_MESSAGES_HINT", @"Accessibility hint that contains current timeout information");
timerButton.accessibilityHint =
[NSString stringWithFormat:formatString, self.disappearingMessagesConfiguration.durationString];
[timerButton addTarget:self
action:@selector(didTapTimerInNavbar:)
forControlEvents:UIControlEventTouchUpInside];
timerButton.frame = CGRectMake(0,
0,
round(image.size.width + imageEdgeInsets.left + imageEdgeInsets.right),
round(image.size.height + imageEdgeInsets.top + imageEdgeInsets.bottom));
[barButtons addObject:[[UIBarButtonItem alloc] initWithCustomView:timerButton]];
DisappearingTimerConfigurationView *timerView = [[DisappearingTimerConfigurationView alloc]
initWithDurationSeconds:self.disappearingMessagesConfiguration.durationSeconds];
timerView.delegate = self;
timerView.tintColor = UIColor.whiteColor;
// As of iOS11, we can size barButton item custom views with autoLayout.
// Before that, though we can still use autoLayout *within* the customView,
// setting the view's size with constraints causes the customView to be temporarily
// laid out with a misplaced origin.
if (@available(iOS 11.0, *)) {
[timerView autoSetDimensionsToSize:CGSizeMake(36, 44)];
} else {
timerView.frame = CGRectMake(0, 0, 36, 44);
}
[barButtons addObject:[[UIBarButtonItem alloc] initWithCustomView:timerView]];
}
self.navigationItem.rightBarButtonItems = [barButtons copy];
@ -1453,7 +1442,9 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
[self.navigationController pushViewController:settingsVC animated:YES];
}
- (void)didTapTimerInNavbar:(id)sender
#pragma mark - DisappearingTimerConfigurationViewDelegate
- (void)disappearingTimerConfigurationViewWasTapped:(DisappearingTimerConfigurationView *)disappearingTimerView
{
DDLogDebug(@"%@ Tapped timer in navbar", self.logTag);
[self showConversationSettings];

View File

@ -343,7 +343,7 @@ NS_ASSUME_NONNULL_BEGIN
[topView autoPinEdgeToSuperviewEdge:ALEdgeTop];
[topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight];
UIImageView *iconView = [strongSelf viewForIconWithName:@"table_ic_timer"];
UIImageView *iconView = [strongSelf viewForIconWithName:@"ic_timer"];
[topView addSubview:iconView];
[iconView autoVCenterInSuperview];
[iconView autoPinLeadingToSuperview];
@ -402,7 +402,7 @@ NS_ASSUME_NONNULL_BEGIN
[topView autoPinEdgeToSuperviewEdge:ALEdgeTop];
[topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight];
UIImageView *iconView = [strongSelf viewForIconWithName:@"table_ic_timer"];
UIImageView *iconView = [strongSelf viewForIconWithName:@"ic_timer"];
[topView addSubview:iconView];
[iconView autoVCenterInSuperview];
[iconView autoPinLeadingToSuperview];
@ -731,11 +731,15 @@ NS_ASSUME_NONNULL_BEGIN
- (UIImageView *)viewForIconWithName:(NSString *)iconName
{
UIImage *icon = [UIImage imageNamed:iconName];
OWSAssert(icon);
UIImageView *iconView = [UIImageView new];
iconView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
iconView.tintColor = [UIColor colorWithRGBHex:0x505050];
iconView.contentMode = UIViewContentModeScaleToFill;
iconView.tintColor = [UIColor ows_blackIconColor];
iconView.contentMode = UIViewContentModeScaleAspectFit;
iconView.layer.minificationFilter = kCAFilterTrilinear;
iconView.layer.magnificationFilter = kCAFilterTrilinear;
[iconView autoSetDimension:ALDimensionWidth toSize:24.f];
[iconView autoSetDimension:ALDimensionHeight toSize:24.f];
return iconView;

View File

@ -1647,15 +1647,27 @@
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ days";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ hours";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutes";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ seconds";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ day";
@ -1671,6 +1683,9 @@
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Cancel";

View File

@ -0,0 +1,134 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public protocol DisappearingTimerConfigurationViewDelegate: class {
func disappearingTimerConfigurationViewWasTapped(_ disappearingTimerView: DisappearingTimerConfigurationView)
}
// DisappearingTimerConfigurationView shows a timer icon and a short label showing the duration
// of disappearing messages for a thread.
//
// If you assign a delegate, it behaves like a button.
@objc
public class DisappearingTimerConfigurationView: UIView {
public weak var delegate: DisappearingTimerConfigurationViewDelegate? {
didSet {
// gesture recognizer is only enabled when a delegate is assigned.
// This lets us use this view as either an interactive button
// or as a non-interactive status indicator
pressGesture.isEnabled = delegate != nil
}
}
override public var frame: CGRect {
didSet {
Logger.verbose("\(logTag) in \(#function): \(oldValue) -> \(frame)")
}
}
override public var bounds: CGRect {
didSet {
Logger.verbose("\(logTag) in \(#function): \(oldValue) -> \(bounds)")
}
}
override public func layoutSubviews() {
let oldFrame = self.frame
super.layoutSubviews()
Logger.verbose("\(logTag) in \(#function). Frame: \(oldFrame) -> \(self.frame)")
}
private let imageView: UIImageView
private let label: UILabel
private var pressGesture: UILongPressGestureRecognizer!
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc
public init(durationSeconds: UInt32) {
self.imageView = UIImageView(image: #imageLiteral(resourceName: "ic_timer"))
imageView.contentMode = .scaleAspectFit
self.label = UILabel()
label.text = OWSDisappearingMessagesConfiguration.string(forDurationSeconds: durationSeconds, useShortFormat: true)
label.font = UIFont.systemFont(ofSize: 10)
label.textColor = UIColor.white
label.textAlignment = .center
label.minimumScaleFactor = 0.5
super.init(frame: CGRect.zero)
applyTintColor(self.tintColor)
// Gesture, simulating button touch up inside
let gesture = UILongPressGestureRecognizer(target: self, action: #selector(pressHandler))
gesture.minimumPressDuration = 0
self.pressGesture = gesture
self.addGestureRecognizer(pressGesture)
// disable gesture recognizer until a delegate is assigned
// this lets us use the UI as either an interactive button
// or as a non-interactive status indicator
pressGesture.isEnabled = false
// Accessability
self.accessibilityLabel = NSLocalizedString("DISAPPEARING_MESSAGES_LABEL", comment: "Accessibility label for disappearing messages")
let hintFormatString = NSLocalizedString("DISAPPEARING_MESSAGES_HINT", comment: "Accessibility hint that contains current timeout information")
let durationString = OWSDisappearingMessagesConfiguration.string(forDurationSeconds: durationSeconds, useShortFormat: false)
self.accessibilityHint = String(format: hintFormatString, durationString)
// Layout
self.addSubview(imageView)
self.addSubview(label)
let kHorizontalPadding: CGFloat = 4
let kVerticalPadding: CGFloat = 6
imageView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: kVerticalPadding, left: kHorizontalPadding, bottom: 0, right: kHorizontalPadding), excludingEdge: .bottom)
label.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 0, left: kHorizontalPadding, bottom: kVerticalPadding, right: kHorizontalPadding), excludingEdge: .top)
label.autoPinEdge(.top, to: .bottom, of: imageView)
}
@objc
func pressHandler(_ gestureRecognizer: UILongPressGestureRecognizer) {
Logger.verbose("\(self.logTag) in \(#function)")
// handle touch down and touch up events separately
if gestureRecognizer.state == .began {
applyTintColor(UIColor.gray)
} else if gestureRecognizer.state == .ended {
applyTintColor(self.tintColor)
let location = gestureRecognizer.location(in: self)
let isTouchUpInside = self.bounds.contains(location)
if (isTouchUpInside) {
// Similar to a UIButton's touch-up-inside
self.delegate?.disappearingTimerConfigurationViewWasTapped(self)
} else {
// Similar to a UIButton's touch-up-outside
// cancel gesture
gestureRecognizer.isEnabled = false
gestureRecognizer.isEnabled = true
}
}
}
override public var tintColor: UIColor! {
didSet {
applyTintColor(tintColor)
}
}
private func applyTintColor(_ color: UIColor) {
imageView.tintColor = color
label.textColor = color
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@ -21,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (class, readonly, nonatomic) UIColor *ows_greenColor;
@property (class, readonly, nonatomic) UIColor *ows_redColor;
@property (class, readonly, nonatomic) UIColor *ows_blackColor;
@property (class, readonly, nonatomic) UIColor *ows_blackIconColor;
@property (class, readonly, nonatomic) UIColor *ows_errorMessageBorderColor;
@property (class, readonly, nonatomic) UIColor *ows_infoMessageBorderColor;
@property (class, readonly, nonatomic) UIColor *ows_inputToolbarBackgroundColor;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSMath.h"
@ -27,6 +27,11 @@ NS_ASSUME_NONNULL_BEGIN
return [UIColor colorWithRed:8.f / 255.f green:10.f / 255.f blue:0. / 255.f alpha:1.f];
}
+ (UIColor *)ows_blackIconColor
{
return [UIColor colorWithRGBHex:0x505050];
}
+ (UIColor *)ows_darkGrayColor
{
return [UIColor colorWithRed:81.f / 255.f green:81.f / 255.f blue:81.f / 255.f alpha:1.f];

View File

@ -217,17 +217,14 @@ NS_ASSUME_NONNULL_BEGIN
}];
if (disappearingMessagesConfiguration && disappearingMessagesConfiguration.isEnabled) {
UIImage *icon = [UIImage imageNamed:@"table_ic_hourglass"];
OWSAssert(icon);
UIImageView *iconView = [UIImageView new];
iconView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
iconView.tintColor = [UIColor colorWithWhite:0.5f alpha:1.f];
iconView.contentMode = UIViewContentModeScaleAspectFit;
// Default size of this icon is a too large for the thread picker context
// so we specify a bit smaller.
iconView.frame = CGRectMake(0, 0, 20, 20);
DisappearingTimerConfigurationView *disappearingTimerConfigurationView =
[[DisappearingTimerConfigurationView alloc]
initWithDurationSeconds:disappearingMessagesConfiguration.durationSeconds];
cell.accessoryView = iconView;
disappearingTimerConfigurationView.frame = CGRectMake(0, 0, 44, 44);
disappearingTimerConfigurationView.tintColor = [UIColor colorWithWhite:0.5f alpha:1.f];
cell.accessoryView = disappearingTimerConfigurationView;
}
}

View File

@ -1,5 +1,6 @@
// Created by Michael Kirk on 9/23/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSYapDatabaseObject.h"
@ -24,7 +25,7 @@ extern const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDurat
+ (NSArray<NSNumber *> *)validDurationsSeconds;
+ (NSString *)stringForDurationSeconds:(uint32_t)durationSeconds;
+ (NSString *)stringForDurationSeconds:(uint32_t)durationSeconds useShortFormat:(BOOL)useShortFormat;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSDisappearingMessagesConfiguration.h"
@ -62,7 +62,7 @@ const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDuration = k
}
}
+ (NSString *)stringForDurationSeconds:(uint32_t)durationSeconds
+ (NSString *)stringForDurationSeconds:(uint32_t)durationSeconds useShortFormat:(BOOL)useShortFormat
{
NSString *amountFormat;
uint32_t duration;
@ -73,55 +73,101 @@ const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDuration = k
uint32_t secondsPerWeek = secondsPerDay * 7;
if (durationSeconds < secondsPerMinute) { // XX Seconds
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SECONDS",
@"{{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SECONDS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SECONDS",
@"{{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds;
} else if (durationSeconds < secondsPerMinute * 1.5) { // 1 Minute
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_MINUTE",
@"{{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_MINUTES_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_MINUTE",
@"{{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerMinute;
} else if (durationSeconds < secondsPerHour) { // Multiple Minutes
amountFormat = NSLocalizedString(@"TIME_AMOUNT_MINUTES",
@"{{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_MINUTES_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_MINUTES",
@"{{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerMinute;
} else if (durationSeconds < secondsPerHour * 1.5) { // 1 Hour
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_HOUR",
@"{{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_HOURS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_HOUR",
@"{{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerHour;
} else if (durationSeconds < secondsPerDay) { // Multiple Hours
amountFormat = NSLocalizedString(@"TIME_AMOUNT_HOURS",
@"{{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_HOURS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_HOURS",
@"{{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerHour;
} else if (durationSeconds < secondsPerDay * 1.5) { // 1 Day
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_DAY",
@"{{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 day}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_DAYS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_DAY",
@"{{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 day}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerDay;
} else if (durationSeconds < secondsPerWeek) { // Multiple Days
amountFormat = NSLocalizedString(@"TIME_AMOUNT_DAYS",
@"{{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 days}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_DAYS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_DAYS",
@"{{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 days}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerDay;
} else if (durationSeconds < secondsPerWeek * 1.5) { // 1 Week
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_WEEK",
@"{{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 week}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_WEEKS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_WEEK",
@"{{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{1 week}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerWeek;
} else { // Multiple weeks
amountFormat = NSLocalizedString(@"TIME_AMOUNT_WEEKS",
@"{{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings");
if (useShortFormat) {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_WEEKS_SHORT_FORMAT",
@"Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally ommitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings");
} else {
amountFormat = NSLocalizedString(@"TIME_AMOUNT_WEEKS",
@"{{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages "
@"expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings");
}
duration = durationSeconds / secondsPerWeek;
}
@ -152,7 +198,7 @@ const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDuration = k
- (NSString *)durationString
{
return [self.class stringForDurationSeconds:self.durationSeconds];
return [self.class stringForDurationSeconds:self.durationSeconds useShortFormat:NO];
}
#pragma mark - Dirty Tracking

View File

@ -1,5 +1,6 @@
// Created by Michael Kirk on 9/25/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSDisappearingConfigurationUpdateInfoMessage.h"
#import "OWSDisappearingMessagesConfiguration.h"
@ -57,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN
@"strings for context.");
NSString *durationString =
[OWSDisappearingMessagesConfiguration stringForDurationSeconds:self.configurationDurationSeconds];
[OWSDisappearingMessagesConfiguration stringForDurationSeconds:self.configurationDurationSeconds useShortFormat:NO];
return [NSString stringWithFormat:infoFormat, self.createdByRemoteName, durationString];
} else {
NSString *infoFormat = NSLocalizedString(@"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION",
@ -70,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN
@"Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context.");
NSString *durationString =
[OWSDisappearingMessagesConfiguration stringForDurationSeconds:self.configurationDurationSeconds];
[OWSDisappearingMessagesConfiguration stringForDurationSeconds:self.configurationDurationSeconds useShortFormat:NO];
return [NSString stringWithFormat:infoFormat, durationString];
} else {
return NSLocalizedString(@"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION",