mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Various fixes
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user