Сделать плавную анимацию кнопки send
This commit is contained in:
@@ -75,6 +75,17 @@ struct ChatDetailView: View {
|
|||||||
!messageText.isEmpty
|
!messageText.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var sendButtonProgress: CGFloat {
|
||||||
|
shouldShowSendButton ? 1 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private var micButtonProgress: CGFloat {
|
||||||
|
shouldShowSendButton ? 0 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
private var sendButtonWidth: CGFloat { 38 }
|
||||||
|
private var sendButtonHeight: CGFloat { 36 }
|
||||||
|
|
||||||
private var composerHorizontalPadding: CGFloat {
|
private var composerHorizontalPadding: CGFloat {
|
||||||
isInputFocused ? 16 : 28
|
isInputFocused ? 16 : 28
|
||||||
}
|
}
|
||||||
@@ -337,7 +348,7 @@ private extension ChatDetailView {
|
|||||||
.padding(.horizontal, 16)
|
.padding(.horizontal, 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack(alignment: .bottom, spacing: 6) {
|
HStack(alignment: .bottom, spacing: shouldShowSendButton ? 0 : 6) {
|
||||||
Button {
|
Button {
|
||||||
// Placeholder for attachment picker
|
// Placeholder for attachment picker
|
||||||
} label: {
|
} label: {
|
||||||
@@ -366,7 +377,7 @@ private extension ChatDetailView {
|
|||||||
.padding(.bottom, 8)
|
.padding(.bottom, 8)
|
||||||
.frame(maxWidth: .infinity, minHeight: 36, alignment: .bottomLeading)
|
.frame(maxWidth: .infinity, minHeight: 36, alignment: .bottomLeading)
|
||||||
|
|
||||||
HStack(alignment: .center, spacing: 8) {
|
HStack(alignment: .center, spacing: 0) {
|
||||||
Button {
|
Button {
|
||||||
// Placeholder for quick actions
|
// Placeholder for quick actions
|
||||||
} label: {
|
} label: {
|
||||||
@@ -381,10 +392,9 @@ private extension ChatDetailView {
|
|||||||
.accessibilityLabel("Quick actions")
|
.accessibilityLabel("Quick actions")
|
||||||
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
||||||
}
|
}
|
||||||
.padding(.trailing, 8)
|
.padding(.trailing, 8 + (sendButtonWidth * sendButtonProgress))
|
||||||
.frame(height: 36, alignment: .center)
|
.frame(height: 36, alignment: .center)
|
||||||
|
.overlay(alignment: .trailing) {
|
||||||
if shouldShowSendButton {
|
|
||||||
Button(action: sendCurrentMessage) {
|
Button(action: sendCurrentMessage) {
|
||||||
ZStack {
|
ZStack {
|
||||||
// Mirrors the layered blend stack from the original SVG icon.
|
// Mirrors the layered blend stack from the original SVG icon.
|
||||||
@@ -431,8 +441,10 @@ private extension ChatDetailView {
|
|||||||
.blendMode(.overlay)
|
.blendMode(.overlay)
|
||||||
}
|
}
|
||||||
.compositingGroup()
|
.compositingGroup()
|
||||||
|
.opacity(0.42 + (0.58 * sendButtonProgress))
|
||||||
|
.scaleEffect(0.72 + (0.28 * sendButtonProgress))
|
||||||
.frame(width: 22, height: 19)
|
.frame(width: 22, height: 19)
|
||||||
.frame(width: 44, height: 36)
|
.frame(width: sendButtonWidth, height: sendButtonHeight)
|
||||||
.background {
|
.background {
|
||||||
Capsule().fill(Color(hex: 0x008BFF))
|
Capsule().fill(Color(hex: 0x008BFF))
|
||||||
}
|
}
|
||||||
@@ -440,7 +452,18 @@ private extension ChatDetailView {
|
|||||||
.accessibilityLabel("Send")
|
.accessibilityLabel("Send")
|
||||||
.disabled(!canSend)
|
.disabled(!canSend)
|
||||||
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
||||||
.transition(.move(edge: .trailing).combined(with: .opacity))
|
.allowsHitTesting(shouldShowSendButton)
|
||||||
|
.opacity(Double(sendButtonProgress))
|
||||||
|
.scaleEffect(0.74 + (0.26 * sendButtonProgress), anchor: .trailing)
|
||||||
|
.blur(radius: (1 - sendButtonProgress) * 2.1)
|
||||||
|
.mask(
|
||||||
|
Capsule()
|
||||||
|
.frame(
|
||||||
|
width: max(0.001, sendButtonWidth * sendButtonProgress),
|
||||||
|
height: max(0.001, sendButtonHeight * sendButtonProgress)
|
||||||
|
)
|
||||||
|
.frame(width: sendButtonWidth, height: sendButtonHeight, alignment: .trailing)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(3)
|
.padding(3)
|
||||||
@@ -451,21 +474,28 @@ private extension ChatDetailView {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !shouldShowSendButton {
|
Button(action: trailingAction) {
|
||||||
Button(action: trailingAction) {
|
TelegramVectorIcon(
|
||||||
TelegramVectorIcon(
|
pathData: TelegramIconPath.microphone,
|
||||||
pathData: TelegramIconPath.microphone,
|
viewBox: CGSize(width: 18, height: 24),
|
||||||
viewBox: CGSize(width: 18, height: 24),
|
color: Color.white
|
||||||
color: Color.white
|
)
|
||||||
)
|
.frame(width: 18, height: 24)
|
||||||
.frame(width: 18, height: 24)
|
.frame(width: 42, height: 42)
|
||||||
.frame(width: 42, height: 42)
|
.background { floatingCircleBackground(strokeOpacity: 0.18) }
|
||||||
.background { floatingCircleBackground(strokeOpacity: 0.18) }
|
|
||||||
}
|
|
||||||
.accessibilityLabel("Voice message")
|
|
||||||
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
|
||||||
.transition(.move(edge: .trailing).combined(with: .opacity))
|
|
||||||
}
|
}
|
||||||
|
.accessibilityLabel("Voice message")
|
||||||
|
.buttonStyle(ChatDetailGlassPressButtonStyle())
|
||||||
|
.allowsHitTesting(!shouldShowSendButton)
|
||||||
|
.opacity(Double(micButtonProgress))
|
||||||
|
.scaleEffect(
|
||||||
|
x: max(0.001, 0.42 + (0.58 * micButtonProgress)),
|
||||||
|
y: 0.78 + (0.22 * micButtonProgress),
|
||||||
|
anchor: .trailing
|
||||||
|
)
|
||||||
|
.blur(radius: (1 - micButtonProgress) * 2.4)
|
||||||
|
.frame(width: 42 * micButtonProgress, height: 42, alignment: .trailing)
|
||||||
|
.clipped()
|
||||||
}
|
}
|
||||||
.padding(.horizontal, composerHorizontalPadding)
|
.padding(.horizontal, composerHorizontalPadding)
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
|
|||||||
Reference in New Issue
Block a user