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 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 {
|
if let itemSetPanState = self.itemSetPanState {
|
||||||
|
panFraction = -itemSetPanState.fraction
|
||||||
|
|
||||||
if self.visibleItemSetViews[slice.peer.id] != nil {
|
if self.visibleItemSetViews[slice.peer.id] != nil {
|
||||||
isItemVisible = true
|
isItemVisible = true
|
||||||
}
|
}
|
||||||
@ -543,14 +555,16 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
self.visibleItemSetViews[slice.peer.id] = itemSetView
|
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 {
|
if case .regular = environment.metrics.widthClass {
|
||||||
let availableHeight = availableSize.height - max(45.0, environment.safeInsets.bottom) * 2.0
|
let availableHeight = min(1080.0, availableSize.height - max(45.0, environment.safeInsets.bottom) * 2.0)
|
||||||
let mediaHeight = min(1040.0, availableHeight - 90.0)
|
let mediaHeight = availableHeight - 40.0
|
||||||
let mediaWidth = floorToScreenPixels(mediaHeight * 0.5625)
|
let mediaWidth = floor(mediaHeight * 0.5625)
|
||||||
itemContainerSize = CGSize(width: mediaWidth, height: availableHeight)
|
itemSetContainerSize = CGSize(width: mediaWidth, height: availableHeight)
|
||||||
} else {
|
itemSetContainerTopInset = 0.0
|
||||||
itemContainerSize = availableSize
|
itemSetContainerSafeInsets.bottom = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = itemSetView.view.update(
|
let _ = itemSetView.view.update(
|
||||||
@ -561,11 +575,13 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
slice: slice,
|
slice: slice,
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
strings: environment.strings,
|
strings: environment.strings,
|
||||||
containerInsets: UIEdgeInsets(top: environment.statusBarHeight + 12.0, left: 0.0, bottom: environment.inputHeight, right: 0.0),
|
containerInsets: UIEdgeInsets(top: itemSetContainerTopInset, left: 0.0, bottom: environment.inputHeight, right: 0.0),
|
||||||
safeInsets: environment.safeInsets,
|
safeInsets: itemSetContainerSafeInsets,
|
||||||
inputHeight: environment.inputHeight,
|
inputHeight: environment.inputHeight,
|
||||||
|
metrics: environment.metrics,
|
||||||
isProgressPaused: isProgressPaused || i != focusedIndex,
|
isProgressPaused: isProgressPaused || i != focusedIndex,
|
||||||
hideUI: i == focusedIndex && self.itemSetPanState?.didBegin == false,
|
hideUI: i == focusedIndex && self.itemSetPanState?.didBegin == false,
|
||||||
|
visibilityFraction: 1.0 - abs(panFraction + cubeAdditionalRotationFraction),
|
||||||
presentController: { [weak self] c in
|
presentController: { [weak self] c in
|
||||||
guard let self, let environment = self.environment else {
|
guard let self, let environment = self.environment else {
|
||||||
return
|
return
|
||||||
@ -641,14 +657,14 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: itemContainerSize
|
containerSize: itemSetContainerSize
|
||||||
)
|
)
|
||||||
|
|
||||||
if i == focusedIndex {
|
if i == focusedIndex {
|
||||||
contentDerivedBottomInset = itemSetView.externalState.derivedBottomInset
|
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 let itemSetComponentView = itemSetView.view.view {
|
||||||
if itemSetView.superview == nil {
|
if itemSetView.superview == nil {
|
||||||
self.addSubview(itemSetView)
|
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.setPosition(view: itemSetComponentView, position: CGRect(origin: CGPoint(), size: itemFrame.size).center)
|
||||||
itemSetTransition.setBounds(view: itemSetComponentView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
|
itemSetTransition.setBounds(view: itemSetComponentView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
|
||||||
|
|
||||||
itemSetTransition.setPosition(layer: itemSetView.tintLayer, position: CGRect(origin: CGPoint(), size: itemFrame.size).center)
|
let itemTintSize: CGSize
|
||||||
itemSetTransition.setBounds(layer: itemSetView.tintLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
|
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 perspectiveConstant: CGFloat = 500.0
|
||||||
let width = itemFrame.width
|
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_d: CGFloat = -pow(perspectiveConstant, 2)*pow(sideDistance, 2)
|
||||||
let sideAngle_e: CGFloat = pow(perspectiveConstant, 2)*pow(width, 2)
|
let sideAngle_e: CGFloat = pow(perspectiveConstant, 2)*pow(width, 2)
|
||||||
@ -713,21 +741,7 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
|
|
||||||
return targetTransform
|
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(view: itemSetComponentView, transform: faceTransform)
|
||||||
Transition.immediate.setTransform(layer: itemSetView.tintLayer, transform: faceTransform)
|
Transition.immediate.setTransform(layer: itemSetView.tintLayer, transform: faceTransform)
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import AvatarNode
|
|||||||
public final class StoryItemSetContainerComponent: Component {
|
public final class StoryItemSetContainerComponent: Component {
|
||||||
public final class ExternalState {
|
public final class ExternalState {
|
||||||
public fileprivate(set) var derivedBottomInset: CGFloat = 0.0
|
public fileprivate(set) var derivedBottomInset: CGFloat = 0.0
|
||||||
|
public fileprivate(set) var derivedMediaSize: CGSize = .zero
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
}
|
}
|
||||||
@ -39,8 +40,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
public let containerInsets: UIEdgeInsets
|
public let containerInsets: UIEdgeInsets
|
||||||
public let safeInsets: UIEdgeInsets
|
public let safeInsets: UIEdgeInsets
|
||||||
public let inputHeight: CGFloat
|
public let inputHeight: CGFloat
|
||||||
|
public let metrics: LayoutMetrics
|
||||||
public let isProgressPaused: Bool
|
public let isProgressPaused: Bool
|
||||||
public let hideUI: Bool
|
public let hideUI: Bool
|
||||||
|
public let visibilityFraction: CGFloat
|
||||||
public let presentController: (ViewController) -> Void
|
public let presentController: (ViewController) -> Void
|
||||||
public let close: () -> Void
|
public let close: () -> Void
|
||||||
public let navigate: (NavigationDirection) -> Void
|
public let navigate: (NavigationDirection) -> Void
|
||||||
@ -56,8 +59,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
containerInsets: UIEdgeInsets,
|
containerInsets: UIEdgeInsets,
|
||||||
safeInsets: UIEdgeInsets,
|
safeInsets: UIEdgeInsets,
|
||||||
inputHeight: CGFloat,
|
inputHeight: CGFloat,
|
||||||
|
metrics: LayoutMetrics,
|
||||||
isProgressPaused: Bool,
|
isProgressPaused: Bool,
|
||||||
hideUI: Bool,
|
hideUI: Bool,
|
||||||
|
visibilityFraction: CGFloat,
|
||||||
presentController: @escaping (ViewController) -> Void,
|
presentController: @escaping (ViewController) -> Void,
|
||||||
close: @escaping () -> Void,
|
close: @escaping () -> Void,
|
||||||
navigate: @escaping (NavigationDirection) -> Void,
|
navigate: @escaping (NavigationDirection) -> Void,
|
||||||
@ -72,8 +77,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
self.containerInsets = containerInsets
|
self.containerInsets = containerInsets
|
||||||
self.safeInsets = safeInsets
|
self.safeInsets = safeInsets
|
||||||
self.inputHeight = inputHeight
|
self.inputHeight = inputHeight
|
||||||
|
self.metrics = metrics
|
||||||
self.isProgressPaused = isProgressPaused
|
self.isProgressPaused = isProgressPaused
|
||||||
self.hideUI = hideUI
|
self.hideUI = hideUI
|
||||||
|
self.visibilityFraction = visibilityFraction
|
||||||
self.presentController = presentController
|
self.presentController = presentController
|
||||||
self.close = close
|
self.close = close
|
||||||
self.navigate = navigate
|
self.navigate = navigate
|
||||||
@ -103,12 +110,18 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
if lhs.inputHeight != rhs.inputHeight {
|
if lhs.inputHeight != rhs.inputHeight {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.metrics != rhs.metrics {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.isProgressPaused != rhs.isProgressPaused {
|
if lhs.isProgressPaused != rhs.isProgressPaused {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.hideUI != rhs.hideUI {
|
if lhs.hideUI != rhs.hideUI {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.visibilityFraction != rhs.visibilityFraction {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,12 +1296,16 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
self.itemLayout = itemLayout
|
self.itemLayout = itemLayout
|
||||||
|
|
||||||
let inputPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize)
|
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 let inputPanelView = self.inputPanel.view {
|
||||||
if inputPanelView.superview == nil {
|
if inputPanelView.superview == nil {
|
||||||
self.addSubview(inputPanelView)
|
self.addSubview(inputPanelView)
|
||||||
}
|
}
|
||||||
transition.setFrame(view: inputPanelView, frame: inputPanelFrame)
|
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 {
|
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 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 {
|
if self.displayViewList {
|
||||||
footerPanelFrame.origin.y += footerPanelSize.height
|
footerPanelFrame.origin.y += footerPanelSize.height
|
||||||
}
|
}
|
||||||
@ -1551,7 +1572,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
self.addSubview(footerPanelView)
|
self.addSubview(footerPanelView)
|
||||||
}
|
}
|
||||||
transition.setFrame(view: footerPanelView, frame: footerPanelFrame)
|
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
|
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)
|
component.externalState.derivedBottomInset = availableSize.height - min(inputPanelFrame.minY, contentFrame.maxY)
|
||||||
|
|
||||||
return contentSize
|
return contentSize
|
||||||
|
@ -8,6 +8,7 @@ import FFMpegBinding
|
|||||||
import LocalMediaResources
|
import LocalMediaResources
|
||||||
import LegacyMediaPickerUI
|
import LegacyMediaPickerUI
|
||||||
import MediaEditor
|
import MediaEditor
|
||||||
|
import Photos
|
||||||
|
|
||||||
private final class AVURLAssetCopyItem: MediaResourceDataFetchCopyLocalItem {
|
private final class AVURLAssetCopyItem: MediaResourceDataFetchCopyLocalItem {
|
||||||
private let url: URL
|
private let url: URL
|
||||||
@ -268,10 +269,22 @@ public func fetchVideoLibraryMediaResource(account: Account, resource: VideoLibr
|
|||||||
var value = stat()
|
var value = stat()
|
||||||
if stat(tempFile.path, &value) == 0 {
|
if stat(tempFile.path, &value) == 0 {
|
||||||
let remuxedTempFile = TempBox.shared.tempFile(fileName: "video.mp4")
|
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)
|
TempBox.shared.dispose(tempFile)
|
||||||
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
|
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
|
||||||
} else {
|
} 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)
|
TempBox.shared.dispose(remuxedTempFile)
|
||||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path), options: [.mappedRead]) {
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path), options: [.mappedRead]) {
|
||||||
var range: Range<Int64>?
|
var range: Range<Int64>?
|
||||||
@ -424,7 +437,7 @@ func fetchLocalFileVideoMediaResource(account: Account, resource: LocalFileVideo
|
|||||||
var value = stat()
|
var value = stat()
|
||||||
if stat(tempFile.path, &value) == 0 {
|
if stat(tempFile.path, &value) == 0 {
|
||||||
let remuxedTempFile = TempBox.shared.tempFile(fileName: "video.mp4")
|
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)
|
TempBox.shared.dispose(tempFile)
|
||||||
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
|
subscriber.putNext(.moveTempFile(file: remuxedTempFile))
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user