Various fixes

This commit is contained in:
Ilya Laktyushin
2024-07-21 00:29:07 +04:00
parent dfc5077946
commit b4415c251b
9 changed files with 306 additions and 278 deletions

View File

@@ -1198,6 +1198,7 @@ final class MediaEditorScreenComponent: Component {
let displayTopButtons = !(self.inputPanelExternalState.isEditing || isEditingTextEntity || component.isDisplayingTool != nil)
var inputPanelSize: CGSize = .zero
if case .storyEditor = controller.mode {
let nextInputMode: MessageInputPanelComponent.InputMode
switch self.currentInputMode {
@@ -1217,7 +1218,7 @@ final class MediaEditorScreenComponent: Component {
}
self.inputPanel.parentState = state
let inputPanelSize = self.inputPanel.update(
inputPanelSize = self.inputPanel.update(
transition: transition,
component: AnyComponent(MessageInputPanelComponent(
externalState: self.inputPanelExternalState,
@@ -1429,192 +1430,7 @@ final class MediaEditorScreenComponent: Component {
transition.setFrame(view: inputPanelView, frame: inputPanelFrame)
transition.setAlpha(view: inputPanelView, alpha: isEditingTextEntity || component.isDisplayingTool != nil || component.isDismissing || component.isInteractingWithEntities ? 0.0 : 1.0)
}
if let playerState = state.playerState {
let scrubberInset: CGFloat = 9.0
let minDuration: Double
let maxDuration: Double
if playerState.isAudioOnly {
minDuration = 5.0
maxDuration = 15.0
} else {
minDuration = 1.0
maxDuration = storyMaxVideoDuration
}
let previousTrackCount = self.currentVisibleTracks?.count
let visibleTracks = playerState.tracks.filter { $0.visibleInTimeline }.map { MediaScrubberComponent.Track($0) }
self.currentVisibleTracks = visibleTracks
var scrubberTransition = transition
if let previousTrackCount, previousTrackCount != visibleTracks.count {
scrubberTransition = .easeInOut(duration: 0.2)
}
let isAudioOnly = playerState.isAudioOnly
let hasMainVideoTrack = playerState.tracks.contains(where: { $0.id == 0 })
let scrubber: ComponentView<Empty>
if let current = self.scrubber {
scrubber = current
} else {
scrubber = ComponentView<Empty>()
self.scrubber = scrubber
}
let scrubberSize = scrubber.update(
transition: scrubberTransition,
component: AnyComponent(MediaScrubberComponent(
context: component.context,
style: .editor,
theme: environment.theme,
generationTimestamp: playerState.generationTimestamp,
position: playerState.position,
minDuration: minDuration,
maxDuration: maxDuration,
isPlaying: playerState.isPlaying,
tracks: visibleTracks,
positionUpdated: { [weak mediaEditor] position, apply in
if let mediaEditor {
mediaEditor.seek(position, andPlay: apply)
}
},
trackTrimUpdated: { [weak mediaEditor] trackId, start, end, updatedEnd, apply in
guard let mediaEditor else {
return
}
let trimRange = start..<end
if trackId == 2 {
mediaEditor.setAudioTrackTrimRange(trimRange, apply: apply)
if isAudioOnly {
let offset = (mediaEditor.values.audioTrackOffset ?? 0.0)
if apply {
mediaEditor.seek(offset + start, andPlay: true)
} else {
mediaEditor.seek(offset + start, andPlay: false)
mediaEditor.stop()
}
} else {
if apply {
mediaEditor.play()
} else {
mediaEditor.stop()
}
}
} else if trackId == 1 {
mediaEditor.setAdditionalVideoTrimRange(trimRange, apply: apply)
if hasMainVideoTrack {
if apply {
mediaEditor.play()
} else {
mediaEditor.stop()
}
} else {
if apply {
mediaEditor.seek(start, andPlay: true)
} else {
mediaEditor.seek(updatedEnd ? end : start, andPlay: false)
}
}
} else {
mediaEditor.setVideoTrimRange(trimRange, apply: apply)
if apply {
mediaEditor.seek(start, andPlay: true)
} else {
mediaEditor.seek(updatedEnd ? end : start, andPlay: false)
}
}
},
trackOffsetUpdated: { trackId, offset, apply in
guard let mediaEditor else {
return
}
if trackId == 2 {
mediaEditor.setAudioTrackOffset(offset, apply: apply)
if isAudioOnly {
let offset = (mediaEditor.values.audioTrackOffset ?? 0.0)
let start = (mediaEditor.values.audioTrackTrimRange?.lowerBound ?? 0.0)
if apply {
mediaEditor.seek(offset + start, andPlay: true)
} else {
mediaEditor.seek(offset + start, andPlay: false)
mediaEditor.stop()
}
} else {
if apply {
let audioStart = mediaEditor.values.audioTrackTrimRange?.lowerBound ?? 0.0
let audioOffset = min(0.0, mediaEditor.values.audioTrackOffset ?? 0.0)
var start = -audioOffset + audioStart
if let duration = mediaEditor.duration {
let lowerBound = mediaEditor.values.videoTrimRange?.lowerBound ?? 0.0
let upperBound = mediaEditor.values.videoTrimRange?.upperBound ?? duration
if start >= upperBound {
start = lowerBound
} else if start < lowerBound {
start = lowerBound
}
}
mediaEditor.seek(start, andPlay: true)
mediaEditor.play()
} else {
mediaEditor.stop()
}
}
} else if trackId == 1 {
mediaEditor.setAdditionalVideoOffset(offset, apply: apply)
}
},
trackLongPressed: { [weak controller] trackId, sourceView in
guard let controller else {
return
}
controller.node.presentTrackOptions(trackId: trackId, sourceView: sourceView)
}
)),
environment: {},
containerSize: CGSize(width: previewSize.width - scrubberInset * 2.0, height: availableSize.height)
)
let scrubberFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - scrubberSize.width) / 2.0), y: availableSize.height - environment.safeInsets.bottom - scrubberSize.height + controlsBottomInset - inputPanelSize.height + 3.0), size: scrubberSize)
if let scrubberView = scrubber.view {
var animateIn = false
if scrubberView.superview == nil {
animateIn = true
if let inputPanelBackgroundView = self.inputPanelBackground.view, inputPanelBackgroundView.superview != nil {
self.insertSubview(scrubberView, belowSubview: inputPanelBackgroundView)
} else {
self.addSubview(scrubberView)
}
}
if animateIn {
scrubberView.frame = scrubberFrame
} else {
scrubberTransition.setFrame(view: scrubberView, frame: scrubberFrame)
}
if !self.animatingButtons && !(!hasMainVideoTrack && animateIn) {
transition.setAlpha(view: scrubberView, alpha: component.isDisplayingTool != nil || component.isDismissing || component.isInteractingWithEntities || isEditingCaption || isRecordingAdditionalVideo || isEditingTextEntity ? 0.0 : 1.0)
} else if animateIn {
scrubberView.layer.animatePosition(from: CGPoint(x: 0.0, y: 44.0), to: .zero, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
scrubberView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
scrubberView.layer.animateScale(from: 0.6, to: 1.0, duration: 0.2)
}
}
} else {
if let scrubber = self.scrubber {
self.scrubber = nil
if let scrubberView = scrubber.view {
scrubberView.layer.animatePosition(from: .zero, to: CGPoint(x: 0.0, y: 44.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
scrubberView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
scrubberView.removeFromSuperview()
})
scrubberView.layer.animateScale(from: 1.0, to: 0.6, duration: 0.2, removeOnCompletion: false)
}
}
}
let saveContentComponent: AnyComponentWithIdentity<Empty>
if component.hasAppeared {
saveContentComponent = AnyComponentWithIdentity(
@@ -1971,8 +1787,199 @@ final class MediaEditorScreenComponent: Component {
transition.setScale(view: switchCameraButtonView, scale: isRecordingAdditionalVideo ? 1.0 : 0.01)
transition.setAlpha(view: switchCameraButtonView, alpha: isRecordingAdditionalVideo ? 1.0 : 0.0)
}
} else {
inputPanelSize = CGSize(width: 0.0, height: 12.0)
}
if case .stickerEditor = controller.mode {
} else {
if let playerState = state.playerState {
let scrubberInset: CGFloat = 9.0
let minDuration: Double
let maxDuration: Double
if playerState.isAudioOnly {
minDuration = 5.0
maxDuration = 15.0
} else {
minDuration = 1.0
maxDuration = storyMaxVideoDuration
}
let previousTrackCount = self.currentVisibleTracks?.count
let visibleTracks = playerState.tracks.filter { $0.visibleInTimeline }.map { MediaScrubberComponent.Track($0) }
self.currentVisibleTracks = visibleTracks
var scrubberTransition = transition
if let previousTrackCount, previousTrackCount != visibleTracks.count {
scrubberTransition = .easeInOut(duration: 0.2)
}
let isAudioOnly = playerState.isAudioOnly
let hasMainVideoTrack = playerState.tracks.contains(where: { $0.id == 0 })
let scrubber: ComponentView<Empty>
if let current = self.scrubber {
scrubber = current
} else {
scrubber = ComponentView<Empty>()
self.scrubber = scrubber
}
let scrubberSize = scrubber.update(
transition: scrubberTransition,
component: AnyComponent(MediaScrubberComponent(
context: component.context,
style: .editor,
theme: environment.theme,
generationTimestamp: playerState.generationTimestamp,
position: playerState.position,
minDuration: minDuration,
maxDuration: maxDuration,
isPlaying: playerState.isPlaying,
tracks: visibleTracks,
positionUpdated: { [weak mediaEditor] position, apply in
if let mediaEditor {
mediaEditor.seek(position, andPlay: apply)
}
},
trackTrimUpdated: { [weak mediaEditor] trackId, start, end, updatedEnd, apply in
guard let mediaEditor else {
return
}
let trimRange = start..<end
if trackId == 2 {
mediaEditor.setAudioTrackTrimRange(trimRange, apply: apply)
if isAudioOnly {
let offset = (mediaEditor.values.audioTrackOffset ?? 0.0)
if apply {
mediaEditor.seek(offset + start, andPlay: true)
} else {
mediaEditor.seek(offset + start, andPlay: false)
mediaEditor.stop()
}
} else {
if apply {
mediaEditor.play()
} else {
mediaEditor.stop()
}
}
} else if trackId == 1 {
mediaEditor.setAdditionalVideoTrimRange(trimRange, apply: apply)
if hasMainVideoTrack {
if apply {
mediaEditor.play()
} else {
mediaEditor.stop()
}
} else {
if apply {
mediaEditor.seek(start, andPlay: true)
} else {
mediaEditor.seek(updatedEnd ? end : start, andPlay: false)
}
}
} else {
mediaEditor.setVideoTrimRange(trimRange, apply: apply)
if apply {
mediaEditor.seek(start, andPlay: true)
} else {
mediaEditor.seek(updatedEnd ? end : start, andPlay: false)
}
}
},
trackOffsetUpdated: { trackId, offset, apply in
guard let mediaEditor else {
return
}
if trackId == 2 {
mediaEditor.setAudioTrackOffset(offset, apply: apply)
if isAudioOnly {
let offset = (mediaEditor.values.audioTrackOffset ?? 0.0)
let start = (mediaEditor.values.audioTrackTrimRange?.lowerBound ?? 0.0)
if apply {
mediaEditor.seek(offset + start, andPlay: true)
} else {
mediaEditor.seek(offset + start, andPlay: false)
mediaEditor.stop()
}
} else {
if apply {
let audioStart = mediaEditor.values.audioTrackTrimRange?.lowerBound ?? 0.0
let audioOffset = min(0.0, mediaEditor.values.audioTrackOffset ?? 0.0)
var start = -audioOffset + audioStart
if let duration = mediaEditor.duration {
let lowerBound = mediaEditor.values.videoTrimRange?.lowerBound ?? 0.0
let upperBound = mediaEditor.values.videoTrimRange?.upperBound ?? duration
if start >= upperBound {
start = lowerBound
} else if start < lowerBound {
start = lowerBound
}
}
mediaEditor.seek(start, andPlay: true)
mediaEditor.play()
} else {
mediaEditor.stop()
}
}
} else if trackId == 1 {
mediaEditor.setAdditionalVideoOffset(offset, apply: apply)
}
},
trackLongPressed: { [weak controller] trackId, sourceView in
guard let controller else {
return
}
controller.node.presentTrackOptions(trackId: trackId, sourceView: sourceView)
}
)),
environment: {},
containerSize: CGSize(width: previewSize.width - scrubberInset * 2.0, height: availableSize.height)
)
let scrubberFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - scrubberSize.width) / 2.0), y: availableSize.height - environment.safeInsets.bottom - scrubberSize.height + controlsBottomInset - inputPanelSize.height + 3.0), size: scrubberSize)
if let scrubberView = scrubber.view {
var animateIn = false
if scrubberView.superview == nil {
animateIn = true
if let inputPanelBackgroundView = self.inputPanelBackground.view, inputPanelBackgroundView.superview != nil {
self.insertSubview(scrubberView, belowSubview: inputPanelBackgroundView)
} else {
self.addSubview(scrubberView)
}
}
if animateIn {
scrubberView.frame = scrubberFrame
} else {
scrubberTransition.setFrame(view: scrubberView, frame: scrubberFrame)
}
if !self.animatingButtons && !(!hasMainVideoTrack && animateIn) {
transition.setAlpha(view: scrubberView, alpha: component.isDisplayingTool != nil || component.isDismissing || component.isInteractingWithEntities || isEditingCaption || isRecordingAdditionalVideo || isEditingTextEntity ? 0.0 : 1.0)
} else if animateIn {
scrubberView.layer.animatePosition(from: CGPoint(x: 0.0, y: 44.0), to: .zero, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
scrubberView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
scrubberView.layer.animateScale(from: 0.6, to: 1.0, duration: 0.2)
}
}
} else {
if let scrubber = self.scrubber {
self.scrubber = nil
if let scrubberView = scrubber.view {
scrubberView.layer.animatePosition(from: .zero, to: CGPoint(x: 0.0, y: 44.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)
scrubberView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
scrubberView.removeFromSuperview()
})
scrubberView.layer.animateScale(from: 1.0, to: 0.6, duration: 0.2, removeOnCompletion: false)
}
}
}
}
if case .stickerEditor = controller.mode {
var stickerButtonsHidden = buttonsAreHidden
if let displayingTool = component.isDisplayingTool, [.cutoutErase, .cutoutRestore].contains(displayingTool) {