|
|
|
@ -13,8 +13,8 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
|
|
|
|
|
// MARK: Components
|
|
|
|
|
private lazy var mainButton = NewConversationButton(isMainButton: true, icon: #imageLiteral(resourceName: "Plus").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
private lazy var newPrivateChatButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Message").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
private lazy var newClosedGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Group").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
private lazy var createNewPrivateChatButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Message").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
private lazy var createNewClosedGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Group").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
private lazy var joinOpenGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Globe").scaled(to: CGSize(width: iconSize, height: iconSize)))
|
|
|
|
|
|
|
|
|
|
// MARK: Initialization
|
|
|
|
@ -33,12 +33,12 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
addSubview(joinOpenGroupButton)
|
|
|
|
|
horizontalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.left, to: .left, of: self, withInset: inset)
|
|
|
|
|
verticalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset)
|
|
|
|
|
addSubview(newPrivateChatButton)
|
|
|
|
|
newPrivateChatButton.center(.horizontal, in: self)
|
|
|
|
|
verticalButtonConstraints[newPrivateChatButton] = newPrivateChatButton.pin(.top, to: .top, of: self, withInset: inset)
|
|
|
|
|
addSubview(newClosedGroupButton)
|
|
|
|
|
horizontalButtonConstraints[newClosedGroupButton] = newClosedGroupButton.pin(.right, to: .right, of: self, withInset: -inset)
|
|
|
|
|
verticalButtonConstraints[newClosedGroupButton] = newClosedGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset)
|
|
|
|
|
addSubview(createNewPrivateChatButton)
|
|
|
|
|
createNewPrivateChatButton.center(.horizontal, in: self)
|
|
|
|
|
verticalButtonConstraints[createNewPrivateChatButton] = createNewPrivateChatButton.pin(.top, to: .top, of: self, withInset: inset)
|
|
|
|
|
addSubview(createNewClosedGroupButton)
|
|
|
|
|
horizontalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.right, to: .right, of: self, withInset: -inset)
|
|
|
|
|
verticalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset)
|
|
|
|
|
addSubview(mainButton)
|
|
|
|
|
mainButton.center(.horizontal, in: self)
|
|
|
|
|
mainButton.pin(.bottom, to: .bottom, of: self)
|
|
|
|
@ -53,9 +53,9 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
let joinOpenGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleJoinOpenGroupButtonTapped))
|
|
|
|
|
joinOpenGroupButton.addGestureRecognizer(joinOpenGroupButtonTapGestureRecognizer)
|
|
|
|
|
let createNewPrivateChatButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewPrivateChatButtonTapped))
|
|
|
|
|
newPrivateChatButton.addGestureRecognizer(createNewPrivateChatButtonTapGestureRecognizer)
|
|
|
|
|
createNewPrivateChatButton.addGestureRecognizer(createNewPrivateChatButtonTapGestureRecognizer)
|
|
|
|
|
let createNewClosedGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewClosedGroupButtonTapped))
|
|
|
|
|
newClosedGroupButton.addGestureRecognizer(createNewClosedGroupButtonTapGestureRecognizer)
|
|
|
|
|
createNewClosedGroupButton.addGestureRecognizer(createNewClosedGroupButtonTapGestureRecognizer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: Interaction
|
|
|
|
@ -65,14 +65,14 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
@objc private func handleCreateNewClosedGroupButtonTapped() { delegate?.createNewClosedGroup() }
|
|
|
|
|
|
|
|
|
|
private func expand(isUserDragging: Bool) {
|
|
|
|
|
let buttons = [ joinOpenGroupButton, newPrivateChatButton, newClosedGroupButton ]
|
|
|
|
|
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
|
|
|
|
|
UIView.animate(withDuration: 0.25, animations: {
|
|
|
|
|
buttons.forEach { $0.alpha = 1 }
|
|
|
|
|
let inset = (Values.newConversationButtonExpandedSize - Values.newConversationButtonCollapsedSize) / 2
|
|
|
|
|
let size = Values.newConversationButtonCollapsedSize
|
|
|
|
|
self.joinOpenGroupButton.frame = CGRect(origin: CGPoint(x: inset, y: self.height() - size - inset), size: CGSize(width: size, height: size))
|
|
|
|
|
self.newPrivateChatButton.frame = CGRect(center: CGPoint(x: self.bounds.center.x, y: inset + size / 2), size: CGSize(width: size, height: size))
|
|
|
|
|
self.newClosedGroupButton.frame = CGRect(origin: CGPoint(x: self.width() - size - inset, y: self.height() - size - inset), size: CGSize(width: size, height: size))
|
|
|
|
|
self.createNewPrivateChatButton.frame = CGRect(center: CGPoint(x: self.bounds.center.x, y: inset + size / 2), size: CGSize(width: size, height: size))
|
|
|
|
|
self.createNewClosedGroupButton.frame = CGRect(origin: CGPoint(x: self.width() - size - inset, y: self.height() - size - inset), size: CGSize(width: size, height: size))
|
|
|
|
|
}, completion: { _ in
|
|
|
|
|
self.isUserDragging = isUserDragging
|
|
|
|
|
})
|
|
|
|
@ -80,7 +80,7 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
|
|
|
|
|
private func collapse(withAnimation isAnimated: Bool) {
|
|
|
|
|
isUserDragging = false
|
|
|
|
|
let buttons = [ joinOpenGroupButton, newPrivateChatButton, newClosedGroupButton ]
|
|
|
|
|
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
|
|
|
|
|
UIView.animate(withDuration: isAnimated ? 0.25 : 0) {
|
|
|
|
|
buttons.forEach { button in
|
|
|
|
|
button.alpha = 0
|
|
|
|
@ -117,8 +117,14 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
let touchLocationInSelfCoordinates = touch.location(in: self)
|
|
|
|
|
mainButton.frame = CGRect(center: touchLocationInSelfCoordinates, size: mainButtonSize)
|
|
|
|
|
mainButton.alpha = 1 - (touchLocationInSelfCoordinates.distance(to: mainButtonLocationInSelfCoordinates) / maxDragDistance)
|
|
|
|
|
let buttons = [ joinOpenGroupButton, newPrivateChatButton, newClosedGroupButton ]
|
|
|
|
|
let buttonToExpand = buttons.first { $0.contains(touch) }
|
|
|
|
|
let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ]
|
|
|
|
|
let buttonToExpand = buttons.first { button in
|
|
|
|
|
var hasUserDraggedBeyondButton = false
|
|
|
|
|
if button == joinOpenGroupButton && touch.isLeft(of: joinOpenGroupButton) { hasUserDraggedBeyondButton = true }
|
|
|
|
|
if button == createNewPrivateChatButton && touch.isAbove(createNewPrivateChatButton) { hasUserDraggedBeyondButton = true }
|
|
|
|
|
if button == createNewClosedGroupButton && touch.isRight(of: createNewClosedGroupButton) { hasUserDraggedBeyondButton = true }
|
|
|
|
|
return button.contains(touch) || hasUserDraggedBeyondButton
|
|
|
|
|
}
|
|
|
|
|
if let buttonToExpand = buttonToExpand {
|
|
|
|
|
guard buttonToExpand != expandedButton else { return }
|
|
|
|
|
if let expandedButton = expandedButton { collapse(expandedButton) }
|
|
|
|
@ -132,9 +138,9 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
|
|
|
|
|
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
|
|
|
guard let touch = touches.first, isUserDragging else { return }
|
|
|
|
|
if joinOpenGroupButton.contains(touch) { delegate?.joinOpenGroup() }
|
|
|
|
|
else if newPrivateChatButton.contains(touch) { delegate?.createNewPrivateChat() }
|
|
|
|
|
else if newClosedGroupButton.contains(touch) { delegate?.createNewClosedGroup() }
|
|
|
|
|
if joinOpenGroupButton.contains(touch) || touch.isLeft(of: joinOpenGroupButton) { delegate?.joinOpenGroup() }
|
|
|
|
|
else if createNewPrivateChatButton.contains(touch) || touch.isAbove(createNewPrivateChatButton) { delegate?.createNewPrivateChat() }
|
|
|
|
|
else if createNewClosedGroupButton.contains(touch) || touch.isRight(of: createNewClosedGroupButton) { delegate?.createNewClosedGroup() }
|
|
|
|
|
reset()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -164,11 +170,11 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
if joinOpenGroupButton == expandedButton {
|
|
|
|
|
horizontalButtonConstraints[joinOpenGroupButton]!.constant = inset
|
|
|
|
|
verticalButtonConstraints[joinOpenGroupButton]!.constant = -inset
|
|
|
|
|
} else if newPrivateChatButton == expandedButton {
|
|
|
|
|
verticalButtonConstraints[newPrivateChatButton]!.constant = inset
|
|
|
|
|
} else if newClosedGroupButton == expandedButton {
|
|
|
|
|
horizontalButtonConstraints[newClosedGroupButton]!.constant = -inset
|
|
|
|
|
verticalButtonConstraints[newClosedGroupButton]!.constant = -inset
|
|
|
|
|
} else if createNewPrivateChatButton == expandedButton {
|
|
|
|
|
verticalButtonConstraints[createNewPrivateChatButton]!.constant = inset
|
|
|
|
|
} else if createNewClosedGroupButton == expandedButton {
|
|
|
|
|
horizontalButtonConstraints[createNewClosedGroupButton]!.constant = -inset
|
|
|
|
|
verticalButtonConstraints[createNewClosedGroupButton]!.constant = -inset
|
|
|
|
|
}
|
|
|
|
|
let size = Values.newConversationButtonCollapsedSize
|
|
|
|
|
let frame = CGRect(center: button.center, size: CGSize(width: size, height: size))
|
|
|
|
@ -182,6 +188,11 @@ final class NewConversationButtonSet : UIView {
|
|
|
|
|
button.backgroundColor = Colors.newConversationButtonCollapsedBackground
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
|
|
|
if !bounds.contains(point), isUserDragging { collapse(withAnimation: true) }
|
|
|
|
|
return super.hitTest(point, with: event)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: Delegate
|
|
|
|
@ -253,6 +264,33 @@ private extension UIView {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension UITouch {
|
|
|
|
|
|
|
|
|
|
func isLeft(of view: UIView) -> Bool {
|
|
|
|
|
return isContainedVertically(in: view) && location(in: view).x < view.bounds.minX
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isAbove(_ view: UIView) -> Bool {
|
|
|
|
|
return isContainedHorizontally(in: view) && location(in: view).y < view.bounds.minY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isRight(of view: UIView) -> Bool {
|
|
|
|
|
return isContainedVertically(in: view) && location(in: view).x > view.bounds.maxX
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isBelow(_ view: UIView) -> Bool {
|
|
|
|
|
return isContainedHorizontally(in: view) && location(in: view).y > view.bounds.maxY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func isContainedHorizontally(in view: UIView) -> Bool {
|
|
|
|
|
return (view.bounds.minX...view.bounds.maxX) ~= location(in: view).x
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func isContainedVertically(in view: UIView) -> Bool {
|
|
|
|
|
return (view.bounds.minY...view.bounds.maxY) ~= location(in: view).y
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension CGPoint {
|
|
|
|
|
|
|
|
|
|
func distance(to otherPoint: CGPoint) -> CGFloat {
|
|
|
|
|