Various fixes

This commit is contained in:
Ilya Laktyushin 2023-07-11 06:48:28 +02:00
parent 0d69b86b92
commit 5ad9671d70
13 changed files with 820 additions and 378 deletions

View File

@ -161,6 +161,7 @@ private final class CameraContext {
self.secondaryPreviewView = secondaryPreviewView
self.positionValue = configuration.position
self._positionPromise = ValuePromise<Camera.Position>(configuration.position)
self.mainDeviceContext = CameraDeviceContext(session: session, exclusive: true, additional: false)
self.configure {
@ -251,14 +252,14 @@ private final class CameraContext {
}
}
private var _positionPromise = ValuePromise<Camera.Position>(.unspecified)
private var _positionPromise: ValuePromise<Camera.Position>
var position: Signal<Camera.Position, NoError> {
return self._positionPromise.get()
}
private var positionValue: Camera.Position = .back
func togglePosition() {
if self.isDualCamEnabled {
if self.isDualCameraEnabled {
let targetPosition: Camera.Position
if case .back = self.positionValue {
targetPosition = .front
@ -308,12 +309,12 @@ private final class CameraContext {
}
}
private var isDualCamEnabled = false
public func setDualCamEnabled(_ enabled: Bool) {
guard enabled != self.isDualCamEnabled else {
private var isDualCameraEnabled = false
public func setDualCameraEnabled(_ enabled: Bool) {
guard enabled != self.isDualCameraEnabled else {
return
}
self.isDualCamEnabled = enabled
self.isDualCameraEnabled = enabled
self.modeChange = .dualCamera
if enabled {
@ -659,10 +660,10 @@ public final class Camera {
}
}
public func setDualCamEnabled(_ enabled: Bool) {
public func setDualCameraEnabled(_ enabled: Bool) {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.setDualCamEnabled(enabled)
context.setDualCameraEnabled(enabled)
}
}
}

View File

@ -2568,16 +2568,41 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
switch self.storyPostingAvailability {
case .premium:
guard self.isPremium else {
let context = self.context
var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: self.context, subject: .stories, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .stories)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
if let componentView = self.chatListHeaderView() {
var sourceFrame: CGRect?
if fromList {
if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) {
sourceFrame = transitionView.convert(transitionView.bounds, to: nil).offsetBy(dx: 18.0 - UIScreenPixel, dy: 1.0)
}
} else {
if let rightButtonView = componentView.rightButtonViews["story"] {
sourceFrame = rightButtonView.convert(rightButtonView.bounds, to: nil).offsetBy(dx: 5.0, dy: -8.0)
}
}
if let sourceFrame {
let context = self.context
let location = CGRect(origin: CGPoint(x: sourceFrame.midX, y: sourceFrame.maxY), size: CGSize())
let tooltipController = TooltipScreen(
context: context,
account: context.account,
sharedContext: context.sharedContext,
text: .markdown(text: "Posting stories is currently available only to subscribers of [Telegram Premium]()."),
style: .customBlur(UIColor(rgb: 0x2a2a2a), 2.0),
icon: .none,
location: .point(location, .top),
shouldDismissOnTouch: { [weak self] point, containerFrame in
if containerFrame.contains(point) {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .stories)
self?.push(controller)
return .dismiss(consume: true)
} else {
return .dismiss(consume: false)
}
}
)
self.present(tooltipController, in: .window(.root))
}
}
self.push(controller)
return
}
case .disabled:

View File

@ -12,6 +12,186 @@ private let imageManager: PHCachingImageManager = {
private let assetsQueue = Queue()
final class AssetDownloadManager {
private final class DownloadingAssetContext {
let identifier: String
let updated: () -> Void
var status: AssetDownloadStatus = .progress(0.0)
var disposable: Disposable?
init(identifier: String, updated: @escaping () -> Void) {
self.identifier = identifier
self.updated = updated
}
deinit {
self.disposable?.dispose()
}
}
private let queue = Queue()
private var currentAssetContext: DownloadingAssetContext?
init() {
}
deinit {
}
func download(asset: PHAsset) {
if let currentAssetContext = self.currentAssetContext {
currentAssetContext.disposable?.dispose()
}
let queue = self.queue
let identifier = asset.localIdentifier
let assetContext = DownloadingAssetContext(identifier: identifier, updated: { [weak self] in
queue.async {
guard let self else {
return
}
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier, let bag = self.progressObserverContexts[identifier] {
for f in bag.copyItems() {
f(currentAssetContext.status)
}
}
}
})
assetContext.disposable = (downloadAssetMediaData(asset)
|> deliverOn(queue)).start(next: { [weak self] status in
guard let self else {
return
}
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier {
currentAssetContext.status = status
currentAssetContext.updated()
}
})
self.currentAssetContext = assetContext
}
func cancel(identifier: String) {
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier {
currentAssetContext.disposable?.dispose()
self.currentAssetContext = nil
}
}
private var progressObserverContexts: [String: Bag<(AssetDownloadStatus) -> Void>] = [:]
private func downloadProgress(identifier: String, next: @escaping (AssetDownloadStatus) -> Void) -> Disposable {
let bag: Bag<(AssetDownloadStatus) -> Void>
if let current = self.progressObserverContexts[identifier] {
bag = current
} else {
bag = Bag()
self.progressObserverContexts[identifier] = bag
}
let index = bag.add(next)
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier {
next(currentAssetContext.status)
} else {
next(.progress(0.0))
}
let queue = self.queue
return ActionDisposable { [weak self, weak bag] in
queue.async {
guard let `self` = self else {
return
}
if let bag = bag, let listBag = self.progressObserverContexts[identifier], listBag === bag {
bag.remove(index)
if bag.isEmpty {
self.progressObserverContexts.removeValue(forKey: identifier)
}
}
}
}
}
func downloadProgress(identifier: String) -> Signal<AssetDownloadStatus, NoError> {
return Signal { [weak self] subscriber in
if let self {
return self.downloadProgress(identifier: identifier, next: { status in
subscriber.putNext(status)
if case .completed = status {
subscriber.putCompletion()
}
})
} else {
return EmptyDisposable
}
}
}
}
func checkIfAssetIsLocal(_ asset: PHAsset) -> Signal<Bool, NoError> {
return Signal { subscriber in
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = false
let requestId: PHImageRequestID
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(data != nil)
}
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(data != nil)
}
subscriber.putCompletion()
}
}
return ActionDisposable {
imageManager.cancelImageRequest(requestId)
}
}
}
enum AssetDownloadStatus {
case progress(Float)
case completed
}
private func downloadAssetMediaData(_ asset: PHAsset) -> Signal<AssetDownloadStatus, NoError> {
return Signal { subscriber in
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = true
options.progressHandler = { progress, _, _, _ in
subscriber.putNext(.progress(Float(progress)))
}
let requestId: PHImageRequestID
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(.completed)
}
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(.completed)
}
subscriber.putCompletion()
}
}
return ActionDisposable {
imageManager.cancelImageRequest(requestId)
}
}
}
func assetImage(fetchResult: PHFetchResult<PHAsset>, index: Int, targetSize: CGSize, exact: Bool, deliveryMode: PHImageRequestOptionsDeliveryMode = .opportunistic, synchronous: Bool = false) -> Signal<UIImage?, NoError> {
let asset = fetchResult[index]
return assetImage(asset: asset, targetSize: targetSize, exact: exact, deliveryMode: deliveryMode, synchronous: synchronous)
@ -68,3 +248,10 @@ func assetVideo(fetchResult: PHFetchResult<PHAsset>, index: Int) -> Signal<AVAss
}
}
}
extension PHAsset {
var isLocallyAvailable: Bool? {
let resourceArray = PHAssetResource.assetResources(for: self)
return resourceArray.first?.value(forKey: "locallyAvailable") as? Bool
}
}

