Timer button with duration label
// FREEBIE
|
@ -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 */,
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "61D54E7EB87D07B55A29BE2A5A7F463A"
|
||||
BlueprintIdentifier = "B57ACF2237BE640621E2E2CF12637CFE"
|
||||
BuildableName = "SignalServiceKit.framework"
|
||||
BlueprintName = "SignalServiceKit"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 631 B |
Before Width: | Height: | Size: 809 B |
|
@ -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"
|
||||
}
|
||||
],
|
BIN
Signal/Images.xcassets/ic_timer.imageset/ic_timer.png
vendored
Normal file
After Width: | Height: | Size: 778 B |
BIN
Signal/Images.xcassets/ic_timer.imageset/ic_timer@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Signal/Images.xcassets/ic_timer.imageset/ic_timer@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.4 KiB |
|
@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 631 B |
Before Width: | Height: | Size: 809 B |
Before Width: | Height: | Size: 518 B |
Before Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 1 KiB |
|
@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 518 B |
Before Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 1 KiB |
|
@ -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"];
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
134
SignalMessaging/Views/DisappearingTimerConfigurationView.swift
Normal 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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|