mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-28 19:05:49 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
9c9fd6cc03
@ -364,6 +364,8 @@ public enum ChatPresentationInputQueryResult: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public let ChatControllerCount = Atomic<Int32>(value: 0)
|
||||
|
||||
public protocol ChatController: ViewController {
|
||||
var chatLocation: ChatLocation { get }
|
||||
var canReadHistory: ValuePromise<Bool> { get }
|
||||
|
||||
@ -152,6 +152,8 @@ public enum FetchManagerPriority: Comparable {
|
||||
public let FetchCompleteRange = IndexSet(integersIn: 0 ..< Int(Int32.max) as Range<Int>)
|
||||
|
||||
public protocol FetchManager {
|
||||
var queue: Queue { get }
|
||||
|
||||
func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: IndexSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal<Void, NoError>
|
||||
func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource)
|
||||
func fetchStatus(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource) -> Signal<MediaResourceStatus, NoError>
|
||||
|
||||
@ -60,6 +60,31 @@ public func messageMediaImageCancelInteractiveFetch(context: AccountContext, mes
|
||||
context.fetchManager.cancelInteractiveFetches(category: .image, location: .chat(messageId.peerId), locationKey: .messageId(messageId), resource: resource)
|
||||
}
|
||||
|
||||
public func messageMediaFileStatus(context: AccountContext, messageId: MessageId, file: TelegramMediaFile) -> Signal<MediaResourceStatus, NoError> {
|
||||
return context.fetchManager.fetchStatus(category: fetchCategoryForFile(file), location: .chat(messageId.peerId), locationKey: .messageId(messageId), resource: file.resource)
|
||||
public func messageMediaFileStatus(context: AccountContext, messageId: MessageId, file: TelegramMediaFile, adjustForVideoThumbnail: Bool = false) -> Signal<MediaResourceStatus, NoError> {
|
||||
let fileStatus = context.fetchManager.fetchStatus(category: fetchCategoryForFile(file), location: .chat(messageId.peerId), locationKey: .messageId(messageId), resource: file.resource)
|
||||
if !adjustForVideoThumbnail {
|
||||
return fileStatus
|
||||
}
|
||||
|
||||
var thumbnailStatus: Signal<MediaResourceStatus?, NoError> = .single(nil)
|
||||
if let videoThumbnail = file.videoThumbnails.first {
|
||||
thumbnailStatus = context.account.postbox.mediaBox.resourceStatus(videoThumbnail.resource)
|
||||
|> map(Optional.init)
|
||||
}
|
||||
|
||||
return combineLatest(queue: context.fetchManager.queue,
|
||||
fileStatus,
|
||||
thumbnailStatus
|
||||
)
|
||||
|> map { fileStatus, thumbnailStatus -> MediaResourceStatus in
|
||||
guard let thumbnailStatus = thumbnailStatus else {
|
||||
return fileStatus
|
||||
}
|
||||
if case .Local = thumbnailStatus {
|
||||
return thumbnailStatus
|
||||
} else {
|
||||
return fileStatus
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
}
|
||||
|
||||
@ -207,7 +207,7 @@ public final class ActivityIndicator: ASDisplayNode {
|
||||
indicatorSize = CGSize(width: diameter, height: diameter)
|
||||
shouldScale = !forceDefault
|
||||
}
|
||||
self.indicatorNode.frame = CGRect(origin: CGPoint(x: floor((size.width - indicatorSize.width) / 2.0), y: floor((size.height - indicatorSize.height) / 2.0)), size: indicatorSize)
|
||||
self.indicatorNode.frame = CGRect(origin: CGPoint(x: ((size.width - indicatorSize.width) / 2.0), y: ((size.height - indicatorSize.height) / 2.0)), size: indicatorSize)
|
||||
if shouldScale, let indicatorView = self.indicatorView {
|
||||
let intrinsicSize = indicatorView.bounds.size
|
||||
self.subnodeTransform = CATransform3DMakeScale(min(1.0, indicatorSize.width / intrinsicSize.width), min(1.0, indicatorSize.height / intrinsicSize.height), 1.0)
|
||||
|
||||
@ -1065,7 +1065,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
return
|
||||
}
|
||||
|
||||
#if false && DEBUG
|
||||
#if true && DEBUG
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0, execute: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
||||
@ -594,7 +594,10 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS
|
||||
entries.append(.photoPreview(presentationData.theme, experimentalSettings.chatListPhotos))
|
||||
entries.append(.knockoutWallpaper(presentationData.theme, experimentalSettings.knockoutWallpaper))
|
||||
entries.append(.alternativeFolderTabs(experimentalSettings.foldersTabAtBottom))
|
||||
#if DEBUG
|
||||
// There was no time to un-merge the experimental branch. Nothing to see here yet.
|
||||
entries.append(.videoCalls(experimentalSettings.videoCalls))
|
||||
#endif
|
||||
|
||||
if let backupHostOverride = networkSettings?.backupHostOverride {
|
||||
entries.append(.hostInfo(presentationData.theme, "Host: \(backupHostOverride)"))
|
||||
|
||||
@ -476,7 +476,7 @@ func initializedNetwork(arguments: NetworkInitializationArguments, supplementary
|
||||
} else {
|
||||
seedAddressList = [
|
||||
1: ["149.154.175.50", "2001:b28:f23d:f001::a"],
|
||||
2: ["149.154.167.50", "2001:67c:4e8:f002::a"],
|
||||
2: ["149.154.167.50", "95.161.76.100", "2001:67c:4e8:f002::a"],
|
||||
3: ["149.154.175.100", "2001:b28:f23d:f003::a"],
|
||||
4: ["149.154.167.91", "2001:67c:4e8:f004::a"],
|
||||
5: ["149.154.171.5", "2001:b28:f23f:f005::a"]
|
||||
|
||||
@ -140,8 +140,6 @@ private func calculateSlowmodeActiveUntilTimestamp(account: Account, untilTimest
|
||||
}
|
||||
}
|
||||
|
||||
let ChatControllerCount = Atomic<Int32>(value: 0)
|
||||
|
||||
public final class ChatControllerImpl: TelegramBaseController, ChatController, GalleryHiddenMediaTarget, UIDropInteractionDelegate {
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
@ -542,6 +540,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.controllerInteraction?.addContact(phoneNumber)
|
||||
}
|
||||
}, storeMediaPlaybackState: { [weak self] messageId, timestamp in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var storedState: MediaPlaybackStoredState?
|
||||
if let timestamp = timestamp {
|
||||
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: .x1)
|
||||
|
||||
@ -653,7 +653,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
}
|
||||
}
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
updatedStatusSignal = combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file), context.account.pendingMessageManager.pendingMessageStatus(message.id) |> map { $0.0 })
|
||||
updatedStatusSignal = combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file, adjustForVideoThumbnail: true), context.account.pendingMessageManager.pendingMessageStatus(message.id) |> map { $0.0 })
|
||||
|> map { resourceStatus, pendingStatus -> (MediaResourceStatus, MediaResourceStatus?) in
|
||||
if let pendingStatus = pendingStatus {
|
||||
let adjustedProgress = max(pendingStatus.progress, 0.027)
|
||||
|
||||
@ -1433,19 +1433,18 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
func updateIsProcessingInlineRequest(_ value: Bool) {
|
||||
if value {
|
||||
if self.searchActivityIndicator == nil, let currentState = self.presentationInterfaceState {
|
||||
let searchActivityIndicator = ActivityIndicator(type: .custom(currentState.theme.list.itemAccentColor, 11.0, 1.0, false))
|
||||
let searchActivityIndicator = ActivityIndicator(type: .custom(currentState.theme.list.itemAccentColor, 20.0, 1.5, true))
|
||||
searchActivityIndicator.isUserInteractionEnabled = false
|
||||
self.searchActivityIndicator = searchActivityIndicator
|
||||
let indicatorSize = searchActivityIndicator.measure(CGSize(width: 100.0, height: 100.0))
|
||||
let size = self.searchLayoutClearButton.bounds.size
|
||||
searchActivityIndicator.frame = CGRect(origin: CGPoint(x: floor((size.width - indicatorSize.width) / 2.0), y: floor((size.height - indicatorSize.height) / 2.0) + 1.0), size: indicatorSize)
|
||||
self.searchLayoutClearImageNode.isHidden = true
|
||||
searchActivityIndicator.frame = CGRect(origin: CGPoint(x: floor((size.width - indicatorSize.width) / 2.0) + 0.0, y: floor((size.height - indicatorSize.height) / 2.0) - 0.0), size: indicatorSize)
|
||||
//self.searchLayoutClearImageNode.isHidden = true
|
||||
self.searchLayoutClearButton.addSubnode(searchActivityIndicator)
|
||||
//searchActivityIndicator.layer.sublayerTransform = CATransform3DMakeScale(0.5, 0.5, 1.0)
|
||||
}
|
||||
} else if let searchActivityIndicator = self.searchActivityIndicator {
|
||||
self.searchActivityIndicator = nil
|
||||
self.searchLayoutClearImageNode.isHidden = false
|
||||
//self.searchLayoutClearImageNode.isHidden = false
|
||||
searchActivityIndicator.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ private final class FetchManagerCategoryContext {
|
||||
}
|
||||
|
||||
public final class FetchManagerImpl: FetchManager {
|
||||
private let queue = Queue.mainQueue()
|
||||
public let queue = Queue.mainQueue()
|
||||
private let postbox: Postbox
|
||||
private let storeManager: DownloadedMediaStoreManager?
|
||||
private var nextEpisodeId: Int32 = 0
|
||||
|
||||
@ -10,18 +10,22 @@ import StickerResources
|
||||
import AccountContext
|
||||
import AnimatedStickerNode
|
||||
import TelegramAnimatedStickerNode
|
||||
import ShimmerEffect
|
||||
import TelegramPresentationData
|
||||
|
||||
final class HorizontalStickerGridItem: GridItem {
|
||||
let account: Account
|
||||
let file: TelegramMediaFile
|
||||
let theme: PresentationTheme
|
||||
let isPreviewed: (HorizontalStickerGridItem) -> Bool
|
||||
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void
|
||||
|
||||
let section: GridSection? = nil
|
||||
|
||||
init(account: Account, file: TelegramMediaFile, isPreviewed: @escaping (HorizontalStickerGridItem) -> Bool, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void) {
|
||||
init(account: Account, file: TelegramMediaFile, theme: PresentationTheme, isPreviewed: @escaping (HorizontalStickerGridItem) -> Bool, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void) {
|
||||
self.account = account
|
||||
self.file = file
|
||||
self.theme = theme
|
||||
self.isPreviewed = isPreviewed
|
||||
self.sendSticker = sendSticker
|
||||
}
|
||||
@ -47,6 +51,7 @@ final class HorizontalStickerGridItemNode: GridItemNode {
|
||||
private var currentState: (Account, HorizontalStickerGridItem, CGSize)?
|
||||
private let imageNode: TransformImageNode
|
||||
private var animationNode: AnimatedStickerNode?
|
||||
private var placeholderNode: ShimmerEffectNode?
|
||||
|
||||
private let stickerFetchedDisposable = MetaDisposable()
|
||||
|
||||
@ -76,17 +81,47 @@ final class HorizontalStickerGridItemNode: GridItemNode {
|
||||
|
||||
override init() {
|
||||
self.imageNode = TransformImageNode()
|
||||
self.placeholderNode = ShimmerEffectNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.imageNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
self.addSubnode(self.imageNode)
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
placeholderNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
self.addSubnode(placeholderNode)
|
||||
}
|
||||
|
||||
var firstTime = true
|
||||
self.imageNode.imageUpdated = { [weak self] image in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if image != nil {
|
||||
strongSelf.removePlaceholder(animated: !firstTime)
|
||||
}
|
||||
firstTime = false
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.stickerFetchedDisposable.dispose()
|
||||
}
|
||||
|
||||
private func removePlaceholder(animated: Bool) {
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
self.placeholderNode = nil
|
||||
if !animated {
|
||||
placeholderNode.removeFromSupernode()
|
||||
} else {
|
||||
placeholderNode.alpha = 0.0
|
||||
placeholderNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak placeholderNode] _ in
|
||||
placeholderNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
@ -105,7 +140,11 @@ final class HorizontalStickerGridItemNode: GridItemNode {
|
||||
animationNode.transform = self.imageNode.transform
|
||||
animationNode.visibility = self.isVisibleInGrid
|
||||
animationNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
|
||||
self.addSubnode(animationNode)
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
self.insertSubnode(animationNode, belowSubnode: placeholderNode)
|
||||
} else {
|
||||
self.addSubnode(animationNode)
|
||||
}
|
||||
self.animationNode = animationNode
|
||||
}
|
||||
|
||||
@ -145,6 +184,15 @@ final class HorizontalStickerGridItemNode: GridItemNode {
|
||||
let bounds = self.bounds
|
||||
let boundingSize = bounds.insetBy(dx: 2.0, dy: 2.0).size
|
||||
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
let placeholderFrame = CGRect(origin: CGPoint(x: floor((bounds.width - boundingSize.width) / 2.0), y: floor((bounds.height - boundingSize.height) / 2.0)), size: boundingSize)
|
||||
placeholderNode.frame = bounds
|
||||
|
||||
if let theme = self.currentState?.1.theme {
|
||||
placeholderNode.update(backgroundColor: theme.list.plainBackgroundColor, foregroundColor: theme.list.mediaPlaceholderColor.mixedWith(theme.list.plainBackgroundColor, alpha: 0.4), shimmeringColor: theme.list.mediaPlaceholderColor.withAlphaComponent(0.3), shapes: [.roundedRect(rect: placeholderFrame, cornerRadius: 10.0)], size: bounds.size)
|
||||
}
|
||||
}
|
||||
|
||||
if let (_, _, mediaDimensions) = self.currentState {
|
||||
let imageSize = mediaDimensions.aspectFitted(boundingSize)
|
||||
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
|
||||
@ -160,6 +208,12 @@ final class HorizontalStickerGridItemNode: GridItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func updateAbsoluteRect(_ absoluteRect: CGRect, within containerSize: CGSize) {
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
placeholderNode.updateAbsoluteRect(absoluteRect, within: containerSize)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) {
|
||||
if let (_, item, _) = self.currentState, case .ended = recognizer.state {
|
||||
self.sendSticker?(.standalone(media: item.file), self, self.bounds)
|
||||
|
||||
@ -65,8 +65,8 @@ private struct StickerEntry: Identifiable, Comparable {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(account: Account, stickersInteraction: HorizontalStickersChatContextPanelInteraction, interfaceInteraction: ChatPanelInterfaceInteraction) -> GridItem {
|
||||
return HorizontalStickerGridItem(account: account, file: self.file, isPreviewed: { item in
|
||||
func item(account: Account, stickersInteraction: HorizontalStickersChatContextPanelInteraction, interfaceInteraction: ChatPanelInterfaceInteraction, theme: PresentationTheme) -> GridItem {
|
||||
return HorizontalStickerGridItem(account: account, file: self.file, theme: theme, isPreviewed: { item in
|
||||
return false//stickersInteraction.previewedStickerItem == item
|
||||
}, sendSticker: { file, node, rect in
|
||||
let _ = interfaceInteraction.sendSticker(file, node, rect)
|
||||
@ -83,15 +83,15 @@ private struct StickerEntryTransition {
|
||||
let scrollToItem: GridNodeScrollToItem?
|
||||
}
|
||||
|
||||
private func preparedGridEntryTransition(account: Account, from fromEntries: [StickerEntry], to toEntries: [StickerEntry], stickersInteraction: HorizontalStickersChatContextPanelInteraction, interfaceInteraction: ChatPanelInterfaceInteraction) -> StickerEntryTransition {
|
||||
private func preparedGridEntryTransition(account: Account, from fromEntries: [StickerEntry], to toEntries: [StickerEntry], stickersInteraction: HorizontalStickersChatContextPanelInteraction, interfaceInteraction: ChatPanelInterfaceInteraction, theme: PresentationTheme) -> StickerEntryTransition {
|
||||
let stationaryItems: GridNodeStationaryItems = .none
|
||||
let scrollToItem: GridNodeScrollToItem? = nil
|
||||
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices
|
||||
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, stickersInteraction: stickersInteraction, interfaceInteraction: interfaceInteraction), previousIndex: $0.2) }
|
||||
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, stickersInteraction: stickersInteraction, interfaceInteraction: interfaceInteraction)) }
|
||||
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, stickersInteraction: stickersInteraction, interfaceInteraction: interfaceInteraction, theme: theme), previousIndex: $0.2) }
|
||||
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, stickersInteraction: stickersInteraction, interfaceInteraction: interfaceInteraction, theme: theme)) }
|
||||
|
||||
return StickerEntryTransition(deletions: deletions, insertions: insertions, updates: updates, updateFirstIndexInSectionOffset: nil, stationaryItems: stationaryItems, scrollToItem: scrollToItem)
|
||||
}
|
||||
@ -257,7 +257,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, bottomInset: validLayout.3, transition: .immediate, interfaceState: validLayout.4)
|
||||
}
|
||||
|
||||
let transition = preparedGridEntryTransition(account: self.context.account, from: previousEntries, to: entries, stickersInteraction: self.stickersInteraction, interfaceInteraction: self.interfaceInteraction!)
|
||||
let transition = preparedGridEntryTransition(account: self.context.account, from: previousEntries, to: entries, stickersInteraction: self.stickersInteraction, interfaceInteraction: self.interfaceInteraction!, theme: self.theme)
|
||||
self.enqueueTransition(transition)
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private var theme: PresentationTheme
|
||||
|
||||
private let scrollNode: ASScrollNode
|
||||
private var items: [TelegramMediaFile] = []
|
||||
@ -36,8 +37,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
var updateBackgroundOffset: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
|
||||
var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Void)?
|
||||
|
||||
init(context: AccountContext) {
|
||||
init(context: AccountContext, theme: PresentationTheme) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
|
||||
self.scrollNode = ASScrollNode()
|
||||
|
||||
@ -182,7 +184,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
columnIndex += 1
|
||||
if columnIndex == itemsPerRow {
|
||||
columnIndex = 0
|
||||
topOffset += itemSize
|
||||
topOffset += itemSize + itemSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,6 +197,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
var minVisibleY = self.scrollNode.view.bounds.minY
|
||||
var maxVisibleY = self.scrollNode.view.bounds.maxY
|
||||
|
||||
let containerSize = self.scrollNode.view.bounds.size
|
||||
let absoluteOffset: CGFloat = -self.scrollNode.view.contentOffset.y
|
||||
|
||||
let minActivatedY = minVisibleY
|
||||
let maxActivatedY = maxVisibleY
|
||||
|
||||
@ -217,6 +222,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
let item = HorizontalStickerGridItem(
|
||||
account: self.context.account,
|
||||
file: item.file,
|
||||
theme: self.theme,
|
||||
isPreviewed: { _ in
|
||||
return false
|
||||
}, sendSticker: { [weak self] file, node, rect in
|
||||
@ -235,6 +241,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
self.scrollNode.addSubnode(itemNode)
|
||||
}
|
||||
itemNode.frame = itemFrame
|
||||
itemNode.updateAbsoluteRect(itemFrame.offsetBy(dx: 0.0, dy: absoluteOffset), within: containerSize)
|
||||
itemNode.isVisibleInGrid = isActivated
|
||||
validIds.insert(item.file.fileId)
|
||||
}
|
||||
@ -296,7 +303,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode {
|
||||
|
||||
context.restoreGState()
|
||||
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
context.setFillColor(theme.list.plainBackgroundColor.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter)))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(backroundDiameter / 2.0 + shadowBlur), topCapHeight: 0)
|
||||
|
||||
@ -314,7 +321,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode {
|
||||
|
||||
self.backgroundContainerNode = ASDisplayNode()
|
||||
|
||||
self.stickersNode = InlineReactionSearchStickersNode(context: context)
|
||||
self.stickersNode = InlineReactionSearchStickersNode(context: context, theme: theme)
|
||||
|
||||
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
|
||||
|
||||
@ -330,7 +337,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode {
|
||||
|
||||
self.addSubnode(self.containerNode)
|
||||
|
||||
self.backgroundNode.backgroundColor = .white
|
||||
self.backgroundNode.backgroundColor = theme.list.plainBackgroundColor
|
||||
|
||||
self.stickersNode.updateBackgroundOffset = { [weak self] offset, transition in
|
||||
guard let strongSelf = self, let (_, _) = strongSelf.validLayout else {
|
||||
@ -350,6 +357,9 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode {
|
||||
}
|
||||
let _ = strongSelf.controllerInteraction?.sendSticker(file, true, node, rect)
|
||||
}
|
||||
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
self.view.disablesInteractiveKeyboardGestureRecognizer = true
|
||||
}
|
||||
|
||||
func updateResults(results: [TelegramMediaFile]) {
|
||||
|
||||
@ -513,10 +513,13 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.panGesture(_:)), allowedDirections: { [weak self] _ in
|
||||
let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.panGesture(_:)), allowedDirections: { [weak self] point in
|
||||
guard let strongSelf = self, let currentPaneKey = strongSelf.currentPaneKey, let availablePanes = strongSelf.currentParams?.data?.availablePanes, let index = availablePanes.firstIndex(of: currentPaneKey) else {
|
||||
return []
|
||||
}
|
||||
if strongSelf.tabsContainerNode.bounds.contains(strongSelf.view.convert(point, to: strongSelf.tabsContainerNode.view)) {
|
||||
return []
|
||||
}
|
||||
if index == 0 {
|
||||
return .left
|
||||
}
|
||||
|
||||
@ -64,8 +64,10 @@ final class SoftwareVideoThumbnailNode: ASDisplayNode {
|
||||
if let strongSelf = self {
|
||||
strongSelf.contents = image.cgImage
|
||||
if let placeholder = strongSelf.placeholder {
|
||||
strongSelf.placeholder = placeholder
|
||||
placeholder.removeFromSupernode()
|
||||
strongSelf.placeholder = nil
|
||||
placeholder.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak placeholder] _ in
|
||||
placeholder?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
strongSelf.ready?()
|
||||
}
|
||||
|
||||
@ -106,6 +106,19 @@ static bool notyfyingShiftState = false;
|
||||
[RuntimeUtils swizzleInstanceMethodOfClass:[UIViewController class] currentSelector:@selector(presentViewController:animated:completion:) newSelector:@selector(_65087dc8_presentViewController:animated:completion:)];
|
||||
[RuntimeUtils swizzleInstanceMethodOfClass:[UIViewController class] currentSelector:@selector(setNeedsStatusBarAppearanceUpdate) newSelector:@selector(_65087dc8_setNeedsStatusBarAppearanceUpdate)];
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
if (@available(iOS 13, *)) {
|
||||
Class UIUndoGestureInteractionClass = NSClassFromString(@"UIUndoGestureInteraction");
|
||||
SEL addGestureRecognizersSelector = @selector(_addGestureRecognizers);
|
||||
IMP doNothing = imp_implementationWithBlock(^void(__unused id _self) {
|
||||
return;
|
||||
});
|
||||
|
||||
method_setImplementation(class_getInstanceMethod(UIUndoGestureInteractionClass, addGestureRecognizersSelector), doNothing);
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
//[RuntimeUtils swizzleInstanceMethodOfClass:NSClassFromString(@"UIKeyboardImpl") currentSelector:@selector(notifyShiftState) withAnotherClass:[UIKeyboardImpl_65087dc8 class] newSelector:@selector(notifyShiftState)];
|
||||
//[RuntimeUtils swizzleInstanceMethodOfClass:NSClassFromString(@"UIInputWindowController") currentSelector:@selector(updateViewConstraints) withAnotherClass:[UIInputWindowController_65087dc8 class] newSelector:@selector(updateViewConstraints)];
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user