View File

@ -777,6 +777,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private weak var currentGalleryController: TGModernGalleryController?
private func requestAssetDownload(_ asset: PHAsset) {
}
private var openingMedia = false
fileprivate func openMedia(fetchResult: PHFetchResult<PHAsset>, index: Int, immediateThumbnail: UIImage?) {
guard let controller = self.controller, let interaction = controller.interaction, let (layout, _) = self.validLayout, !self.openingMedia else {
@ -788,7 +792,29 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
if let customSelection = controller.customSelection {
self.openingMedia = true
customSelection(controller, fetchResult[index])
let asset = fetchResult[index]
customSelection(controller, asset)
// let isLocallyAvailable = asset.isLocallyAvailable
//
// if let isLocallyAvailable {
// if isLocallyAvailable {
// customSelection(controller, asset)
// } else {
// self.requestAssetDownload(asset)
// }
// } else {
// let _ = (checkIfAssetIsLocal(asset)
// |> deliverOnMainQueue).start(next: { [weak self] isLocallyAvailable in
// if isLocallyAvailable {
// customSelection(controller, asset)
// } else {
// self?.requestAssetDownload(asset)
// }
// })
// }
Queue.mainQueue().after(0.3) {
self.openingMedia = false
}

View File

@ -1729,7 +1729,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
if let strongSelf = self, (count < 2 && currentTimestamp > timestamp + 24 * 60 * 60) {
strongSelf.displayedPreviewTooltip = true
let controller = TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: .plain(text: isDark ? strongSelf.presentationData.strings.WallpaperPreview_PreviewInDayMode : strongSelf.presentationData.strings.WallpaperPreview_PreviewInNightMode), style: .customBlur(UIColor(rgb: 0x333333, alpha: 0.35)), icon: nil, location: .point(frame.offsetBy(dx: 1.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _, _ in
let controller = TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: .plain(text: isDark ? strongSelf.presentationData.strings.WallpaperPreview_PreviewInDayMode : strongSelf.presentationData.strings.WallpaperPreview_PreviewInNightMode), style: .customBlur(UIColor(rgb: 0x333333, alpha: 0.35), 0.0), icon: nil, location: .point(frame.offsetBy(dx: 1.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _, _ in
return .dismiss(consume: false)
})
strongSelf.galleryController()?.present(controller, in: .current)

View File

@ -0,0 +1,73 @@
import Foundation
import UIKit
import SwiftSignalKit
import TelegramCore
import TelegramUIPreferences
import MediaEditor
public final class CameraStoredState: Codable {
private enum CodingKeys: String, CodingKey {
case isDualCameraEnabled
case dualCameraPosition
}
public let isDualCameraEnabled: Bool
public let dualCameraPosition: CameraScreen.PIPPosition
public init(
isDualCameraEnabled: Bool,
dualCameraPosition: CameraScreen.PIPPosition
) {
self.isDualCameraEnabled = isDualCameraEnabled
self.dualCameraPosition = dualCameraPosition
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.isDualCameraEnabled = try container.decode(Bool.self, forKey: .isDualCameraEnabled)
self.dualCameraPosition = CameraScreen.PIPPosition(rawValue: try container.decode(Int32.self, forKey: .dualCameraPosition)) ?? .topRight
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.isDualCameraEnabled, forKey: .isDualCameraEnabled)
try container.encode(self.dualCameraPosition.rawValue, forKey: .dualCameraPosition)
}
public func withIsDualCameraEnabled(_ isDualCameraEnabled: Bool) -> CameraStoredState {
return CameraStoredState(isDualCameraEnabled: isDualCameraEnabled, dualCameraPosition: self.dualCameraPosition)
}
public func withDualCameraPosition(_ dualCameraPosition: CameraScreen.PIPPosition) -> CameraStoredState {
return CameraStoredState(isDualCameraEnabled: self.isDualCameraEnabled, dualCameraPosition: dualCameraPosition)
}
}
func cameraStoredState(engine: TelegramEngine) -> Signal<CameraStoredState?, NoError> {
let key = EngineDataBuffer(length: 4)
key.setInt32(0, value: 0)
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cameraState, id: key))
|> map { entry -> CameraStoredState? in
return entry?.get(CameraStoredState.self)
}
}
func updateCameraStoredStateInteractively(engine: TelegramEngine, _ f: @escaping (CameraStoredState?) -> CameraStoredState?) {
let key = EngineDataBuffer(length: 4)
key.setInt32(0, value: 0)
let _ = (engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cameraState, id: key))
|> map { entry -> CameraStoredState? in
return entry?.get(CameraStoredState.self)
}
|> mapToSignal { state -> Signal<Never, NoError> in
if let updatedState = f(state) {
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cameraState, id: key, item: updatedState)
} else {
return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.cameraState, id: key)
}
}).start()
}

