Various Fixes

This commit is contained in:
Ilya Laktyushin 2021-03-23 06:42:47 +05:00
parent e6eff16df1
commit 96e5b0b057
14 changed files with 161 additions and 98 deletions

View File

@ -1,6 +1,8 @@
import UIKit
import AsyncDisplayKit
private let titleFont = Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers])
private var backArrowImageCache: [Int32: UIImage] = [:]
class SparseNode: ASDisplayNode {
@ -269,7 +271,7 @@ open class NavigationBar: ASDisplayNode {
private var title: String? {
didSet {
if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title
if self.titleNode.supernode == nil {
self.buttonsContainerNode.addSubnode(self.titleNode)
@ -744,7 +746,7 @@ open class NavigationBar: ASDisplayNode {
self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05)
self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor)
if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title
}
self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor
@ -820,7 +822,7 @@ open class NavigationBar: ASDisplayNode {
self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05)
self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor)
if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title
}
self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor
@ -1079,7 +1081,7 @@ open class NavigationBar: ASDisplayNode {
}
} else if let title = self.title {
let node = ImmediateTextNode()
node.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: foregroundColor)
node.attributedText = NSAttributedString(string: title, font: titleFont, textColor: foregroundColor)
return node
} else {
return nil

View File

@ -154,6 +154,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var setPlayRate: ((Double) -> Void)?
var fetchControl: (() -> Void)?
var interacting: ((Bool) -> Void)?
private var seekTimer: SwiftSignalKit.Timer?
private var currentIsPaused: Bool = true
private var seekRate: Double = 1.0
@ -892,6 +894,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if messages.count == 1 {
strongSelf.commitDeleteMessages(messages, ask: true)
} else {
strongSelf.interacting?(true)
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
@ -930,8 +934,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.dismissed = { [weak self] _ in
self?.interacting?(false)
}
let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
@ -1012,6 +1018,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forEveryone).start()
strongSelf.controllerInteraction?.dismissController()
} else if !items.isEmpty {
strongSelf.interacting?(true)
actionSheet.dismissed = { [weak self] _ in
self?.interacting?(false)
}
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
@ -1024,13 +1034,17 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
@objc func actionButtonPressed() {
self.interacting?(true)
if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageGroup(currentMessage.id) ?? []
} |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty {
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme?
if !presentationData.theme.overallDarkAppearance {
forceTheme = defaultDarkColorPresentationTheme
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
var generalMessageContentKind: MessageContentKind?
@ -1109,7 +1123,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
}
let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1170,7 +1187,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let shareAction: ([Message]) -> Void = { messages in
if let strongSelf = self {
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1240,7 +1260,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
})
} else if let (webPage, media) = self.currentWebPageAndMedia {
var presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme?
if !presentationData.theme.overallDarkAppearance {
forceTheme = defaultDarkColorPresentationTheme
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
@ -1265,7 +1287,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if availableOpenInOptions(context: self.context, item: item).count > 1 {
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Conversation_FileOpenIn, action: { [weak self] in
if let strongSelf = self {
let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in
let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: forceTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in
if let strongSelf = self {
strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
}
@ -1290,7 +1312,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}
}
}
let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme)
let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in

View File

@ -120,7 +120,7 @@ final class ChatVideoGalleryItemScrubberView: UIView {
self.fetchStatusDisposable.dispose()
}
var collapsed: Bool = false
var collapsed: Bool?
func setCollapsed(_ collapsed: Bool, animated: Bool) {
guard self.collapsed != collapsed else {
return
@ -128,15 +128,14 @@ final class ChatVideoGalleryItemScrubberView: UIView {
self.collapsed = collapsed
guard let (size, _, _) = self.containerLayout else {
return
}
let alpha: CGFloat = collapsed ? 0.0 : 1.0
self.leftTimestampNode.alpha = alpha
self.rightTimestampNode.alpha = alpha
self.infoNode.alpha = size.width < size.height && !self.collapsed ? 1.0 : 0.0
self.updateScrubberVisibility(animated: animated)
if let (size, _, _) = self.containerLayout {
self.infoNode.alpha = size.width < size.height && !collapsed ? 1.0 : 0.0
}
}
private func updateScrubberVisibility(animated: Bool) {
@ -144,10 +143,10 @@ final class ChatVideoGalleryItemScrubberView: UIView {
var alpha: CGFloat = 1.0
if let playbackStatus = self.playbackStatus, playbackStatus.duration <= 30.0 {
} else {
alpha = self.collapsed ? 0.0 : 1.0
alpha = self.collapsed == true ? 0.0 : 1.0
collapsed = false
}
self.scrubberNode.setCollapsed(collapsed, animated: animated)
self.scrubberNode.setCollapsed(collapsed == true, animated: animated)
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .linear) : .immediate
transition.updateAlpha(node: self.scrubberNode, alpha: alpha)
}
@ -285,7 +284,7 @@ final class ChatVideoGalleryItemScrubberView: UIView {
let infoSize = self.infoNode.measure(infoConstrainedSize)
self.infoNode.bounds = CGRect(origin: CGPoint(), size: infoSize)
transition.updatePosition(node: self.infoNode, position: CGPoint(x: size.width / 2.0, y: infoOffset + infoSize.height / 2.0))
self.infoNode.alpha = size.width < size.height && !self.collapsed ? 1.0 : 0.0
self.infoNode.alpha = size.width < size.height && self.collapsed == false ? 1.0 : 0.0
self.scrubberNode.frame = CGRect(origin: CGPoint(x: scrubberInset, y: 6.0), size: CGSize(width: size.width - leftInset - rightInset - scrubberInset * 2.0, height: scrubberHeight))
}

View File

@ -6,6 +6,7 @@ import Display
public final class GalleryFooterNode: ASDisplayNode {
private let backgroundNode: ASDisplayNode
private var currentThumbnailPanelHeight: CGFloat?
private var currentFooterContentNode: GalleryFooterContentNode?
private var currentOverlayContentNode: GalleryOverlayContentNode?
private var currentLayout: (ContainerViewLayout, CGFloat, Bool)?
@ -36,11 +37,16 @@ public final class GalleryFooterNode: ASDisplayNode {
let cleanInsets = layout.insets(options: [])
var dismissedCurrentFooterContentNode: GalleryFooterContentNode?
var dismissedThumbnailPanelHeight: CGFloat?
if self.currentFooterContentNode !== footerContentNode {
if let currentFooterContentNode = self.currentFooterContentNode {
currentFooterContentNode.requestLayout = nil
dismissedCurrentFooterContentNode = currentFooterContentNode
}
if let currentThumbnailPanelHeight = self.currentThumbnailPanelHeight {
dismissedThumbnailPanelHeight = currentThumbnailPanelHeight
}
self.currentThumbnailPanelHeight = thumbnailPanelHeight
self.currentFooterContentNode = footerContentNode
if let footerContentNode = footerContentNode {
footerContentNode.setVisibilityAlpha(self.visibilityAlpha, animated: transition.isAnimated)
@ -68,10 +74,11 @@ public final class GalleryFooterNode: ASDisplayNode {
}
}
let effectiveThumbnailPanelHeight = self.currentThumbnailPanelHeight ?? thumbnailPanelHeight
var backgroundHeight: CGFloat = 0.0
let verticalOffset: CGFloat = isHidden ? (layout.size.width > layout.size.height ? 44.0 : (thumbnailPanelHeight > 0.0 ? 106.0 : 54.0)) : 0.0
let verticalOffset: CGFloat = isHidden ? (layout.size.width > layout.size.height ? 44.0 : (effectiveThumbnailPanelHeight > 0.0 ? 106.0 : 54.0)) : 0.0
if let footerContentNode = self.currentFooterContentNode {
backgroundHeight = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: thumbnailPanelHeight, transition: transition)
backgroundHeight = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: effectiveThumbnailPanelHeight, transition: transition)
transition.updateFrame(node: footerContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight)))
if let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode {
let contentTransition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)

View File

@ -205,7 +205,9 @@ private final class UniversalVideoGalleryItemOverlayNode: GalleryOverlayContentN
}
override func animateIn(previousContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition) {
transition.updateAlpha(node: self.wrapperNode, alpha: 1.0)
if !self.visibilityAlpha.isZero {
transition.updateAlpha(node: self.wrapperNode, alpha: 1.0)
}
}
override func animateOut(nextContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) {
@ -271,12 +273,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
private let statusNode: RadialStatusNode
private var statusNodeShouldBeHidden = true
private var isCentral = false
private var isCentral: Bool?
private var _isVisible: Bool?
private var initiallyActivated = false
private var hideStatusNodeUntilCentrality = false
private var playOnContentOwnership = false
private var skipInitialPause = false
private var ignorePauseStatus = false
private var validLayout: (ContainerViewLayout, CGFloat)?
private var didPause = false
private var isPaused = true
@ -299,6 +302,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
private var scrubbingFrames = false
private var scrubbingFrameDisposable: Disposable?
private let isPlayingPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
private let isInteractingPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
private let controlsVisiblePromise = ValuePromise<Bool>(true, ignoreRepeated: true)
private var hideControlsDisposable: Disposable?
var playbackCompleted: (() -> Void)?
private var customUnembedWhenPortrait: ((OverlayMediaItemNode) -> Bool)?
@ -323,6 +331,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
super.init()
self.footerContentNode.interacting = { [weak self] value in
self?.isInteractingPromise.set(value)
}
self.overlayContentNode.action = { [weak self] toLandscape in
self?.updateControlsVisibility(!toLandscape)
context.sharedContext.applicationBindings.forceOrientation(toLandscape ? .landscapeRight : .portrait)
@ -436,12 +448,30 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
self.titleContentView = GalleryTitleView(frame: CGRect())
self._titleView.set(.single(self.titleContentView))
let shouldHideControlsSignal: Signal<Void, NoError> = combineLatest(self.isPlayingPromise.get(), self.isInteractingPromise.get(), self.controlsVisiblePromise.get())
|> mapToSignal { isPlaying, isIntracting, controlsVisible -> Signal<Void, NoError> in
if isPlaying && !isIntracting && controlsVisible {
return .single(Void())
|> delay(4.0, queue: Queue.mainQueue())
} else {
return .complete()
}
}
self.hideControlsDisposable = (shouldHideControlsSignal
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self {
strongSelf.updateControlsVisibility(false)
}
})
}
deinit {
self.statusDisposable.dispose()
self.mediaPlaybackStateDisposable.dispose()
self.scrubbingFrameDisposable?.dispose()
self.hideControlsDisposable?.dispose()
}
override func ready() -> Signal<Void, NoError> {
@ -484,21 +514,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
}
private var controlsTimer: SwiftSignalKit.Timer?
private var previousPlaying: Bool?
private func setupControlsTimer() {
let timer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in
self?.updateControlsVisibility(false)
self?.controlsTimer = nil
}, queue: Queue.mainQueue())
timer.start()
self.controlsTimer = timer
}
func setupItem(_ item: UniversalVideoGalleryItem) {
if self.item?.content.id != item.content.id {
self.previousPlaying = nil
self.isPlayingPromise.set(false)
if item.hideControls {
self.statusButtonNode.isHidden = true
@ -665,7 +683,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|> deliverOnMainQueue).start(next: { [weak self] value, fetchStatus in
if let strongSelf = self {
var initialBuffering = false
var playing = false
var isPlaying = false
var isPaused = true
var seekable = hintSeekable
var hasStarted = false
@ -683,7 +701,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
switch value.status {
case .playing:
isPaused = false
playing = true
isPlaying = true
strongSelf.ignorePauseStatus = false
case let .buffering(_, whilePlaying, _, display):
displayProgress = display
initialBuffering = !whilePlaying
@ -716,9 +735,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
isPaused = false
}
} else if strongSelf.actionAtEnd == .stop {
strongSelf.updateControlsVisibility(true)
strongSelf.controlsTimer?.invalidate()
strongSelf.controlsTimer = nil
strongSelf.isPlayingPromise.set(false)
if strongSelf.isCentral == true {
strongSelf.updateControlsVisibility(true)
}
}
}
if !value.duration.isZero {
@ -726,14 +746,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
}
if strongSelf.isCentral && playing && strongSelf.previousPlaying != true && !disablePlayerControls {
strongSelf.controlsTimer?.invalidate()
strongSelf.setupControlsTimer()
} else if !playing {
strongSelf.controlsTimer?.invalidate()
strongSelf.controlsTimer = nil
if !disablePlayerControls && strongSelf.isCentral == true && isPlaying {
strongSelf.isPlayingPromise.set(true)
} else if !isPlaying {
strongSelf.isPlayingPromise.set(false)
}
strongSelf.previousPlaying = playing
var fetching = false
if initialBuffering {
@ -751,7 +768,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
case .Remote:
state = .download(.white)
case let .Fetching(_, progress):
if !playing {
if !isPlaying {
fetching = true
isPaused = true
}
@ -768,13 +785,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
strongSelf.fetchStatus = fetchStatus
if !item.hideControls {
strongSelf.statusNodeShouldBeHidden = (!initialBuffering && (strongSelf.didPause || !isPaused) && !fetching)
strongSelf.statusNodeShouldBeHidden = strongSelf.ignorePauseStatus || (!initialBuffering && (strongSelf.didPause || !isPaused) && !fetching)
strongSelf.statusButtonNode.isHidden = strongSelf.hideStatusNodeUntilCentrality || strongSelf.statusNodeShouldBeHidden
}
if isAnimated || disablePlayerControls {
strongSelf.footerContentNode.content = .info
} else if isPaused {
} else if isPaused && !strongSelf.ignorePauseStatus {
if hasStarted || strongSelf.didPause {
strongSelf.footerContentNode.content = .playback(paused: true, seekable: seekable)
} else if let fetchStatus = fetchStatus, !strongSelf.requiresDownload {
@ -808,10 +825,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if let strongSelf = self, !isAnimated {
videoNode?.seek(0.0)
if strongSelf.actionAtEnd == .stop && strongSelf.isCentral {
if strongSelf.actionAtEnd == .stop && strongSelf.isCentral == true {
strongSelf.isPlayingPromise.set(false)
strongSelf.updateControlsVisibility(true)
strongSelf.controlsTimer?.invalidate()
strongSelf.controlsTimer = nil
}
}
}
@ -834,8 +850,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
override func controlsVisibilityUpdated(isVisible: Bool) {
self.controlsTimer?.invalidate()
self.controlsTimer = nil
self.controlsVisiblePromise.set(isVisible)
self.videoNode?.isUserInteractionEnabled = isVisible ? self.videoNodeUserInteractionEnabled : false
self.videoNode?.notifyPlaybackControlsHidden(!isVisible)
@ -915,8 +930,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
}
} else {
self.controlsTimer?.invalidate()
self.controlsTimer = nil
self.isPlayingPromise.set(false)
self.dismissOnOrientationChange = false
if videoNode.ownsContentNode {
@ -941,6 +955,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if self.skipInitialPause {
self.skipInitialPause = false
} else {
self.ignorePauseStatus = true
videoNode.pause()
videoNode.seek(0.0)
}
@ -973,7 +988,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
override func activateAsInitial() {
if let videoNode = self.videoNode, self.isCentral {
if let videoNode = self.videoNode, self.isCentral == true {
self.initiallyActivated = true
var isAnimated = false
@ -1614,6 +1629,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|> delay(0.15, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
self.isInteractingPromise.set(true)
let signal = stickerPacksAttachedToMedia(account: self.context.account, media: media)
|> afterDisposed {
Queue.mainQueue().async {
@ -1627,7 +1644,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
}
let baseNavigationController = strongSelf.baseNavigationController()
baseNavigationController?.view.endEditing(true)
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil)
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, dismissed: { [weak self] in
self?.isInteractingPromise.set(false)
})
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
})
}

View File

@ -231,6 +231,9 @@ public final class SearchDisplayController {
self.searchBar.activate()
if let placeholder = placeholder {
self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
if self.contentNode.hasDim {
self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
}
} else {
self.searchBar.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
@ -264,7 +267,7 @@ public final class SearchDisplayController {
contentNavigationBarHeight += 28.0
}
self.backgroundNode.layer.animatePosition(from: contentNodePosition, to: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (targetTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
// self.backgroundNode.layer.animatePosition(from: contentNodePosition, to: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (targetTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
}
backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak backgroundNode] _ in
backgroundNode?.removeFromSupernode()

View File

@ -299,7 +299,7 @@ public final class ShareController: ViewController {
private var currentAccount: Account
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
private let forcedTheme: PresentationTheme?
private let forceTheme: PresentationTheme?
private let externalShare: Bool
private let immediateExternalShare: Bool
@ -327,11 +327,11 @@ public final class ShareController: ViewController {
}
}
public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forcedTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
self.init(sharedContext: context.sharedContext, currentContext: context, subject: subject, presetText: presetText, preferredAction: preferredAction, showInChat: showInChat, fromForeignApp: fromForeignApp, segmentedValues: segmentedValues, externalShare: externalShare, immediateExternalShare: immediateExternalShare, switchableAccounts: switchableAccounts, immediatePeerId: immediatePeerId, forcedTheme: forcedTheme, forcedActionTitle: forcedActionTitle)
public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
self.init(sharedContext: context.sharedContext, currentContext: context, subject: subject, presetText: presetText, preferredAction: preferredAction, showInChat: showInChat, fromForeignApp: fromForeignApp, segmentedValues: segmentedValues, externalShare: externalShare, immediateExternalShare: immediateExternalShare, switchableAccounts: switchableAccounts, immediatePeerId: immediatePeerId, forceTheme: forceTheme, forcedActionTitle: forcedActionTitle)
}
public init(sharedContext: SharedAccountContext, currentContext: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forcedTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
public init(sharedContext: SharedAccountContext, currentContext: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
self.sharedContext = sharedContext
self.currentContext = currentContext
self.currentAccount = currentContext.account
@ -343,11 +343,11 @@ public final class ShareController: ViewController {
self.immediatePeerId = immediatePeerId
self.fromForeignApp = fromForeignApp
self.segmentedValues = segmentedValues
self.forcedTheme = forcedTheme
self.forceTheme = forceTheme
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
if let forcedTheme = self.forcedTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme)
if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
}
super.init(navigationBarPresentationData: nil)
@ -487,17 +487,17 @@ public final class ShareController: ViewController {
return
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forcedTheme: self.forcedTheme, segmentedValues: self.segmentedValues)
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forceTheme: self.forceTheme, segmentedValues: self.segmentedValues)
self.controllerNode.completed = self.completed
self.controllerNode.dismiss = { [weak self] shared in
self?.presentingViewController?.dismiss(animated: false, completion: nil)
self?.dismissed?(shared)
self?.presentingViewController?.dismiss(animated: false, completion: nil)
}
self.controllerNode.cancel = { [weak self] in
self?.controllerNode.view.endEditing(true)
self?.controllerNode.animateOut(shared: false, completion: {
self?.presentingViewController?.dismiss(animated: false, completion: nil)
self?.dismissed?(false)
self?.presentingViewController?.dismiss(animated: false, completion: nil)
})
}
self.controllerNode.share = { [weak self] text, peerIds in

View File

@ -25,7 +25,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private let sharedContext: SharedAccountContext
private var context: AccountContext?
private var presentationData: PresentationData
private let forcedTheme: PresentationTheme?
private let forceTheme: PresentationTheme?
private let externalShare: Bool
private let immediateExternalShare: Bool
private var immediatePeerId: PeerId?
@ -80,10 +80,10 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private let presetText: String?
init(sharedContext: SharedAccountContext, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forcedTheme: PresentationTheme?, segmentedValues: [ShareControllerSegmentedValue]?) {
init(sharedContext: SharedAccountContext, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, segmentedValues: [ShareControllerSegmentedValue]?) {
self.sharedContext = sharedContext
self.presentationData = sharedContext.currentPresentationData.with { $0 }
self.forcedTheme = forcedTheme
self.forceTheme = forceTheme
self.externalShare = externalShare
self.immediateExternalShare = immediateExternalShare
self.immediatePeerId = immediatePeerId
@ -96,8 +96,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
self.defaultAction = defaultAction
self.requestLayout = requestLayout
if let forcedTheme = self.forcedTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme)
if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
}
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
@ -272,8 +272,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
return
}
self.presentationData = presentationData
if let forcedTheme = self.forcedTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme)
if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
}
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)

View File

@ -25,7 +25,9 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
}
private var animatedIn = false
private var dismissed = false
private var isDismissed = false
public var dismissed: (() -> Void)?
private let context: AccountContext
private let mode: StickerPackPreviewControllerMode
@ -150,6 +152,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
}))
}, actionPerformed: self.actionPerformed)
self.controllerNode.dismiss = { [weak self] in
self?.dismissed?()
self?.presentingViewController?.dismiss(animated: false, completion: nil)
}
self.controllerNode.cancel = { [weak self] in
@ -264,8 +267,8 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
}
override public func dismiss(completion: (() -> Void)? = nil) {
if !self.dismissed {
self.dismissed = true
if !self.isDismissed {
self.isDismissed = true
} else {
return
}

View File

@ -988,6 +988,8 @@ public final class StickerPackScreenImpl: ViewController {
return self.displayNode as! StickerPackScreenNode
}
public var dismissed: (() -> Void)?
private let _ready = Promise<Bool>()
override public var ready: Promise<Bool> {
return self._ready
@ -1020,6 +1022,7 @@ public final class StickerPackScreenImpl: ViewController {
strongSelf.updateModalStyleOverlayTransitionFactor(value, transition: transition)
}
}, dismissed: { [weak self] in
self?.dismissed?()
self?.dismiss()
}, presentInGlobalOverlay: { [weak self] c, a in
self?.presentInGlobalOverlay(c, with: a)
@ -1060,10 +1063,11 @@ public enum StickerPackScreenPerformedAction {
case remove(positionInList: Int)
}
public func StickerPackScreen(context: AccountContext, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil) -> ViewController {
public func StickerPackScreen(context: AccountContext, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController {
//return StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker)
let controller = StickerPackPreviewController(context: context, stickerPack: mainStickerPack, mode: mode, parentNavigationController: parentNavigationController, actionPerformed: actionPerformed)
controller.dismissed = dismissed
controller.sendSticker = sendSticker
return controller
}

View File

@ -1268,7 +1268,7 @@ public final class VoiceChatController: ViewController {
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
} else {
openTitle = strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Info")
openIcon = UIImage(bundleImageName: "Chat/Context Menu/User")
}
items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in
return generateTintedImage(image: openIcon, color: theme.actionSheet.primaryTextColor)
@ -2236,7 +2236,7 @@ public final class VoiceChatController: ViewController {
return formatSendTitle(presentationData.strings.VoiceChat_InviteLink_InviteListeners(Int32(count)))
})]
}
let shareController = ShareController(context: strongSelf.context, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forcedTheme: strongSelf.darkTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink)
let shareController = ShareController(context: strongSelf.context, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forceTheme: strongSelf.darkTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink)
shareController.completed = { [weak self] peerIds in
if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in

View File

@ -179,6 +179,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
private var peerPresenceManager: PeerPresenceStatusManager?
private var layoutParams: (VoiceChatParticipantItem, ListViewItemLayoutParams, Bool, Bool)?
private var isExtracted = false
private var wavesColor: UIColor?
private var videoNode: GroupVideoNode?
@ -279,6 +280,8 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
return
}
strongSelf.isExtracted = isExtracted
if isExtracted {
strongSelf.extractedBackgroundImageNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: item.presentationData.theme.list.itemBlocksBackgroundColor)
}
@ -521,7 +524,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
strongSelf.extractedRect = extractedRect
strongSelf.nonExtractedRect = nonExtractedRect
if strongSelf.contextSourceNode.isExtractedToContextPreview {
if strongSelf.isExtracted {
strongSelf.extractedBackgroundImageNode.frame = extractedRect
} else {
strongSelf.extractedBackgroundImageNode.frame = nonExtractedRect

View File

@ -763,6 +763,7 @@ final class AuthorizedApplicationContext {
self.rootController.setForceInCallStatusBar((self.context.sharedContext as! SharedAccountContextImpl).currentCallStatusBarNode)
if let groupCallController = self.context.sharedContext.currentGroupCallController as? VoiceChatController {
if let overlayController = groupCallController.currentOverlayController {
groupCallController.parentNavigationController = self.rootController
self.rootController.presentOverlay(controller: overlayController, inGlobal: true, blockInteraction: false)
}
}

View File

@ -2423,7 +2423,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
var items: [ContextMenuItem] = [
.action(ContextMenuActionItem(text: isChannel ? strongSelf.presentationData.strings.Conversation_ContextMenuOpenChannelProfile : strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/User"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.openPeer(peerId: peer.id, navigation: .info, fromMessage: nil)
@ -7266,19 +7266,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition, listViewTransaction: { updateSizeAndInsets, additionalScrollDistance, scrollToTop, completion in
self.chatDisplayNode.historyNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, additionalScrollDistance: additionalScrollDistance, scrollToTop: scrollToTop, completion: completion)
})
}
override public func updateToInterfaceOrientation(_ orientation: UIInterfaceOrientation) {
guard let layout = self.validLayout, case .compact = layout.metrics.widthClass else {
return
}
let hasOverlayNodes = self.context.sharedContext.mediaManager.overlayMediaManager.controller?.hasNodes ?? false
if self.validLayout != nil && orientation.isLandscape && !hasOverlayNodes && self.traceVisibility() && isTopmostChatController(self) {
var completed = false
self.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in
if !completed, let itemNode = itemNode as? ChatMessageItemView, let message = itemNode.item?.message, let (_, soundEnabled, _, _, _) = itemNode.playMediaWithSound(), soundEnabled {
let _ = self.controllerInteraction?.openMessage(message, .landscape)
completed = true
if case .compact = layout.metrics.widthClass {
let hasOverlayNodes = self.context.sharedContext.mediaManager.overlayMediaManager.controller?.hasNodes ?? false
if self.validLayout != nil && layout.size.width > layout.size.height && !hasOverlayNodes && self.traceVisibility() && isTopmostChatController(self) {
var completed = false
self.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in
if !completed, let itemNode = itemNode as? ChatMessageItemView, let message = itemNode.item?.message, let (_, soundEnabled, _, _, _) = itemNode.playMediaWithSound(), soundEnabled {
let _ = self.controllerInteraction?.openMessage(message, .landscape)
completed = true
}
}
}
}