mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
b4475f2d91
commit
6389d9040d
@ -335,6 +335,16 @@ private final class StickerSelectionComponent: Component {
|
|||||||
|
|
||||||
return availableSize
|
return availableSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
|
let result = super.hitTest(point, with: event)
|
||||||
|
|
||||||
|
if self.searchVisible, let keyboardView = self.keyboardView.view, let keyboardResult = keyboardView.hitTest(self.convert(point, to: keyboardView), with: event) {
|
||||||
|
return keyboardResult
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeView() -> View {
|
public func makeView() -> View {
|
||||||
@ -363,7 +373,7 @@ public class StickerPickerScreen: ViewController {
|
|||||||
|
|
||||||
private(set) var isExpanded = false
|
private(set) var isExpanded = false
|
||||||
private var panGestureRecognizer: UIPanGestureRecognizer?
|
private var panGestureRecognizer: UIPanGestureRecognizer?
|
||||||
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?)?
|
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
|
||||||
|
|
||||||
private var currentIsVisible: Bool = false
|
private var currentIsVisible: Bool = false
|
||||||
private var currentLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
private var currentLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
||||||
@ -844,85 +854,6 @@ public class StickerPickerScreen: ViewController {
|
|||||||
stateContext: nil
|
stateContext: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
content.masks?.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
|
|
||||||
performItemAction: { [weak self] _, item, _, _, _, _ in
|
|
||||||
guard let strongSelf = self, let file = item.itemFile else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
strongSelf.controller?.completion(.file(file))
|
|
||||||
strongSelf.controller?.dismiss(animated: true)
|
|
||||||
},
|
|
||||||
deleteBackwards: nil,
|
|
||||||
openStickerSettings: nil,
|
|
||||||
openFeatured: nil,
|
|
||||||
openSearch: {},
|
|
||||||
addGroupAction: { [weak self] groupId, isPremiumLocked, _ in
|
|
||||||
guard let strongSelf = self, let controller = strongSelf.controller, let collectionId = groupId.base as? ItemCollectionId else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let context = controller.context
|
|
||||||
let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)
|
|
||||||
let _ = (context.account.postbox.combinedView(keys: [viewKey])
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(next: { views in
|
|
||||||
guard let view = views.views[viewKey] as? OrderedItemListView else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) {
|
|
||||||
if featuredStickerPack.info.id == collectionId {
|
|
||||||
let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false)
|
|
||||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
|
||||||
switch result {
|
|
||||||
case let .result(info, items, installed):
|
|
||||||
if installed {
|
|
||||||
return .complete()
|
|
||||||
} else {
|
|
||||||
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
|
|
||||||
}
|
|
||||||
case .fetching:
|
|
||||||
break
|
|
||||||
case .none:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return .complete()
|
|
||||||
}
|
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|
||||||
})
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
clearGroup: { _ in
|
|
||||||
},
|
|
||||||
pushController: { c in
|
|
||||||
},
|
|
||||||
presentController: { c in
|
|
||||||
},
|
|
||||||
presentGlobalOverlayController: { c in
|
|
||||||
},
|
|
||||||
navigationController: { [weak self] in
|
|
||||||
return self?.controller?.navigationController as? NavigationController
|
|
||||||
},
|
|
||||||
requestUpdate: { _ in
|
|
||||||
},
|
|
||||||
updateSearchQuery: { _ in
|
|
||||||
},
|
|
||||||
updateScrollingToItemGroup: { [weak self] in
|
|
||||||
self?.update(isExpanded: true, transition: .animated(duration: 0.4, curve: .spring))
|
|
||||||
},
|
|
||||||
onScroll: {},
|
|
||||||
chatPeerId: nil,
|
|
||||||
peekBehavior: nil,
|
|
||||||
customLayout: nil,
|
|
||||||
externalBackground: nil,
|
|
||||||
externalExpansionView: nil,
|
|
||||||
useOpaqueTheme: false,
|
|
||||||
hideBackground: true,
|
|
||||||
stateContext: nil
|
|
||||||
)
|
|
||||||
|
|
||||||
var stickerPeekBehavior: EmojiContentPeekBehaviorImpl?
|
var stickerPeekBehavior: EmojiContentPeekBehaviorImpl?
|
||||||
if let controller = self.controller {
|
if let controller = self.controller {
|
||||||
stickerPeekBehavior = EmojiContentPeekBehaviorImpl(
|
stickerPeekBehavior = EmojiContentPeekBehaviorImpl(
|
||||||
@ -951,6 +882,7 @@ public class StickerPickerScreen: ViewController {
|
|||||||
if let pagerView = componentView.keyboardView.view as? EntityKeyboardComponent.View {
|
if let pagerView = componentView.keyboardView.view as? EntityKeyboardComponent.View {
|
||||||
pagerView.openSearch()
|
pagerView.openSearch()
|
||||||
}
|
}
|
||||||
|
self.update(isExpanded: true, transition: .animated(duration: 0.4, curve: .spring))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addGroupAction: { [weak self] groupId, isPremiumLocked, _ in
|
addGroupAction: { [weak self] groupId, isPremiumLocked, _ in
|
||||||
@ -1036,7 +968,13 @@ public class StickerPickerScreen: ViewController {
|
|||||||
navigationController: { [weak self] in
|
navigationController: { [weak self] in
|
||||||
return self?.controller?.navigationController as? NavigationController
|
return self?.controller?.navigationController as? NavigationController
|
||||||
},
|
},
|
||||||
requestUpdate: { _ in
|
requestUpdate: { [weak self] transition in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !transition.animation.isImmediate, let (layout, navigationHeight) = strongSelf.currentLayout {
|
||||||
|
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateSearchQuery: { [weak self] query in
|
updateSearchQuery: { [weak self] query in
|
||||||
guard let strongSelf = self, let controller = strongSelf.controller else {
|
guard let strongSelf = self, let controller = strongSelf.controller else {
|
||||||
@ -1239,7 +1177,7 @@ public class StickerPickerScreen: ViewController {
|
|||||||
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
||||||
let topInset: CGFloat
|
let topInset: CGFloat
|
||||||
var bottomInset = layout.intrinsicInsets.bottom
|
var bottomInset = layout.intrinsicInsets.bottom
|
||||||
if let (panInitialTopInset, panOffset, _) = self.panGestureArguments {
|
if let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
||||||
if effectiveExpanded {
|
if effectiveExpanded {
|
||||||
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
||||||
} else {
|
} else {
|
||||||
@ -1382,10 +1320,16 @@ public class StickerPickerScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func findScrollView(view: UIView?) -> UIScrollView? {
|
private func findScrollView(view: UIView?) -> (UIScrollView, ListView?)? {
|
||||||
if let view = view {
|
if let view = view {
|
||||||
if let view = view as? PagerExpandableScrollView {
|
if let view = view as? PagerExpandableScrollView {
|
||||||
return view
|
return (view, nil)
|
||||||
|
}
|
||||||
|
if let view = view as? GridNodeScrollerView {
|
||||||
|
return (view, nil)
|
||||||
|
}
|
||||||
|
if let node = view.asyncdisplaykit_node as? ListView {
|
||||||
|
return (node.scroller, node)
|
||||||
}
|
}
|
||||||
return findScrollView(view: view.superview)
|
return findScrollView(view: view.superview)
|
||||||
} else {
|
} else {
|
||||||
@ -1406,10 +1350,12 @@ public class StickerPickerScreen: ViewController {
|
|||||||
let point = recognizer.location(in: self.view)
|
let point = recognizer.location(in: self.view)
|
||||||
let currentHitView = self.hitTest(point, with: nil)
|
let currentHitView = self.hitTest(point, with: nil)
|
||||||
|
|
||||||
var scrollView = self.findScrollView(view: currentHitView)
|
var scrollViewAndListNode = self.findScrollView(view: currentHitView)
|
||||||
if scrollView?.frame.height == self.frame.width {
|
if scrollViewAndListNode?.0.frame.height == self.frame.width {
|
||||||
scrollView = nil
|
scrollViewAndListNode = nil
|
||||||
}
|
}
|
||||||
|
let scrollView = scrollViewAndListNode?.0
|
||||||
|
let listNode = scrollViewAndListNode?.1
|
||||||
|
|
||||||
let topInset: CGFloat
|
let topInset: CGFloat
|
||||||
if self.isExpanded {
|
if self.isExpanded {
|
||||||
@ -1418,11 +1364,12 @@ public class StickerPickerScreen: ViewController {
|
|||||||
topInset = edgeTopInset
|
topInset = edgeTopInset
|
||||||
}
|
}
|
||||||
|
|
||||||
self.panGestureArguments = (topInset, 0.0, scrollView)
|
self.panGestureArguments = (topInset, 0.0, scrollView, listNode)
|
||||||
case .changed:
|
case .changed:
|
||||||
guard let (topInset, panOffset, scrollView) = self.panGestureArguments else {
|
guard let (topInset, panOffset, scrollView, listNode) = self.panGestureArguments else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let visibleContentOffset = listNode?.visibleContentOffset()
|
||||||
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
||||||
|
|
||||||
var translation = recognizer.translation(in: self.view).y
|
var translation = recognizer.translation(in: self.view).y
|
||||||
@ -1430,7 +1377,12 @@ public class StickerPickerScreen: ViewController {
|
|||||||
var currentOffset = topInset + translation
|
var currentOffset = topInset + translation
|
||||||
|
|
||||||
let epsilon = 1.0
|
let epsilon = 1.0
|
||||||
if let scrollView = scrollView, contentOffset <= -scrollView.contentInset.top + epsilon {
|
if case let .known(value) = visibleContentOffset, value <= epsilon {
|
||||||
|
if let scrollView = scrollView {
|
||||||
|
scrollView.bounces = false
|
||||||
|
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: 0.0), animated: false)
|
||||||
|
}
|
||||||
|
} else if let scrollView = scrollView, contentOffset <= -scrollView.contentInset.top + epsilon {
|
||||||
scrollView.bounces = false
|
scrollView.bounces = false
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
} else if let scrollView = scrollView {
|
} else if let scrollView = scrollView {
|
||||||
@ -1443,7 +1395,7 @@ public class StickerPickerScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.panGestureArguments = (topInset, translation, scrollView)
|
self.panGestureArguments = (topInset, translation, scrollView, listNode)
|
||||||
|
|
||||||
if !self.isExpanded {
|
if !self.isExpanded {
|
||||||
if currentOffset > 0.0, let scrollView = scrollView {
|
if currentOffset > 0.0, let scrollView = scrollView {
|
||||||
@ -1462,18 +1414,23 @@ public class StickerPickerScreen: ViewController {
|
|||||||
|
|
||||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||||
case .ended:
|
case .ended:
|
||||||
guard let (currentTopInset, panOffset, scrollView) = self.panGestureArguments else {
|
guard let (currentTopInset, panOffset, scrollView, listNode) = self.panGestureArguments else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.panGestureArguments = nil
|
self.panGestureArguments = nil
|
||||||
|
|
||||||
|
let visibleContentOffset = listNode?.visibleContentOffset()
|
||||||
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
||||||
|
|
||||||
let translation = recognizer.translation(in: self.view).y
|
let translation = recognizer.translation(in: self.view).y
|
||||||
var velocity = recognizer.velocity(in: self.view)
|
var velocity = recognizer.velocity(in: self.view)
|
||||||
|
|
||||||
if self.isExpanded {
|
if self.isExpanded {
|
||||||
if contentOffset > 0.1 {
|
if case let .known(value) = visibleContentOffset, value > 0.1 {
|
||||||
|
velocity = CGPoint()
|
||||||
|
} else if case .unknown = visibleContentOffset {
|
||||||
|
velocity = CGPoint()
|
||||||
|
} else if contentOffset > 0.1 {
|
||||||
velocity = CGPoint()
|
velocity = CGPoint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1499,7 +1456,9 @@ public class StickerPickerScreen: ViewController {
|
|||||||
} else if self.isExpanded {
|
} else if self.isExpanded {
|
||||||
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
||||||
self.isExpanded = false
|
self.isExpanded = false
|
||||||
if let scrollView = scrollView {
|
if let listNode = listNode {
|
||||||
|
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
||||||
|
} else if let scrollView = scrollView {
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1520,7 +1479,9 @@ public class StickerPickerScreen: ViewController {
|
|||||||
|
|
||||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: Transition(transition))
|
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: Transition(transition))
|
||||||
} else {
|
} else {
|
||||||
if let scrollView = scrollView {
|
if let listNode = listNode {
|
||||||
|
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
||||||
|
} else if let scrollView = scrollView {
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,6 +418,22 @@ final class LockContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func lastStateImage() -> UIImage {
|
||||||
|
let imagePath = NSTemporaryDirectory() + "galleryImage.jpg"
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: imagePath)), let image = UIImage(data: data) {
|
||||||
|
return image
|
||||||
|
} else {
|
||||||
|
return UIImage(bundleImageName: "Camera/Placeholder")!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func saveLastStateImage(_ image: UIImage) {
|
||||||
|
let imagePath = NSTemporaryDirectory() + "galleryImage.jpg"
|
||||||
|
if let data = image.jpegData(compressionQuality: 0.6) {
|
||||||
|
try? data.write(to: URL(fileURLWithPath: imagePath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class CaptureControlsComponent: Component {
|
final class CaptureControlsComponent: Component {
|
||||||
enum SwipeHint {
|
enum SwipeHint {
|
||||||
case none
|
case none
|
||||||
@ -505,8 +521,13 @@ final class CaptureControlsComponent: Component {
|
|||||||
self.assetDisposable.set((fetchPhotoLibraryImage(localIdentifier: lastGalleryAsset.localIdentifier, thumbnail: true)
|
self.assetDisposable.set((fetchPhotoLibraryImage(localIdentifier: lastGalleryAsset.localIdentifier, thumbnail: true)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] imageAndDegraded in
|
|> deliverOnMainQueue).start(next: { [weak self] imageAndDegraded in
|
||||||
if let self, let (image, _) = imageAndDegraded {
|
if let self, let (image, _) = imageAndDegraded {
|
||||||
|
let updated = self.cachedAssetImage?.0 != lastGalleryAsset.localIdentifier
|
||||||
self.cachedAssetImage = (lastGalleryAsset.localIdentifier, image)
|
self.cachedAssetImage = (lastGalleryAsset.localIdentifier, image)
|
||||||
self.updated(transition: .easeInOut(duration: 0.2))
|
self.updated(transition: .easeInOut(duration: 0.2))
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
saveLastStateImage(image)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -514,6 +535,12 @@ final class CaptureControlsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
self.cachedAssetImage = ("", lastStateImage())
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.assetDisposable.dispose()
|
self.assetDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
@ -446,7 +446,7 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||||||
self.iconNode.layer.animateFrame(from: self.iconNode.frame, to: targetIconFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
self.iconNode.layer.animateFrame(from: self.iconNode.frame, to: targetIconFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
||||||
|
|
||||||
let cancelButtonFrame = self.cancelButton.frame
|
let cancelButtonFrame = self.cancelButton.frame
|
||||||
self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.minY + 2.0 + cancelButtonFrame.size.height / 2.0), duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.minY + 4.0 + cancelButtonFrame.size.height / 2.0), duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
@ -49,8 +49,6 @@ public final class PaneSearchContainerNode: ASDisplayNode, EntitySearchContainer
|
|||||||
|
|
||||||
public var openGifContextMenu: ((MultiplexedVideoNodeFile, ASDisplayNode, CGRect, ContextGesture, Bool) -> Void)?
|
public var openGifContextMenu: ((MultiplexedVideoNodeFile, ASDisplayNode, CGRect, ContextGesture, Bool) -> Void)?
|
||||||
|
|
||||||
public var addOnSupernode: Bool = true
|
|
||||||
|
|
||||||
public var ready: Signal<Void, NoError> {
|
public var ready: Signal<Void, NoError> {
|
||||||
return self.contentNode.ready
|
return self.contentNode.ready
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,6 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
|
|||||||
|
|
||||||
public var onCancel: (() -> Void)?
|
public var onCancel: (() -> Void)?
|
||||||
|
|
||||||
public var addOnSupernode: Bool = false
|
|
||||||
|
|
||||||
private let emojiSearchDisposable = MetaDisposable()
|
private let emojiSearchDisposable = MetaDisposable()
|
||||||
private let emojiSearchState = Promise<EmojiSearchState>(EmojiSearchState(result: nil, isSearching: false))
|
private let emojiSearchState = Promise<EmojiSearchState>(EmojiSearchState(result: nil, isSearching: false))
|
||||||
private var emojiSearchStateValue = EmojiSearchState(result: nil, isSearching: false) {
|
private var emojiSearchStateValue = EmojiSearchState(result: nil, isSearching: false) {
|
||||||
|
@ -13,8 +13,6 @@ import AsyncDisplayKit
|
|||||||
import ComponentDisplayAdapters
|
import ComponentDisplayAdapters
|
||||||
|
|
||||||
public protocol EntitySearchContainerNode: ASDisplayNode {
|
public protocol EntitySearchContainerNode: ASDisplayNode {
|
||||||
var addOnSupernode: Bool { get set }
|
|
||||||
|
|
||||||
var onCancel: (() -> Void)? { get set }
|
var onCancel: (() -> Void)? { get set }
|
||||||
|
|
||||||
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition)
|
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition)
|
||||||
|
@ -1730,6 +1730,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
if case let .draft(draft, _) = subject, let privacy = draft.privacy {
|
if case let .draft(draft, _) = subject, let privacy = draft.privacy {
|
||||||
controller.state.privacy = privacy
|
controller.state.privacy = privacy
|
||||||
|
} else if !controller.isEditingStory {
|
||||||
|
let _ = (mediaEditorStoredState(engine: controller.context.engine)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak controller] state in
|
||||||
|
if let controller, let privacy = state?.privacy {
|
||||||
|
controller.state.privacy = privacy
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let isSavingAvailable: Bool
|
let isSavingAvailable: Bool
|
||||||
@ -2911,17 +2918,17 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
|
|
||||||
if let initialPrivacy {
|
|
||||||
self.state.privacy = MediaEditorResultPrivacy(privacy: initialPrivacy, timeout: 86400, archive: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.automaticallyControlPresentationContextLayout = false
|
self.automaticallyControlPresentationContextLayout = false
|
||||||
|
|
||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .flatModal
|
||||||
|
|
||||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
|
|
||||||
self.statusBar.statusBarStyle = .White
|
self.statusBar.statusBarStyle = .White
|
||||||
|
|
||||||
|
if isEditing {
|
||||||
|
if let initialPrivacy {
|
||||||
|
self.state.privacy = MediaEditorResultPrivacy(privacy: initialPrivacy, timeout: 86400, archive: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
@ -3332,6 +3339,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.isEditingStory {
|
||||||
|
let _ = updateMediaEditorStoredStateInteractively(engine: self.context.engine, state: MediaEditorStoredState(privacy: self.state.privacy)).start()
|
||||||
|
}
|
||||||
|
|
||||||
if mediaEditor.resultIsVideo {
|
if mediaEditor.resultIsVideo {
|
||||||
var firstFrame: Signal<UIImage?, NoError>
|
var firstFrame: Signal<UIImage?, NoError>
|
||||||
let firstFrameTime = CMTime(seconds: mediaEditor.values.videoTrimRange?.lowerBound ?? 0.0, preferredTimescale: CMTimeScale(60))
|
let firstFrameTime = CMTime(seconds: mediaEditor.values.videoTrimRange?.lowerBound ?? 0.0, preferredTimescale: CMTimeScale(60))
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramCore
|
||||||
|
import TelegramUIPreferences
|
||||||
|
import MediaEditor
|
||||||
|
|
||||||
|
public final class MediaEditorStoredState: Codable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case privacy
|
||||||
|
}
|
||||||
|
|
||||||
|
public let privacy: MediaEditorResultPrivacy?
|
||||||
|
|
||||||
|
public init(privacy: MediaEditorResultPrivacy?) {
|
||||||
|
self.privacy = privacy
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if let data = try container.decodeIfPresent(Data.self, forKey: .privacy), let privacy = try? JSONDecoder().decode(MediaEditorResultPrivacy.self, from: data) {
|
||||||
|
self.privacy = privacy
|
||||||
|
} else {
|
||||||
|
self.privacy = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if let privacy = self .privacy {
|
||||||
|
if let data = try? JSONEncoder().encode(privacy) {
|
||||||
|
try container.encode(data, forKey: .privacy)
|
||||||
|
} else {
|
||||||
|
try container.encodeNil(forKey: .privacy)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try container.encodeNil(forKey: .privacy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mediaEditorStoredState(engine: TelegramEngine) -> Signal<MediaEditorStoredState?, NoError> {
|
||||||
|
let key = EngineDataBuffer(length: 4)
|
||||||
|
key.setInt32(0, value: 0)
|
||||||
|
|
||||||
|
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.mediaEditorState, id: key))
|
||||||
|
|> map { entry -> MediaEditorStoredState? in
|
||||||
|
return entry?.get(MediaEditorStoredState.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateMediaEditorStoredStateInteractively(engine: TelegramEngine, state: MediaEditorStoredState?) -> Signal<Never, NoError> {
|
||||||
|
let key = EngineDataBuffer(length: 4)
|
||||||
|
key.setInt32(0, value: 0)
|
||||||
|
|
||||||
|
if let state = state {
|
||||||
|
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.mediaEditorState, id: key, item: state)
|
||||||
|
} else {
|
||||||
|
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.mediaEditorState, id: key)
|
||||||
|
}
|
||||||
|
}
|
@ -77,6 +77,7 @@ private enum ApplicationSpecificItemCacheCollectionIdValues: Int8 {
|
|||||||
case pendingInAppPurchaseState = 7
|
case pendingInAppPurchaseState = 7
|
||||||
case translationState = 10
|
case translationState = 10
|
||||||
case storySource = 11
|
case storySource = 11
|
||||||
|
case mediaEditorState = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ApplicationSpecificItemCacheCollectionId {
|
public struct ApplicationSpecificItemCacheCollectionId {
|
||||||
@ -90,6 +91,7 @@ public struct ApplicationSpecificItemCacheCollectionId {
|
|||||||
public static let pendingInAppPurchaseState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.pendingInAppPurchaseState.rawValue)
|
public static let pendingInAppPurchaseState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.pendingInAppPurchaseState.rawValue)
|
||||||
public static let translationState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.translationState.rawValue)
|
public static let translationState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.translationState.rawValue)
|
||||||
public static let storySource = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.storySource.rawValue)
|
public static let storySource = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.storySource.rawValue)
|
||||||
|
public static let mediaEditorState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.mediaEditorState.rawValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum ApplicationSpecificOrderedItemListCollectionIdValues: Int32 {
|
private enum ApplicationSpecificOrderedItemListCollectionIdValues: Int32 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user