View File

@ -1117,7 +1117,7 @@ final class CaptureControlsComponent: Component {
),
minSize: hintIconSize,
action: {
component.flipTapped()
component.lockRecording()
}
)
),

View File

@ -341,41 +341,54 @@ private func verticesData(
bottomRight = simd_float2(1.0, 1.0)
}
let relativeSize = CGSize(
width: size.width / containerSize.width,
height: size.height / containerSize.height
)
let relativeOffset = CGPoint(
x: position.x / containerSize.width,
y: position.y / containerSize.height
)
let rect = CGRect(
origin: CGPoint(
x: relativeOffset.x - relativeSize.width / 2.0,
y: relativeOffset.y - relativeSize.height / 2.0
),
size: relativeSize
)
let angle = Float(.pi - rotation)
let cosAngle = cos(angle)
let sinAngle = sin(angle)
let centerX = Float(position.x)
let centerY = Float(position.y)
let halfWidth = Float(size.width / 2.0)
let halfHeight = Float(size.height / 2.0)
return [
VertexData(
pos: simd_float4(x: Float(rect.minX) * 2.0, y: Float(rect.minY) * 2.0, z: z, w: 1),
pos: simd_float4(
x: (centerX + (halfWidth * cosAngle) - (halfHeight * sinAngle)) / Float(containerSize.width) * 2.0,
y: (centerY + (halfWidth * sinAngle) + (halfHeight * cosAngle)) / Float(containerSize.height) * 2.0,
z: z,
w: 1
),
texCoord: topLeft,
localPos: simd_float2(0.0, 0.0)
),
VertexData(
pos: simd_float4(x: Float(rect.maxX) * 2.0, y: Float(rect.minY) * 2.0, z: z, w: 1),
pos: simd_float4(
x: (centerX - (halfWidth * cosAngle) - (halfHeight * sinAngle)) / Float(containerSize.width) * 2.0,
y: (centerY - (halfWidth * sinAngle) + (halfHeight * cosAngle)) / Float(containerSize.height) * 2.0,
z: z,
w: 1
),
texCoord: topRight,
localPos: simd_float2(1.0, 0.0)
),
VertexData(
pos: simd_float4(x: Float(rect.minX) * 2.0, y: Float(rect.maxY) * 2.0, z: z, w: 1),
pos: simd_float4(
x: (centerX + (halfWidth * cosAngle) + (halfHeight * sinAngle)) / Float(containerSize.width) * 2.0,
y: (centerY + (halfWidth * sinAngle) - (halfHeight * cosAngle)) / Float(containerSize.height) * 2.0,
z: z,
w: 1
),
texCoord: bottomLeft,
localPos: simd_float2(0.0, 1.0)
),
VertexData(
pos: simd_float4(x: Float(rect.maxX) * 2.0, y: Float(rect.maxY) * 2.0, z: z, w: 1),
pos: simd_float4(
x: (centerX - (halfWidth * cosAngle) + (halfHeight * sinAngle)) / Float(containerSize.width) * 2.0,
y: (centerY - (halfWidth * sinAngle) - (halfHeight * cosAngle)) / Float(containerSize.height) * 2.0,
z: z,
w: 1
),
texCoord: bottomRight,
localPos: simd_float2(1.0, 1.0)
)
@ -650,13 +663,13 @@ final class VideoInputScalePass: RenderPass {
}
func process(input: MTLTexture, secondInput: MTLTexture?, timestamp: CMTime, device: MTLDevice, commandBuffer: MTLCommandBuffer) -> MTLTexture? {
//#if targetEnvironment(simulator)
//
//#else
#if targetEnvironment(simulator)
#else
guard max(input.width, input.height) > 1920 || secondInput != nil else {
return input
}
//#endif
#endif
let scaledSize = CGSize(width: input.width, height: input.height).fitted(CGSize(width: 1920.0, height: 1920.0))
let width: Int
@ -705,9 +718,9 @@ final class VideoInputScalePass: RenderPass {
renderCommandEncoder.setRenderPipelineState(self.mainPipelineState!)
//#if targetEnvironment(simulator)
// let secondInput = input
//#endif
#if targetEnvironment(simulator)
let secondInput = input
#endif
let (mainVideoState, additionalVideoState, transitionVideoState) = self.transitionState(for: timestamp, mainInput: input, additionalInput: secondInput)

View File

@ -935,7 +935,9 @@ final class MediaEditorScreenComponent: Component {
let scrubberFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - scrubberSize.width) / 2.0), y: availableSize.height - environment.safeInsets.bottom - scrubberSize.height - 8.0 + controlsBottomInset), size: scrubberSize)
if let scrubberView = self.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 {
@ -945,6 +947,10 @@ final class MediaEditorScreenComponent: Component {
transition.setFrame(view: scrubberView, frame: scrubberFrame)
if !self.animatingButtons {
transition.setAlpha(view: scrubberView, alpha: component.isDisplayingTool || component.isDismissing || component.isInteractingWithEntities ? 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)
}
}
@ -3134,15 +3140,16 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
case bottomRight
func getPosition(_ size: CGSize) -> CGPoint {
let offset = CGPoint(x: 224.0, y: 520.0)
switch self {
case .topLeft:
return CGPoint(x: 224.0, y: 477.0)
return CGPoint(x: offset.x, y: offset.y)
case .topRight:
return CGPoint(x: size.width - 224.0, y: 477.0)
return CGPoint(x: size.width - offset.x, y: offset.y)
case .bottomLeft:
return CGPoint(x: 224.0, y: size.height - 477.0)
return CGPoint(x: offset.x, y: size.height - offset.y)
case .bottomRight:
return CGPoint(x: size.width - 224.0, y: size.height - 477.0)
return CGPoint(x: size.width - offset.x, y: size.height - offset.y)
}
}
}
@ -3374,28 +3381,29 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
guard let self else {
return
}
self.push(
ShareWithPeersScreen(
context: self.context,
initialPrivacy: privacy,
allowScreenshots: !isForwardingDisabled,
pin: pin,
stateContext: stateContext,
completion: { [weak self] result, isForwardingDisabled, pin in
guard let self else {
return
}
if case .closeFriends = privacy.base {
let _ = self.context.engine.privacy.updateCloseFriends(peerIds: result.additionallyIncludePeers).start()
completion(EngineStoryPrivacy(base: .closeFriends, additionallyIncludePeers: []))
} else {
completion(result)
}
},
editCategory: { _, _, _ in }
)
let controller = ShareWithPeersScreen(
context: self.context,
initialPrivacy: privacy,
allowScreenshots: !isForwardingDisabled,
pin: pin,
stateContext: stateContext,
completion: { [weak self] result, isForwardingDisabled, pin in
guard let self else {
return
}
if case .closeFriends = privacy.base {
let _ = self.context.engine.privacy.updateCloseFriends(peerIds: result.additionallyIncludePeers).start()
completion(EngineStoryPrivacy(base: .closeFriends, additionallyIncludePeers: []))
} else {
completion(result)
}
},
editCategory: { _, _, _ in }
)
controller.dismissed = {
self.node.mediaEditor?.play()
}
self.push(controller)
})
}

