black masking style for avatar cropper
- cancel/done buttons - no navbar for modal edit - vertically center image // FREEBIE
This commit is contained in:
parent
79f0c14e29
commit
4e93bec230
|
@ -13,6 +13,7 @@
|
|||
#import "NotificationsManager.h"
|
||||
#import "OWSAnyTouchGestureRecognizer.h"
|
||||
#import "OWSAudioAttachmentPlayer.h"
|
||||
#import "OWSBezierPathView.h"
|
||||
#import "OWSCallNotificationsAdaptee.h"
|
||||
#import "OWSContactAvatarBuilder.h"
|
||||
#import "OWSContactsManager.h"
|
||||
|
|
|
@ -10,6 +10,8 @@ import Foundation
|
|||
|
||||
@objc class CommonStrings: NSObject {
|
||||
static let dismissButton = NSLocalizedString("DISMISS_BUTTON_TEXT", comment: "Short text to dismiss current modal / actionsheet / screen")
|
||||
static let cancelButton = NSLocalizedString("TXT_CANCEL_TITLE", comment:"Label for the cancel button in an alert or action sheet.")
|
||||
|
||||
}
|
||||
|
||||
@objc class CallStrings: NSObject {
|
||||
|
|
|
@ -355,8 +355,7 @@ class AttachmentApprovalViewController: OWSViewController, OWSAudioAttachmentPla
|
|||
buttonSpacer.autoSetDimension(.width, toSize:buttonHSpacing)
|
||||
buttonSpacer.autoHCenterInSuperview()
|
||||
|
||||
let cancelButton = createButton(title: NSLocalizedString("TXT_CANCEL_TITLE",
|
||||
comment: ""),
|
||||
let cancelButton = createButton(title: CommonStrings.cancelButton,
|
||||
color : UIColor.ows_destructiveRed(),
|
||||
action: #selector(cancelPressed))
|
||||
buttonRow.addSubview(cancelButton)
|
||||
|
|
|
@ -132,10 +132,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
successCompletion:^(UIImage *_Nonnull dstImage) {
|
||||
[self.delegate avatarDidChange:dstImage];
|
||||
}];
|
||||
OWSNavigationController *navigationController =
|
||||
[[OWSNavigationController alloc] initWithRootViewController:vc];
|
||||
[self.delegate.fromViewController
|
||||
presentViewController:navigationController
|
||||
presentViewController:vc
|
||||
animated:YES
|
||||
completion:[UIUtil modalCompletionBlock]];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#import "BlockListUIUtils.h"
|
||||
#import "OWSContactsManager.h"
|
||||
#import "PhoneNumber.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import <SignalServiceKit/Contact.h>
|
||||
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||
#import <SignalServiceKit/SignalAccount.h>
|
||||
|
@ -104,7 +105,7 @@ typedef void (^BlockAlertCompletionBlock)();
|
|||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
|
@ -208,7 +209,7 @@ typedef void (^BlockAlertCompletionBlock)();
|
|||
}];
|
||||
[actionSheetController addAction:unblockAction];
|
||||
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
if (completionBlock) {
|
||||
|
|
|
@ -150,7 +150,7 @@ open class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDa
|
|||
|
||||
let alert = UIAlertController(title: title, message: body, preferredStyle: UIAlertControllerStyle.alert)
|
||||
|
||||
let dismissText = NSLocalizedString("TXT_CANCEL_TITLE", comment:"")
|
||||
let dismissText = CommonStrings.cancelButton
|
||||
|
||||
let cancelAction = UIAlertAction(title: dismissText, style: .cancel, handler: { _ in
|
||||
let error = NSError(domain: "contactsPickerErrorDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "No Contacts Access"])
|
||||
|
|
|
@ -421,7 +421,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
contactViewController.allowsActions = NO;
|
||||
contactViewController.allowsEditing = YES;
|
||||
contactViewController.navigationItem.leftBarButtonItem =
|
||||
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
|
||||
[[UIBarButtonItem alloc] initWithTitle:CommonStrings.cancelButton
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:fromViewController
|
||||
action:@selector(didFinishEditingContact)];
|
||||
|
|
|
@ -66,8 +66,6 @@ class CropScaleImageViewController: OWSViewController {
|
|||
// We use a CALayer to render the image for performance reasons.
|
||||
var imageLayer: CALayer!
|
||||
|
||||
var dashedBorderLayer: CAShapeLayer!
|
||||
|
||||
// In width/height.
|
||||
//
|
||||
// TODO: We could make this a parameter.
|
||||
|
@ -98,6 +96,9 @@ class CropScaleImageViewController: OWSViewController {
|
|||
// corner of the crop region in src image point coordinates.
|
||||
var srcTranslation: CGPoint = CGPoint.zero
|
||||
|
||||
// space between the cropping circle and the outside edge of the view
|
||||
let maskMargin = CGFloat(20)
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
@available(*, unavailable, message:"use srcImage:successCompletion: constructor instead.")
|
||||
|
@ -174,29 +175,18 @@ class CropScaleImageViewController: OWSViewController {
|
|||
|
||||
view.backgroundColor = UIColor.white
|
||||
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem:.stop,
|
||||
target:self,
|
||||
action:#selector(cancelPressed))
|
||||
self.navigationItem.title = NSLocalizedString("CROP_SCALE_IMAGE_VIEW_TITLE",
|
||||
comment: "Title for the 'crop/scale image' dialog.")
|
||||
|
||||
createViews()
|
||||
}
|
||||
|
||||
// MARK: - Create Views
|
||||
|
||||
private func createViews() {
|
||||
let previewTopMargin: CGFloat = 30
|
||||
let previewHMargin: CGFloat = 20
|
||||
|
||||
let contentView = UIView()
|
||||
contentView.backgroundColor = UIColor.black
|
||||
self.view.addSubview(contentView)
|
||||
contentView.autoPinWidthToSuperview(withMargin:previewHMargin)
|
||||
contentView.autoPin(toTopLayoutGuideOf: self, withInset:previewTopMargin)
|
||||
contentView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
createButtonRow(contentView:contentView)
|
||||
|
||||
let imageHMargin: CGFloat = 0
|
||||
let imageView = OWSLayerView(frame:CGRect.zero, layoutCallback: {[weak self] _ in
|
||||
guard let strongSelf = self else { return }
|
||||
strongSelf.updateImageLayout()
|
||||
|
@ -204,22 +194,45 @@ class CropScaleImageViewController: OWSViewController {
|
|||
imageView.clipsToBounds = true
|
||||
self.imageView = imageView
|
||||
contentView.addSubview(imageView)
|
||||
imageView.autoPinWidthToSuperview(withMargin:imageHMargin)
|
||||
imageView.autoVCenterInSuperview()
|
||||
imageView.autoPinToSquareAspectRatio()
|
||||
imageView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
let imageLayer = CALayer()
|
||||
self.imageLayer = imageLayer
|
||||
imageLayer.contents = srcImage.cgImage
|
||||
imageView.layer.addSublayer(imageLayer)
|
||||
|
||||
let dashedBorderLayer = CAShapeLayer()
|
||||
self.dashedBorderLayer = dashedBorderLayer
|
||||
dashedBorderLayer.strokeColor = UIColor.ows_materialBlue().cgColor
|
||||
dashedBorderLayer.lineDashPattern = [10, 10]
|
||||
dashedBorderLayer.lineWidth = 4
|
||||
dashedBorderLayer.fillColor = nil
|
||||
imageView.layer.addSublayer(dashedBorderLayer)
|
||||
let maskingView = OWSBezierPathView()
|
||||
contentView.addSubview(maskingView)
|
||||
|
||||
maskingView.configureShapeLayerBlock = { layer, bounds in
|
||||
let path = UIBezierPath(rect: bounds)
|
||||
|
||||
let radius = min(bounds.size.width, bounds.size.height) * 0.5 - self.maskMargin
|
||||
// Center the circle's bounding rectangle
|
||||
let circleRect = CGRect(x: bounds.size.width * 0.5 - radius, y: bounds.size.height * 0.5 - radius, width: radius * 2, height: radius * 2)
|
||||
let circlePath = UIBezierPath(roundedRect: circleRect, cornerRadius: radius)
|
||||
path.append(circlePath)
|
||||
path.usesEvenOddFillRule = true
|
||||
|
||||
layer.path = path.cgPath
|
||||
layer.fillRule = kCAFillRuleEvenOdd
|
||||
layer.fillColor = UIColor.black.cgColor
|
||||
layer.opacity = 0.7
|
||||
}
|
||||
maskingView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.textColor = UIColor.white
|
||||
titleLabel.textAlignment = .center
|
||||
titleLabel.font = UIFont.ows_mediumFont(withSize:ScaleFromIPhone5(16))
|
||||
titleLabel.text = NSLocalizedString("CROP_SCALE_IMAGE_VIEW_TITLE",
|
||||
comment: "Title for the 'crop/scale image' dialog.")
|
||||
contentView.addSubview(titleLabel)
|
||||
titleLabel.autoPinWidthToSuperview()
|
||||
let titleLabelMargin = ScaleFromIPhone5(16)
|
||||
titleLabel.autoPin(toTopLayoutGuideOf:self, withInset:titleLabelMargin)
|
||||
|
||||
createButtonRow(contentView: contentView)
|
||||
|
||||
contentView.isUserInteractionEnabled = true
|
||||
contentView.addGestureRecognizer(UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(sender:))))
|
||||
|
@ -294,35 +307,36 @@ class CropScaleImageViewController: OWSViewController {
|
|||
height:srcDefaultCropSizePoints.height / imageScale)
|
||||
|
||||
let minSrcTranslationPoints = CGPoint.zero
|
||||
|
||||
// Prevent panning outside of image area.
|
||||
let maxSrcTranslationPoints = CGPoint(x:srcImageSizePoints.width - srcCropSizePoints.width,
|
||||
y:srcImageSizePoints.height - srcCropSizePoints.height
|
||||
)
|
||||
|
||||
// Normalize the translation property.
|
||||
// Normalize the translation property
|
||||
srcTranslation = CGPoint(x: max(minSrcTranslationPoints.x, min(maxSrcTranslationPoints.x, srcTranslation.x)),
|
||||
y: max(minSrcTranslationPoints.y, min(maxSrcTranslationPoints.y, srcTranslation.y)))
|
||||
|
||||
let imageViewFrame = imageRenderRect(forDstSize:viewSizePoints)
|
||||
var imageViewFrame = imageRenderRect(forDstSize: viewSizePoints)
|
||||
|
||||
// Disable implicit animations.
|
||||
// offset to vertically center image in view (aspect ratio?)
|
||||
let srcToViewRatio = viewSizePoints.width / srcCropSizePoints.width / imageScale
|
||||
let heightOfImageLayer = srcDefaultCropSizePoints.height * srcToViewRatio
|
||||
let yOffset = imageView.frame.height * 0.5 - heightOfImageLayer * 0.5
|
||||
imageViewFrame = imageViewFrame.offsetBy(dx: 0, dy: yOffset)
|
||||
|
||||
// inset frame by the with of the masking margin so the user can pan to the very edge of the image
|
||||
imageViewFrame = CGRect(x: imageViewFrame.origin.x + self.maskMargin,
|
||||
y: imageViewFrame.origin.y + self.maskMargin,
|
||||
width: imageViewFrame.width - maskMargin * 2,
|
||||
height: imageViewFrame.height - maskMargin * 2)
|
||||
|
||||
// Disable implicit animations for snappier panning/zooming.
|
||||
CATransaction.begin()
|
||||
CATransaction.setDisableActions(true)
|
||||
|
||||
imageLayer.frame = imageViewFrame
|
||||
|
||||
// Mask to circle.
|
||||
let maskLayer = CAShapeLayer()
|
||||
maskLayer.frame = imageViewFrame
|
||||
maskLayer.fillRule = kCAFillRuleEvenOdd
|
||||
let maskFrame = CGRect(origin:CGPoint(x:-imageViewFrame.origin.x * 2,
|
||||
y: -imageViewFrame.origin.y * 2),
|
||||
size:imageView.bounds.size)
|
||||
maskLayer.path =
|
||||
CGPath(ellipseIn: maskFrame, transform: nil)
|
||||
imageLayer.mask = maskLayer
|
||||
|
||||
dashedBorderLayer.frame = imageView.bounds
|
||||
dashedBorderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
|
||||
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
|
@ -333,10 +347,10 @@ class CropScaleImageViewController: OWSViewController {
|
|||
|
||||
let srcToViewRatio = dstSize.width / srcCropSizePoints.width
|
||||
|
||||
return CGRect(origin: CGPoint(x:srcTranslation.x * -srcToViewRatio,
|
||||
y:srcTranslation.y * -srcToViewRatio),
|
||||
size: CGSize(width:srcImageSizePoints.width * +srcToViewRatio,
|
||||
height:srcImageSizePoints.height * +srcToViewRatio
|
||||
return CGRect(origin: CGPoint(x: srcTranslation.x * -srcToViewRatio,
|
||||
y: srcTranslation.y * -srcToViewRatio),
|
||||
size: CGSize(width:srcImageSizePoints.width * +srcToViewRatio,
|
||||
height:srcImageSizePoints.height * +srcToViewRatio
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -442,19 +456,24 @@ class CropScaleImageViewController: OWSViewController {
|
|||
buttonRow.autoPinEdge(toSuperviewEdge:.bottom, withInset:buttonBottomMargin)
|
||||
buttonRow.autoPinEdge(.top, to:.bottom, of:contentView, withOffset:buttonTopMargin)
|
||||
|
||||
let cancelButton = createButton(title: CommonStrings.cancelButton,
|
||||
action: #selector(cancelPressed))
|
||||
buttonRow.addSubview(cancelButton)
|
||||
cancelButton.autoPinEdge(toSuperviewEdge:.top)
|
||||
cancelButton.autoPinEdge(toSuperviewEdge:.bottom)
|
||||
cancelButton.autoPinEdge(toSuperviewEdge: .left)
|
||||
|
||||
let doneButton = createButton(title: NSLocalizedString("BUTTON_DONE",
|
||||
comment: "Label for generic done button."),
|
||||
color : UIColor.ows_materialBlue(),
|
||||
action: #selector(donePressed))
|
||||
buttonRow.addSubview(doneButton)
|
||||
doneButton.autoPinEdge(toSuperviewEdge:.top)
|
||||
doneButton.autoPinEdge(toSuperviewEdge:.bottom)
|
||||
doneButton.autoHCenterInSuperview()
|
||||
doneButton.autoPinEdge(toSuperviewEdge: .right)
|
||||
}
|
||||
|
||||
private func createButton(title: String, color: UIColor, action: Selector) -> UIButton {
|
||||
private func createButton(title: String, action: Selector) -> UIButton {
|
||||
let buttonFont = UIFont.ows_mediumFont(withSize:ScaleFromIPhone5To7Plus(18, 22))
|
||||
let buttonCornerRadius = ScaleFromIPhone5To7Plus(4, 5)
|
||||
let buttonWidth = ScaleFromIPhone5To7Plus(110, 140)
|
||||
let buttonHeight = ScaleFromIPhone5To7Plus(35, 45)
|
||||
|
||||
|
@ -462,9 +481,6 @@ class CropScaleImageViewController: OWSViewController {
|
|||
button.setTitle(title, for:.normal)
|
||||
button.setTitleColor(UIColor.white, for:.normal)
|
||||
button.titleLabel!.font = buttonFont
|
||||
button.backgroundColor = color
|
||||
button.layer.cornerRadius = buttonCornerRadius
|
||||
button.clipsToBounds = true
|
||||
button.addTarget(self, action:action, for:.touchUpInside)
|
||||
button.autoSetDimension(.width, toSize:buttonWidth)
|
||||
button.autoSetDimension(.height, toSize:buttonHeight)
|
||||
|
@ -497,8 +513,8 @@ class CropScaleImageViewController: OWSViewController {
|
|||
let context = UIGraphicsGetCurrentContext()
|
||||
context!.interpolationQuality = .high
|
||||
|
||||
let imageViewFrame = imageRenderRect(forDstSize:dstSizePixels)
|
||||
srcImage.draw(in:imageViewFrame)
|
||||
let imageViewFrame = imageRenderRect(forDstSize: dstSizePixels)
|
||||
srcImage.draw(in: imageViewFrame)
|
||||
|
||||
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
if scaledImage == nil {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#import "OWSDeviceProvisioningURLParser.h"
|
||||
#import "OWSLinkedDevicesTableViewController.h"
|
||||
#import "OWSProfileManager.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import <SignalServiceKit/ECKeyPair+OWSPrivateKey.h>
|
||||
#import <SignalServiceKit/OWSDeviceProvisioner.h>
|
||||
#import <SignalServiceKit/OWSIdentityManager.h>
|
||||
|
@ -80,15 +81,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
|
||||
message:body
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
|
||||
UIAlertAction *cancelAction =
|
||||
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
});
|
||||
}];
|
||||
[UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
});
|
||||
}];
|
||||
[alertController addAction:cancelAction];
|
||||
|
||||
UIAlertAction *proceedAction =
|
||||
|
@ -111,7 +112,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *cancelAction =
|
||||
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
|
||||
[UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
@ -183,7 +184,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[alertController addAction:retryAction];
|
||||
|
||||
UIAlertAction *cancelAction =
|
||||
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
|
||||
[UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
|
|
@ -319,7 +319,7 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien
|
|||
message:NSLocalizedString(@"ALERT_VALIDATE_RECIPIENT_MESSAGE",
|
||||
@"A message for the alert shown while validating a signal account")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[activityAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
[activityAlert addAction:[UIAlertAction actionWithTitle:CommonStrings.cancelButton
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
wasCancelled = YES;
|
||||
|
|
|
@ -85,7 +85,7 @@ NSString *const TSStorageManagerAppUpgradeNagDate = @"TSStorageManagerAppUpgrade
|
|||
@"version number.}}.")];
|
||||
[updater setAlertUpdateButtonTitle:NSLocalizedString(@"APP_UPDATE_NAG_ALERT_UPDATE_BUTTON",
|
||||
@"Label for the 'update' button in the 'new app version available' alert.")];
|
||||
[updater setAlertCancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")];
|
||||
[updater setAlertCancelButtonTitle:CommonStrings.cancelButton];
|
||||
[updater setDelegate:self];
|
||||
[updater showUpdateWithConfirmation];
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ import Foundation
|
|||
}
|
||||
|
||||
public class func cancelAction() -> UIAlertAction {
|
||||
let action = UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment:"Label for the cancel button in an alert or action sheet."), style: .cancel) { _ in
|
||||
let action = UIAlertAction(title: CommonStrings.cancelButton, style: .cancel) { _ in
|
||||
Logger.debug("Cancel item")
|
||||
// Do nothing.
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@interface OWSBezierPathView : UIView
|
||||
|
||||
// Configure the view with this method if it uses a single Bezier path.
|
||||
- (void)setConfigureShapeLayerBlock:(ConfigureShapeLayerBlock)configureShapeLayerBlock;
|
||||
@property (nonatomic) ConfigureShapeLayerBlock configureShapeLayerBlock;
|
||||
|
||||
// Configure the view with this method if it uses multiple Bezier paths.
|
||||
//
|
||||
// Paths will be rendered in back-to-front order.
|
||||
- (void)setConfigureShapeLayerBlocks:(NSArray<ConfigureShapeLayerBlock> *)configureShapeLayerBlocks;
|
||||
@property (nonatomic) NSArray<ConfigureShapeLayerBlock> *configureShapeLayerBlocks;
|
||||
|
||||
// This method forces the view to reconstruct its layer content. It shouldn't
|
||||
// be necessary to call this unless the ConfigureShapeLayerBlocks depend on external
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSBezierPathView ()
|
||||
|
||||
@property (nonatomic) NSArray<ConfigureShapeLayerBlock> *configureShapeLayerBlocks;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSBezierPathView
|
||||
|
|
|
@ -389,7 +389,7 @@
|
|||
"CREATE_NEW_GROUP" = "Create new group";
|
||||
|
||||
/* Title for the 'crop/scale image' dialog. */
|
||||
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Crop Image";
|
||||
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Crop and Scale";
|
||||
|
||||
/* Subtitle shown while the app is updating its database. */
|
||||
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
|
||||
|
|
Loading…
Reference in New Issue