Various improvements

This commit is contained in:
Isaac 2025-09-19 17:51:11 +04:00
parent 14782c1d33
commit 16b981651a
5 changed files with 68 additions and 34 deletions

View File

@ -388,8 +388,6 @@ public final class ChatRecordingPreviewInputPanelNodeImpl: ChatInputPanelNode {
} }
override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat {
let innerSize = CGSize(width: 40.0, height: 40.0)
let waveformBackgroundFrame = CGRect(origin: CGPoint(x: 2.0, y: 2.0), size: CGSize(width: width - 2.0 * 2.0, height: 40.0 - 2.0 * 2.0)) let waveformBackgroundFrame = CGRect(origin: CGPoint(x: 2.0, y: 2.0), size: CGSize(width: width - 2.0 * 2.0, height: 40.0 - 2.0 * 2.0))
if self.presentationInterfaceState != interfaceState { if self.presentationInterfaceState != interfaceState {
@ -558,22 +556,18 @@ public final class ChatRecordingPreviewInputPanelNodeImpl: ChatInputPanelNode {
), ),
environment: {}, environment: {},
forceUpdate: false, forceUpdate: false,
containerSize: CGSize(width: min(424.0, width - leftInset - rightInset - innerSize.width - 1.0), height: 40.0) containerSize: CGSize(width: waveformBackgroundFrame.width, height: 44.0)
) )
if let view = self.scrubber.view { if let view = self.scrubber.view {
if view.superview == nil { if view.superview == nil {
self.view.addSubview(view) self.view.addSubview(view)
} }
view.bounds = CGRect(origin: .zero, size: scrubberSize) view.frame = CGRect(origin: CGPoint(x: 2.0, y: 2.0), size: scrubberSize)
} }
} }
} }
} }
if let view = self.scrubber.view {
view.frame = CGRect(origin: CGPoint(x: min(width - innerSize.width - view.bounds.width, max(leftInset + 45.0, floorToScreenPixels((width - view.bounds.width) / 2.0))), y: 7.0 - UIScreenPixel), size: view.bounds.size)
}
let panelHeight = 40.0 let panelHeight = 40.0

View File

@ -466,7 +466,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
private var spoilersRevealed = false private var spoilersRevealed = false
private var animatingTransition = false private var animatingTransition = false
public var finishedTransitionToPreview: Bool?
private var touchDownGestureRecognizer: TouchDownGestureRecognizer? private var touchDownGestureRecognizer: TouchDownGestureRecognizer?
@ -2188,8 +2187,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
audioRecordingCancelIndicator.layer.animateAlpha(from: CGFloat(audioRecordingCancelIndicator.layer.presentation()?.opacity ?? 1), to: 0, duration: 0.15, delay: 0, removeOnCompletion: false) audioRecordingCancelIndicator.layer.animateAlpha(from: CGFloat(audioRecordingCancelIndicator.layer.presentation()?.opacity ?? 1), to: 0, duration: 0.15, delay: 0, removeOnCompletion: false)
} }
} else if self.audioRecordingInfoContainerNode != nil { } else if self.audioRecordingInfoContainerNode != nil {
self.finishedTransitionToPreview = nil
self.actionButtons.micButton.audioRecorder = nil self.actionButtons.micButton.audioRecorder = nil
self.actionButtons.micButton.videoRecordingStatus = nil self.actionButtons.micButton.videoRecordingStatus = nil
transition.updateAlpha(layer: self.textInputBackgroundNode.layer, alpha: 1.0) transition.updateAlpha(layer: self.textInputBackgroundNode.layer, alpha: 1.0)

View File

@ -750,7 +750,7 @@ public final class MediaScrubberComponent: Component {
case .editor, .cover: case .editor, .cover:
fullTrackHeight = trackHeight fullTrackHeight = trackHeight
case .videoMessage, .voiceMessage: case .videoMessage, .voiceMessage:
fullTrackHeight = 33.0 fullTrackHeight = 36.0
} }
let scrubberSize = CGSize(width: availableSize.width, height: fullTrackHeight) let scrubberSize = CGSize(width: availableSize.width, height: fullTrackHeight)
@ -1134,6 +1134,10 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
let fullTrackHeight: CGFloat let fullTrackHeight: CGFloat
if case .cover = params.style { if case .cover = params.style {
fullTrackHeight = trackHeight fullTrackHeight = trackHeight
} else if case .voiceMessage = params.style {
fullTrackHeight = 36.0
} else if case .videoMessage = params.style {
fullTrackHeight = 36.0
} else { } else {
fullTrackHeight = 33.0 fullTrackHeight = 33.0
} }
@ -1209,7 +1213,7 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
framesCornerRadius = 9.0 framesCornerRadius = 9.0
self.videoTransparentFramesContainer.alpha = 0.35 self.videoTransparentFramesContainer.alpha = 0.35
case .videoMessage, .voiceMessage: case .videoMessage, .voiceMessage:
fullTrackHeight = 33.0 fullTrackHeight = 36.0
framesCornerRadius = fullTrackHeight / 2.0 framesCornerRadius = fullTrackHeight / 2.0
self.videoTransparentFramesContainer.alpha = 0.5 self.videoTransparentFramesContainer.alpha = 0.5
} }

