mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Camera and editor improvements
This commit is contained in:
parent
9ae260945c
commit
c3ed819d01
@ -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)
|
||||
@ -714,20 +742,6 @@ 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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user