View File

@ -1235,7 +1235,7 @@ public final class StoryItemSetContainerComponent: Component {
centerInfoView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
}
if let moreButtonView = self.moreButton.view {
moreButtonView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
moreButtonView.layer.animateAlpha(from: 0.0, to: moreButtonView.alpha, duration: 0.25)
}
if let soundButtonView = self.soundButton.view {
soundButtonView.layer.animateAlpha(from: 0.0, to: soundButtonView.alpha, duration: 0.25)
@ -1361,7 +1361,7 @@ public final class StoryItemSetContainerComponent: Component {
centerInfoView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
}
if let moreButtonView = self.moreButton.view {
moreButtonView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
moreButtonView.layer.animateAlpha(from: moreButtonView.alpha, to: 0.0, duration: 0.25, removeOnCompletion: false)
}
if let soundButtonView = self.soundButton.view {
soundButtonView.layer.animateAlpha(from: soundButtonView.alpha, to: 0.0, duration: 0.25, removeOnCompletion: false)
@ -1592,6 +1592,16 @@ public final class StoryItemSetContainerComponent: Component {
if self.component?.slice.item.storyItem.id != component.slice.item.storyItem.id {
self.initializedOffset = false
if let inputPanelView = self.inputPanel.view as? MessageInputPanelComponent.View {
Queue.mainQueue().justDispatch {
inputPanelView.clearSendMessageInput()
}
}
if let tooltipScreen = self.sendMessageContext.tooltipScreen {
tooltipScreen.dismiss()
}
}
var itemsTransition = transition
var resetScrollingOffsetWithItemTransition = false
@ -3341,7 +3351,6 @@ public final class StoryItemSetContainerComponent: Component {
return .single(nil)
|> then(
.single(.video(symlinkPath, nil, false, nil, nil, PixelDimensions(width: 720, height: 1280), duration ?? 0.0, [], .bottomRight))
|> delay(0.1, queue: Queue.mainQueue())
)
}
}
@ -3848,7 +3857,7 @@ public final class StoryItemSetContainerComponent: Component {
account: component.context.account,
sharedContext: component.context.sharedContext,
text: .markdown(text: text),
style: .customBlur(UIColor(rgb: 0x1c1c1c)),
style: .customBlur(UIColor(rgb: 0x1c1c1c), 0.0),
icon: .peer(peer: component.slice.peer, isStory: true),
action: TooltipScreen.Action(
title: "Undo",

View File

@ -78,6 +78,7 @@ private enum ApplicationSpecificItemCacheCollectionIdValues: Int8 {
case translationState = 10
case storySource = 11
case mediaEditorState = 12
case cameraState = 13
}
public struct ApplicationSpecificItemCacheCollectionId {
@ -92,6 +93,7 @@ public struct ApplicationSpecificItemCacheCollectionId {
public static let translationState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.translationState.rawValue)
public static let storySource = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.storySource.rawValue)
public static let mediaEditorState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.mediaEditorState.rawValue)
public static let cameraState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.cameraState.rawValue)
}
private enum ApplicationSpecificOrderedItemListCollectionIdValues: Int32 {

View File

@ -240,7 +240,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
if !hasArrow {
let backgroundColor: UIColor
var enableSaturation = true
if case let .customBlur(color) = style {
if case let .customBlur(color, _) = style {
backgroundColor = color
enableSaturation = false
} else {
@ -297,7 +297,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
} else {
var enableSaturation = true
let backgroundColor: UIColor
if case let .customBlur(color) = style {
if case let .customBlur(color, _) = style {
backgroundColor = color
enableSaturation = false
} else if case .light = style {
@ -356,10 +356,11 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
case let .entities(text, entities):
attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: baseFont, linkFont: baseFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: fixedFont, blockQuoteFont: baseFont, underlineLinks: true, external: false, message: nil)
case let .markdown(text):
let linkColor = UIColor(rgb: 0x64d2ff)
let markdownAttributes = MarkdownAttributes(
body: MarkdownAttributeSet(font: baseFont, textColor: textColor),
bold: MarkdownAttributeSet(font: boldFont, textColor: textColor),
link: MarkdownAttributeSet(font: baseFont, textColor: textColor),
link: MarkdownAttributeSet(font: boldFont, textColor: linkColor),
linkAttribute: { _ in
return nil
}
@ -560,14 +561,16 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
var backgroundHeight: CGFloat
switch self.tooltipStyle {
case .default, .gradient, .customBlur, .wide:
case .default, .gradient:
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0
case .wide:
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0 + 4.0
case let .customBlur(_, inset):
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0 + inset * 2.0
case .light:
backgroundHeight = max(28.0, max(animationSize.height, textSize.height) + 4.0 * 2.0)
}
if case .wide = self.tooltipStyle {
backgroundHeight += 4.0
} else if self.actionButtonNode != nil {
if self.actionButtonNode != nil {
backgroundHeight += 4.0
}
@ -739,6 +742,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
}
}
private var didRequestDismiss = false
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let event = event {
if let _ = self.openActiveTextItem, let result = self.textNode.hitTest(self.view.convert(point, to: self.textNode.view), with: event) {
@ -753,14 +757,19 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
if let actionButtonNode = self.actionButtonNode, let result = actionButtonNode.hitTest(self.convert(point, to: actionButtonNode), with: event) {
return result
}
switch self.shouldDismissOnTouch(point, self.containerNode.frame) {
case .ignore:
break
case let .dismiss(consume):
self.requestDismiss()
if consume {
return self.view
if !self.didRequestDismiss {
switch self.shouldDismissOnTouch(point, self.containerNode.frame) {
case .ignore:
break
case let .dismiss(consume):
self.requestDismiss()
if consume {
self.didRequestDismiss = true
return self.view
}
}
} else {
return self.view
}
return nil
}
@ -915,7 +924,7 @@ public final class TooltipScreen: ViewController {
public enum Style {
case `default`
case light
case customBlur(UIColor)
case customBlur(UIColor, CGFloat)
case gradient(UIColor, UIColor)
case wide
}