View File

@ -42,6 +42,7 @@ swift_library(
"//submodules/ChatSendMessageActionUI", "//submodules/ChatSendMessageActionUI",
"//submodules/TelegramUI/Components/ChatControllerInteraction", "//submodules/TelegramUI/Components/ChatControllerInteraction",
"//submodules/TelegramUI/Components/LottieComponent", "//submodules/TelegramUI/Components/LottieComponent",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -30,6 +30,7 @@ import TelegramAudio
import ChatSendMessageActionUI import ChatSendMessageActionUI
import ChatControllerInteraction import ChatControllerInteraction
import LottieComponent import LottieComponent
import GlassBackgroundComponent
struct CameraState: Equatable { struct CameraState: Equatable {
enum Recording: Equatable { enum Recording: Equatable {
@ -116,6 +117,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let context: AccountContext let context: AccountContext
let cameraState: CameraState let cameraState: CameraState
let containerSize: CGSize
let previewFrame: CGRect let previewFrame: CGRect
let isPreviewing: Bool let isPreviewing: Bool
let isMuted: Bool let isMuted: Bool
@ -131,6 +133,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
init( init(
context: AccountContext, context: AccountContext,
cameraState: CameraState, cameraState: CameraState,
containerSize: CGSize,
previewFrame: CGRect, previewFrame: CGRect,
isPreviewing: Bool, isPreviewing: Bool,
isMuted: Bool, isMuted: Bool,
@ -145,6 +148,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
) { ) {
self.context = context self.context = context
self.cameraState = cameraState self.cameraState = cameraState
self.containerSize = containerSize
self.previewFrame = previewFrame self.previewFrame = previewFrame
self.isPreviewing = isPreviewing self.isPreviewing = isPreviewing
self.isMuted = isMuted self.isMuted = isMuted
@ -168,6 +172,9 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
if lhs.cameraState != rhs.cameraState { if lhs.cameraState != rhs.cameraState {
return false return false
} }
if lhs.containerSize != rhs.containerSize {
return false
}
if lhs.isPreviewing != rhs.isPreviewing { if lhs.isPreviewing != rhs.isPreviewing {
return false return false
} }
@ -505,7 +512,9 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
static var body: Body { static var body: Body {
let frontFlash = Child(Image.self) let frontFlash = Child(Image.self)
let flipButtonBackground = Child(GlassBackgroundComponent.self)
let flipButton = Child(CameraButton.self) let flipButton = Child(CameraButton.self)
let flashButtonBackground = Child(GlassBackgroundComponent.self)
let flashButton = Child(CameraButton.self) let flashButton = Child(CameraButton.self)
let viewOnceButton = Child(PlainButtonComponent.self) let viewOnceButton = Child(PlainButtonComponent.self)
@ -519,7 +528,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
let component = context.component let component = context.component
let state = context.state let state = context.state
let availableSize = context.availableSize let availableSize = context.component.containerSize
state.cameraState = component.cameraState state.cameraState = component.cameraState
@ -558,11 +567,12 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
if case .on = component.cameraState.flashMode, case .front = component.cameraState.position { if case .on = component.cameraState.flashMode, case .front = component.cameraState.position {
let frontFlash = frontFlash.update( let frontFlash = frontFlash.update(
component: Image(image: state.image(.flashImage, theme: environment.theme), tintColor: component.cameraState.flashTint.color), component: Image(image: state.image(.flashImage, theme: environment.theme), tintColor: component.cameraState.flashTint.color),
availableSize: availableSize, availableSize: context.availableSize,
transition: .easeInOut(duration: 0.2) transition: .easeInOut(duration: 0.2)
) )
let frontFlashFrame = CGRect(origin: CGPoint(), size: context.availableSize)
context.add(frontFlash context.add(frontFlash
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) .position(frontFlashFrame.center)
.scale(1.5 - component.cameraState.flashTintSize * 0.5) .scale(1.5 - component.cameraState.flashTintSize * 0.5)
.appear(.default(alpha: true)) .appear(.default(alpha: true))
.disappear(ComponentTransition.Disappear({ view, transition, completion in .disappear(ComponentTransition.Disappear({ view, transition, completion in
@ -574,6 +584,15 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
) )
} }
let flipButtonBackground = flipButtonBackground.update(
component: GlassBackgroundComponent(
size: CGSize(width: 40.0, height: 40.0),
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
),
availableSize: CGSize(width: 40.0, height: 40.0),
transition: .immediate
)
let flipButton = flipButton.update( let flipButton = flipButton.update(
component: CameraButton( component: CameraButton(
content: AnyComponentWithIdentity( content: AnyComponentWithIdentity(
@ -581,12 +600,12 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
component: AnyComponent( component: AnyComponent(
Image( Image(
image: state.image(.flip, theme: environment.theme), image: state.image(.flip, theme: environment.theme),
tintColor: environment.theme.list.itemAccentColor, tintColor: environment.theme.chat.inputPanel.inputControlColor,
size: CGSize(width: 30.0, height: 30.0) size: CGSize(width: 30.0, height: 30.0)
) )
) )
), ),
minSize: CGSize(width: 44.0, height: 44.0), minSize: CGSize(width: 40.0, height: 40.0),
isExclusive: false, isExclusive: false,
action: { [weak state] in action: { [weak state] in
if let state { if let state {
@ -597,6 +616,12 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
availableSize: availableSize, availableSize: availableSize,
transition: context.transition transition: context.transition
) )
context.add(flipButtonBackground
.position(CGPoint(x: flipButton.size.width / 2.0 + 8.0, y: availableSize.height - flipButton.size.height / 2.0 - 8.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
context.add(flipButton context.add(flipButton
.position(CGPoint(x: flipButton.size.width / 2.0 + 8.0, y: availableSize.height - flipButton.size.height / 2.0 - 8.0)) .position(CGPoint(x: flipButton.size.width / 2.0 + 8.0, y: availableSize.height - flipButton.size.height / 2.0 - 8.0))
.appear(.default(scale: true, alpha: true)) .appear(.default(scale: true, alpha: true))
@ -620,7 +645,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
component: AnyComponent( component: AnyComponent(
LottieComponent( LottieComponent(
content: LottieComponent.AppBundleContent(name: flashIconName), content: LottieComponent.AppBundleContent(name: flashIconName),
color: environment.theme.list.itemAccentColor, color: environment.theme.chat.inputPanel.inputControlColor,
startingPosition: !component.cameraState.flashModeDidChange ? .end : .begin, startingPosition: !component.cameraState.flashModeDidChange ? .end : .begin,
size: CGSize(width: 40.0, height: 40.0), size: CGSize(width: 40.0, height: 40.0),
loop: false, loop: false,
@ -634,7 +659,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
component: AnyComponent( component: AnyComponent(
Image( Image(
image: state.image(.flash, theme: environment.theme), image: state.image(.flash, theme: environment.theme),
tintColor: environment.theme.list.itemAccentColor, tintColor: environment.theme.chat.inputPanel.inputControlColor,
size: CGSize(width: 30.0, height: 30.0) size: CGSize(width: 30.0, height: 30.0)
) )
) )
@ -645,7 +670,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let flashButton = flashButton.update( let flashButton = flashButton.update(
component: CameraButton( component: CameraButton(
content: flashContentComponent, content: flashContentComponent,
minSize: CGSize(width: 44.0, height: 44.0), minSize: CGSize(width: 40.0, height: 40.0),
isExclusive: false, isExclusive: false,
action: { [weak state] in action: { [weak state] in
if let state { if let state {
@ -659,6 +684,22 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
availableSize: availableSize, availableSize: availableSize,
transition: context.transition transition: context.transition
) )
let flashButtonBackground = flashButtonBackground.update(
component: GlassBackgroundComponent(
size: CGSize(width: 40.0, height: 40.0),
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
),
availableSize: CGSize(width: 40.0, height: 40.0),
transition: .immediate
)
context.add(flashButtonBackground
.position(CGPoint(x: flipButton.size.width + 8.0 + flashButton.size.width / 2.0 + 11.0, y: availableSize.height - flashButton.size.height / 2.0 - 8.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
context.add(flashButton context.add(flashButton
.position(CGPoint(x: flipButton.size.width + 8.0 + flashButton.size.width / 2.0 + 11.0, y: availableSize.height - flashButton.size.height / 2.0 - 8.0)) .position(CGPoint(x: flipButton.size.width + 8.0 + flashButton.size.width / 2.0 + 11.0, y: availableSize.height - flashButton.size.height / 2.0 - 8.0))
.appear(.default(scale: true, alpha: true)) .appear(.default(scale: true, alpha: true))
@ -686,7 +727,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
component: AnyComponent( component: AnyComponent(
BundleIconComponent( BundleIconComponent(
name: component.cameraState.isViewOnceEnabled ? "Media Gallery/ViewOnceEnabled" : "Media Gallery/ViewOnce", name: component.cameraState.isViewOnceEnabled ? "Media Gallery/ViewOnceEnabled" : "Media Gallery/ViewOnce",
tintColor: environment.theme.list.itemAccentColor tintColor: environment.theme.chat.inputPanel.inputControlColor
) )
) )
) )
@ -718,19 +759,17 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
ZStack([ ZStack([
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: "background", id: "background",
component: AnyComponent( component: AnyComponent(GlassBackgroundComponent(
Image( size: CGSize(width: 40.0, height: 40.0),
image: state.image(.buttonBackground, theme: environment.theme), tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
size: CGSize(width: 40.0, height: 40.0) ))
)
)
), ),
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: "icon", id: "icon",
component: AnyComponent( component: AnyComponent(
BundleIconComponent( BundleIconComponent(
name: "Chat/Input/Text/IconVideo", name: "Chat/Input/Text/IconVideo",
tintColor: environment.theme.list.itemAccentColor tintColor: environment.theme.chat.inputPanel.inputControlColor
) )
) )
) )
@ -745,7 +784,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
transition: context.transition transition: context.transition
) )
context.add(recordMoreButton context.add(recordMoreButton
.position(CGPoint(x: availableSize.width - recordMoreButton.size.width / 2.0 - 2.0 - UIScreenPixel, y: availableSize.height - recordMoreButton.size.height / 2.0 - 22.0)) .position(CGPoint(x: availableSize.width - recordMoreButton.size.width / 2.0 - 8.0, y: availableSize.height - recordMoreButton.size.height / 2.0 - 22.0))
.appear(.default(scale: true, alpha: true)) .appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true)) .disappear(.default(scale: true, alpha: true))
) )
@ -780,7 +819,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
) )
} }
return availableSize return context.availableSize
} }
} }
} }
@ -880,7 +919,6 @@ public class VideoMessageCameraScreen: ViewController {
self.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: self.presentationData.theme.overallDarkAppearance ? .dark : .light)) self.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: self.presentationData.theme.overallDarkAppearance ? .dark : .light))
self.containerView = UIView() self.containerView = UIView()
self.containerView.clipsToBounds = true
self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>() self.componentHost = ComponentView<ViewControllerComponentContainer.Environment>()
@ -1502,6 +1540,7 @@ public class VideoMessageCameraScreen: ViewController {
VideoMessageCameraScreenComponent( VideoMessageCameraScreenComponent(
context: self.context, context: self.context,
cameraState: self.cameraState, cameraState: self.cameraState,
containerSize: backgroundFrame.size,
previewFrame: previewFrame, previewFrame: previewFrame,
isPreviewing: self.previewState != nil || self.transitioningToPreview, isPreviewing: self.previewState != nil || self.transitioningToPreview,
isMuted: self.previewState?.isMuted ?? true, isMuted: self.previewState?.isMuted ?? true,
@ -1525,12 +1564,11 @@ public class VideoMessageCameraScreen: ViewController {
environment environment
}, },
forceUpdate: forceUpdate, forceUpdate: forceUpdate,
containerSize: backgroundFrame.size containerSize: actualBackgroundFrame.size
) )
if let componentView = self.componentHost.view { if let componentView = self.componentHost.view {
if componentView.superview == nil { if componentView.superview == nil {
self.containerView.addSubview(componentView) self.containerView.addSubview(componentView)
componentView.clipsToBounds = true
} }
let componentFrame = CGRect(origin: .zero, size: componentSize) let componentFrame = CGRect(origin: .zero, size: componentSize)