Camera and editor improvements

This commit is contained in:
Ilya Laktyushin 2023-06-05 18:12:58 +04:00
parent 9ae260945c
commit c3ed819d01
3 changed files with 82 additions and 33 deletions

View File

@ -518,7 +518,19 @@ private final class StoryContainerScreenComponent: Component {
let slice = currentSlices[i]
let cubeAdditionalRotationFraction: CGFloat
if i == focusedIndex {
cubeAdditionalRotationFraction = 0.0
} else if i < focusedIndex {
cubeAdditionalRotationFraction = -1.0
} else {
cubeAdditionalRotationFraction = 1.0
}
var panFraction: CGFloat = 0.0
if let itemSetPanState = self.itemSetPanState {
panFraction = -itemSetPanState.fraction
if self.visibleItemSetViews[slice.peer.id] != nil {
isItemVisible = true
}
@ -543,14 +555,16 @@ private final class StoryContainerScreenComponent: Component {
self.visibleItemSetViews[slice.peer.id] = itemSetView
}
let itemContainerSize: CGSize
var itemSetContainerSize = availableSize
var itemSetContainerTopInset = environment.statusBarHeight + 12.0
var itemSetContainerSafeInsets = environment.safeInsets
if case .regular = environment.metrics.widthClass {
let availableHeight = availableSize.height - max(45.0, environment.safeInsets.bottom) * 2.0
let mediaHeight = min(1040.0, availableHeight - 90.0)
let mediaWidth = floorToScreenPixels(mediaHeight * 0.5625)
itemContainerSize = CGSize(width: mediaWidth, height: availableHeight)
} else {
itemContainerSize = availableSize
let availableHeight = min(1080.0, availableSize.height - max(45.0, environment.safeInsets.bottom) * 2.0)
let mediaHeight = availableHeight - 40.0
let mediaWidth = floor(mediaHeight * 0.5625)
itemSetContainerSize = CGSize(width: mediaWidth, height: availableHeight)
itemSetContainerTopInset = 0.0
itemSetContainerSafeInsets.bottom = 0.0
}
let _ = itemSetView.view.update(
@ -561,11 +575,13 @@ private final class StoryContainerScreenComponent: Component {
slice: slice,
theme: environment.theme,
strings: environment.strings,
containerInsets: UIEdgeInsets(top: environment.statusBarHeight + 12.0, left: 0.0, bottom: environment.inputHeight, right: 0.0),
safeInsets: environment.safeInsets,
containerInsets: UIEdgeInsets(top: itemSetContainerTopInset, left: 0.0, bottom: environment.inputHeight, right: 0.0),
safeInsets: itemSetContainerSafeInsets,
inputHeight: environment.inputHeight,
metrics: environment.metrics,
isProgressPaused: isProgressPaused || i != focusedIndex,
hideUI: i == focusedIndex && self.itemSetPanState?.didBegin == false,
visibilityFraction: 1.0 - abs(panFraction + cubeAdditionalRotationFraction),
presentController: { [weak self] c in
guard let self, let environment = self.environment else {
return
@ -641,14 +657,14 @@ private final class StoryContainerScreenComponent: Component {
}
)),
environment: {},
containerSize: itemContainerSize
containerSize: itemSetContainerSize
)
if i == focusedIndex {
contentDerivedBottomInset = itemSetView.externalState.derivedBottomInset
}
let itemFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - itemContainerSize.width) / 2.0), y: floorToScreenPixels((availableSize.height - itemContainerSize.height) / 2.0)), size: itemContainerSize)
let itemFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - itemSetContainerSize.width) / 2.0), y: floorToScreenPixels((availableSize.height - itemSetContainerSize.height) / 2.0)), size: itemSetContainerSize)
if let itemSetComponentView = itemSetView.view.view {
if itemSetView.superview == nil {
self.addSubview(itemSetView)
@ -666,13 +682,25 @@ private final class StoryContainerScreenComponent: Component {
itemSetTransition.setPosition(view: itemSetComponentView, position: CGRect(origin: CGPoint(), size: itemFrame.size).center)
itemSetTransition.setBounds(view: itemSetComponentView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
itemSetTransition.setPosition(layer: itemSetView.tintLayer, position: CGRect(origin: CGPoint(), size: itemFrame.size).center)
itemSetTransition.setBounds(layer: itemSetView.tintLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
let itemTintSize: CGSize
if case .regular = environment.metrics.widthClass {
itemTintSize = itemSetView.externalState.derivedMediaSize
} else {
itemTintSize = itemFrame.size
}
itemSetTransition.setPosition(layer: itemSetView.tintLayer, position: CGRect(origin: CGPoint(), size: itemTintSize).center)
itemSetTransition.setBounds(layer: itemSetView.tintLayer, bounds: CGRect(origin: CGPoint(), size: itemTintSize))
let perspectiveConstant: CGFloat = 500.0
let width = itemFrame.width
let sideDistance: CGFloat = 40.0
let sideDistance: CGFloat
if case .regular = environment.metrics.widthClass {
sideDistance = 0.0
} else {
sideDistance = 40.0
}
let sideAngle_d: CGFloat = -pow(perspectiveConstant, 2)*pow(sideDistance, 2)
let sideAngle_e: CGFloat = pow(perspectiveConstant, 2)*pow(width, 2)
@ -713,21 +741,7 @@ private final class StoryContainerScreenComponent: Component {
return targetTransform
}
let cubeAdditionalRotationFraction: CGFloat
if i == focusedIndex {
cubeAdditionalRotationFraction = 0.0
} else if i < focusedIndex {
cubeAdditionalRotationFraction = -1.0
} else {
cubeAdditionalRotationFraction = 1.0
}
var panFraction: CGFloat = 0.0
if let itemSetPanState = self.itemSetPanState {
panFraction = -itemSetPanState.fraction
}
Transition.immediate.setTransform(view: itemSetComponentView, transform: faceTransform)
Transition.immediate.setTransform(layer: itemSetView.tintLayer, transform: faceTransform)

View File

@ -21,6 +21,7 @@ import AvatarNode
public final class StoryItemSetContainerComponent: Component {
public final class ExternalState {
public fileprivate(set) var derivedBottomInset: CGFloat = 0.0
public fileprivate(set) var derivedMediaSize: CGSize = .zero
public init() {
}
@ -39,8 +40,10 @@ public final class StoryItemSetContainerComponent: Component {
public let containerInsets: UIEdgeInsets
public let safeInsets: UIEdgeInsets
public let inputHeight: CGFloat
public let metrics: LayoutMetrics
public let isProgressPaused: Bool
public let hideUI: Bool
public let visibilityFraction: CGFloat
public let presentController: (ViewController) -> Void
public let close: () -> Void
public let navigate: (NavigationDirection) -> Void
@ -56,8 +59,10 @@ public final class StoryItemSetContainerComponent: Component {
containerInsets: UIEdgeInsets,
safeInsets: UIEdgeInsets,
inputHeight: CGFloat,
metrics: LayoutMetrics,
isProgressPaused: Bool,
hideUI: Bool,
visibilityFraction: CGFloat,
presentController: @escaping (ViewController) -> Void,
close: @escaping () -> Void,
navigate: @escaping (NavigationDirection) -> Void,
@ -72,8 +77,10 @@ public final class StoryItemSetContainerComponent: Component {
self.containerInsets = containerInsets
self.safeInsets = safeInsets
self.inputHeight = inputHeight
self.metrics = metrics
self.isProgressPaused = isProgressPaused
self.hideUI = hideUI
self.visibilityFraction = visibilityFraction
self.presentController = presentController
self.close = close
self.navigate = navigate
@ -103,12 +110,18 @@ public final class StoryItemSetContainerComponent: Component {
if lhs.inputHeight != rhs.inputHeight {
return false
}
if lhs.metrics != rhs.metrics {
return false
}
if lhs.isProgressPaused != rhs.isProgressPaused {
return false
}
if lhs.hideUI != rhs.hideUI {
return false
}
if lhs.visibilityFraction != rhs.visibilityFraction {
return false
}
return true
}
@ -1283,12 +1296,16 @@ public final class StoryItemSetContainerComponent: Component {
self.itemLayout = itemLayout
let inputPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize)
var inputPanelAlpha: CGFloat = focusedItem?.isMy == true ? 0.0 : 1.0
if case .regular = component.metrics.widthClass {
inputPanelAlpha *= component.visibilityFraction
}
if let inputPanelView = self.inputPanel.view {
if inputPanelView.superview == nil {
self.addSubview(inputPanelView)
}
transition.setFrame(view: inputPanelView, frame: inputPanelFrame)
transition.setAlpha(view: inputPanelView, alpha: focusedItem?.isMy == true ? 0.0 : 1.0)
transition.setAlpha(view: inputPanelView, alpha: inputPanelAlpha)
}
if let captionItem = self.captionItem, captionItem.itemId != component.slice.item.storyItem.id {
@ -1543,6 +1560,10 @@ public final class StoryItemSetContainerComponent: Component {
}
var footerPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - inputPanelBottomInset - footerPanelSize.height), size: footerPanelSize)
var footerPanelAlpha: CGFloat = (focusedItem?.isMy == true && !self.displayViewList) ? 1.0 : 0.0
if case .regular = component.metrics.widthClass {
footerPanelAlpha *= component.visibilityFraction
}
if self.displayViewList {
footerPanelFrame.origin.y += footerPanelSize.height
}
@ -1551,7 +1572,7 @@ public final class StoryItemSetContainerComponent: Component {
self.addSubview(footerPanelView)
}
transition.setFrame(view: footerPanelView, frame: footerPanelFrame)
transition.setAlpha(view: footerPanelView, alpha: (focusedItem?.isMy == true && !self.displayViewList) ? 1.0 : 0.0)
transition.setAlpha(view: footerPanelView, alpha: footerPanelAlpha)
}
let bottomGradientHeight = inputPanelSize.height + 32.0
@ -1650,6 +1671,7 @@ public final class StoryItemSetContainerComponent: Component {
}
}
component.externalState.derivedMediaSize = contentFrame.size
component.externalState.derivedBottomInset = availableSize.height - min(inputPanelFrame.minY, contentFrame.maxY)
return contentSize

View File

@ -8,6 +8,7 @@ import FFMpegBinding
import LocalMediaResources
import LegacyMediaPickerUI
import MediaEditor
import Photos
private final class AVURLAssetCopyItem: MediaResourceDataFetchCopyLocalItem {
private let url: URL
@ -268,10 +269,22 @@ public func fetchVideoLibraryMediaResource(account: Account, resource: VideoLibr
var value = stat()
if stat(tempFile.path, &value) == 0 {
let remuxedTempFile = TempBox.shared.tempFile(fileName: "video.mp4")
if let size = fileSize(tempFile.path), size <= 32 * 1024 * 1024, FFMpegRemuxer.remux(tempFile.path, to: remuxedTempFile.path) {
if !"".isEmpty, let size = fileSize(tempFile.path), size <= 32 * 1024 * 1024, FFMpegRemuxer.remux(tempFile.path, to: remuxedTempFile.path) {
TempBox.shared.dispose(tempFile)
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
} else {
let tempVideoPath = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max)).mp4"
if let _ = try? FileManager.default.copyItem(atPath: tempFile.path, toPath: tempVideoPath) {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: tempVideoPath))
}, completionHandler: { _, error in
if let error = error {
print("\(error)")
}
let _ = try? FileManager.default.removeItem(atPath: tempVideoPath)
})
}
TempBox.shared.dispose(remuxedTempFile)
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path), options: [.mappedRead]) {
var range: Range<Int64>?
@ -424,7 +437,7 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
var value = stat()
if stat(tempFile.path, &value) == 0 {
let remuxedTempFile = TempBox.shared.tempFile(fileName: "video.mp4")
if let size = fileSize(tempFile.path), size <= 32 * 1024 * 1024, FFMpegRemuxer.remux(tempFile.path, to: remuxedTempFile.path) {
if !"".isEmpty, let size = fileSize(tempFile.path), size <= 32 * 1024 * 1024, FFMpegRemuxer.remux(tempFile.path, to: remuxedTempFile.path) {
TempBox.shared.dispose(tempFile)
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
} else {