diff --git a/Signal/Images.xcassets/x-24.imageset/Contents.json b/Signal/Images.xcassets/x-24.imageset/Contents.json new file mode 100644 index 000000000..1f25af162 --- /dev/null +++ b/Signal/Images.xcassets/x-24.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "x-24@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "x-24@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "x-24@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/x-24.imageset/x-24@1x.png b/Signal/Images.xcassets/x-24.imageset/x-24@1x.png new file mode 100644 index 000000000..ee6d0b887 Binary files /dev/null and b/Signal/Images.xcassets/x-24.imageset/x-24@1x.png differ diff --git a/Signal/Images.xcassets/x-24.imageset/x-24@2x.png b/Signal/Images.xcassets/x-24.imageset/x-24@2x.png new file mode 100644 index 000000000..ea502285c Binary files /dev/null and b/Signal/Images.xcassets/x-24.imageset/x-24@2x.png differ diff --git a/Signal/Images.xcassets/x-24.imageset/x-24@3x.png b/Signal/Images.xcassets/x-24.imageset/x-24@3x.png new file mode 100644 index 000000000..cbb9bb263 Binary files /dev/null and b/Signal/Images.xcassets/x-24.imageset/x-24@3x.png differ diff --git a/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift b/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift index 40e681eda..026aaa433 100644 --- a/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift +++ b/SignalMessaging/ViewControllers/AttachmentApprovalViewController.swift @@ -1462,6 +1462,7 @@ class MediaMessageTextToolbar: UIView, UITextViewDelegate { lengthLimitLabel.layer.shadowColor = UIColor.black.cgColor lengthLimitLabel.layer.shadowOffset = .zero lengthLimitLabel.layer.shadowOpacity = 0.8 + lengthLimitLabel.layer.shadowRadius = 2.0 lengthLimitLabel.isHidden = true return lengthLimitLabel @@ -1676,12 +1677,14 @@ public class ApprovalRailCellView: GalleryRailCellView { strongSelf.approvalRailCellDelegate?.approvalRailCellView(strongSelf, didRemoveItem: attachmentItem) } - button.setImage(#imageLiteral(resourceName: "ic_circled_x"), for: .normal) + button.setImage(UIImage(named: "x-24")?.withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = .white + button.layer.shadowColor = UIColor.black.cgColor + button.layer.shadowRadius = 2 + button.layer.shadowOpacity = 0.66 + button.layer.shadowOffset = .zero - let kInsetDistance: CGFloat = 5 - button.imageEdgeInsets = UIEdgeInsets(top: kInsetDistance, left: kInsetDistance, bottom: kInsetDistance, right: kInsetDistance) - - let kButtonWidth: CGFloat = 24 + kInsetDistance * 2 + let kButtonWidth: CGFloat = 24 button.autoSetDimensions(to: CGSize(width: kButtonWidth, height: kButtonWidth)) return button @@ -1704,8 +1707,8 @@ public class ApprovalRailCellView: GalleryRailCellView { if isSelected { addSubview(deleteButton) - deleteButton.autoPinEdge(toSuperviewEdge: .top, withInset: -12) - deleteButton.autoPinEdge(toSuperviewEdge: .trailing, withInset: -8) + deleteButton.autoPinEdge(toSuperviewEdge: .top, withInset: cellBorderWidth) + deleteButton.autoPinEdge(toSuperviewEdge: .trailing, withInset: cellBorderWidth + 4) } else { deleteButton.removeFromSuperview() } @@ -1726,8 +1729,8 @@ public class ApprovalRailCellView: GalleryRailCellView { if hasCaption { addSubview(captionIndicator) - captionIndicator.autoPinEdge(toSuperviewEdge: .top, withInset: 2) - captionIndicator.autoPinEdge(toSuperviewEdge: .leading, withInset: 6) + captionIndicator.autoPinEdge(toSuperviewEdge: .top, withInset: cellBorderWidth) + captionIndicator.autoPinEdge(toSuperviewEdge: .leading, withInset: cellBorderWidth + 4) } else { captionIndicator.removeFromSuperview() } diff --git a/SignalMessaging/Views/GalleryRailView.swift b/SignalMessaging/Views/GalleryRailView.swift index 66690ab2a..6f797ea6b 100644 --- a/SignalMessaging/Views/GalleryRailView.swift +++ b/SignalMessaging/Views/GalleryRailView.swift @@ -63,17 +63,18 @@ public class GalleryRailCellView: UIView { private(set) var isSelected: Bool = false + public let cellBorderWidth: CGFloat = 2 + func setIsSelected(_ isSelected: Bool) { - let borderWidth: CGFloat = 2 self.isSelected = isSelected // Reserve space for the selection border whether or not the cell is selected. - layoutMargins = UIEdgeInsets(top: 0, left: borderWidth, bottom: 0, right: borderWidth) + layoutMargins = UIEdgeInsets(top: 0, left: cellBorderWidth, bottom: 0, right: cellBorderWidth) if isSelected { imageView.layer.borderColor = Theme.galleryHighlightColor.cgColor - imageView.layer.borderWidth = borderWidth - imageView.layer.cornerRadius = borderWidth + imageView.layer.borderWidth = cellBorderWidth + imageView.layer.cornerRadius = cellBorderWidth } else { imageView.layer.borderWidth = 0 imageView.layer.cornerRadius = 0 diff --git a/SignalMessaging/Views/ImageEditor/ImageEditorBrushViewController.swift b/SignalMessaging/Views/ImageEditor/ImageEditorBrushViewController.swift index af56c8db1..4281208dc 100644 --- a/SignalMessaging/Views/ImageEditor/ImageEditorBrushViewController.swift +++ b/SignalMessaging/Views/ImageEditor/ImageEditorBrushViewController.swift @@ -165,9 +165,9 @@ public class ImageEditorBrushViewController: OWSViewController { let view = self.canvasView.gestureReferenceView let viewBounds = view.bounds let newSample = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationInView, - viewBounds: viewBounds, - model: self.model, - transform: self.model.currentTransform()) + viewBounds: viewBounds, + model: self.model, + transform: self.model.currentTransform()) if let prevSample = self.currentStrokeSamples.last, prevSample == newSample { @@ -178,8 +178,7 @@ public class ImageEditorBrushViewController: OWSViewController { } let strokeColor = paletteView.selectedValue.color - // TODO: Tune stroke width. - let unitStrokeWidth = ImageEditorStrokeItem.defaultUnitStrokeWidth() + let unitStrokeWidth = ImageEditorStrokeItem.defaultUnitStrokeWidth() / self.model.currentTransform().scaling switch gestureRecognizer.state { case .began: diff --git a/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift b/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift index dbe3448a3..dba18ef70 100644 --- a/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift +++ b/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift @@ -642,10 +642,24 @@ public class ImageEditorCanvasView: UIView { guard let sublayers = contentView.layer.sublayers else { return nil } + + // First we build a map of all text layers. + var layerMap = [String: EditorTextLayer]() for layer in sublayers { guard let textLayer = layer as? EditorTextLayer else { continue } + layerMap[textLayer.itemId] = textLayer + } + + // The layer ordering in the model is authoritative. + // Iterate over the layers in _reverse_ order of which they appear + // in the model, so that layers "on top" are hit first. + for item in model.items().reversed() { + guard let textLayer = layerMap[item.itemId] else { + // Not a text layer. + continue + } if textLayer.hitTest(point) != nil { return textLayer } diff --git a/SignalMessaging/Views/ImageEditor/ImageEditorPaletteView.swift b/SignalMessaging/Views/ImageEditor/ImageEditorPaletteView.swift index e1c78ff24..746ba5303 100644 --- a/SignalMessaging/Views/ImageEditor/ImageEditorPaletteView.swift +++ b/SignalMessaging/Views/ImageEditor/ImageEditorPaletteView.swift @@ -81,7 +81,9 @@ public class ImageEditorPaletteView: UIView { private let imageView = UIImageView() private let selectionView = UIView() - private let selectionWrapper = OWSLayerView() + // imageWrapper is used to host the "selection view". + private let imageWrapper = OWSLayerView() + private let shadowView = UIView() private var selectionConstraint: NSLayoutConstraint? private func createContents() { @@ -89,9 +91,18 @@ public class ImageEditorPaletteView: UIView { self.isOpaque = false self.layoutMargins = .zero + shadowView.backgroundColor = .black + shadowView.layer.shadowColor = UIColor.black.cgColor + shadowView.layer.shadowRadius = 2.0 + shadowView.layer.shadowOpacity = 0.33 + shadowView.layer.shadowOffset = .zero + addSubview(shadowView) + if let image = ImageEditorPaletteView.buildPaletteGradientImage() { imageView.image = image - imageView.layer.cornerRadius = image.size.width * 0.5 + let imageRadius = image.size.width * 0.5 + imageView.layer.cornerRadius = imageRadius + shadowView.layer.cornerRadius = imageRadius imageView.clipsToBounds = true } else { owsFailDebug("Missing image.") @@ -100,31 +111,28 @@ public class ImageEditorPaletteView: UIView { // We use an invisible margin to expand the hot area of this control. let margin: CGFloat = 20 imageView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin)) - imageView.layer.borderColor = UIColor.white.cgColor - imageView.layer.borderWidth = CGHairlineWidth() - imageView.layer.shadowColor = UIColor.black.cgColor - imageView.layer.shadowRadius = 2.0 - imageView.layer.shadowOpacity = 0.33 - imageView.layer.shadowOffset = .zero - selectionWrapper.layoutCallback = { [weak self] (view) in + imageView.addBorder(with: .white) + + imageWrapper.layoutCallback = { [weak self] (view) in guard let strongSelf = self else { return } strongSelf.updateState() } - self.addSubview(selectionWrapper) - selectionWrapper.autoPin(toEdgesOf: imageView) + addSubview(imageWrapper) + imageWrapper.autoPin(toEdgesOf: imageView) + shadowView.autoPin(toEdgesOf: imageView) selectionView.addBorder(with: .white) selectionView.layer.cornerRadius = selectionSize / 2 selectionView.autoSetDimensions(to: CGSize(width: selectionSize, height: selectionSize)) - selectionWrapper.addSubview(selectionView) + imageWrapper.addSubview(selectionView) selectionView.autoHCenterInSuperview() // There must be a better way to pin the selection view's location, // but I can't find it. let selectionConstraint = NSLayoutConstraint(item: selectionView, - attribute: .centerY, relatedBy: .equal, toItem: selectionWrapper, attribute: .top, multiplier: 1, constant: 0) + attribute: .centerY, relatedBy: .equal, toItem: imageWrapper, attribute: .top, multiplier: 1, constant: 0) selectionConstraint.autoInstall() self.selectionConstraint = selectionConstraint @@ -201,7 +209,7 @@ public class ImageEditorPaletteView: UIView { owsFailDebug("Missing selectionConstraint.") return } - let selectionY = selectionWrapper.height() * selectedValue.palettePhase + let selectionY = imageWrapper.height() * selectedValue.palettePhase selectionConstraint.constant = selectionY }