Added tooltip when tapping on forwarded messages from private channels

Various UI fixes
This commit is contained in:
Ilya Laktyushin 2019-04-18 19:45:42 +04:00
parent 2c17ccdd7d
commit fe3d243272
22 changed files with 843 additions and 824 deletions

View File

@ -71,7 +71,7 @@ final class ChatBackgroundNode: ASDisplayNode {
private var backgroundImageForWallpaper: (TelegramWallpaper, Bool, UIImage)? private var backgroundImageForWallpaper: (TelegramWallpaper, Bool, UIImage)?
private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)? private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)?
func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: MediaBox) -> UIImage? { func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: MediaBox, composed: Bool = false) -> UIImage? {
var backgroundImage: UIImage? var backgroundImage: UIImage?
if wallpaper == backgroundImageForWallpaper?.0, (wallpaper.settings?.blur ?? false) == backgroundImageForWallpaper?.1 { if wallpaper == backgroundImageForWallpaper?.0, (wallpaper.settings?.blur ?? false) == backgroundImageForWallpaper?.1 {
backgroundImage = backgroundImageForWallpaper?.2 backgroundImage = backgroundImageForWallpaper?.2
@ -88,7 +88,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: Media
}) })
case let .image(representations, settings): case let .image(representations, settings):
if let largest = largestImageRepresentation(representations) { if let largest = largestImageRepresentation(representations) {
if settings.blur { if settings.blur && composed {
var image: UIImage? var image: UIImage?
let _ = mediaBox.cachedResourceRepresentation(largest.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in let _ = mediaBox.cachedResourceRepresentation(largest.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
if data.complete { if data.complete {
@ -111,7 +111,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: Media
}) })
backgroundImage = image backgroundImage = image
} else { } else {
if file.settings.blur { if file.settings.blur && composed {
var image: UIImage? var image: UIImage?
let _ = mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in let _ = mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
if data.complete { if data.complete {

View File

@ -830,7 +830,6 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie
}) })
#endif #endif
if let lockViewFrame = self.titleView.lockViewFrame, !self.didShowPasscodeLockTooltipController { if let lockViewFrame = self.titleView.lockViewFrame, !self.didShowPasscodeLockTooltipController {
self.passcodeLockTooltipDisposable.set(combineLatest(queue: .mainQueue(), ApplicationSpecificNotice.getPasscodeLockTips(accountManager: self.context.sharedContext.accountManager), self.context.sharedContext.accountManager.accessChallengeData() |> take(1)).start(next: { [weak self] tooltipValue, passcodeView in self.passcodeLockTooltipDisposable.set(combineLatest(queue: .mainQueue(), ApplicationSpecificNotice.getPasscodeLockTips(accountManager: self.context.sharedContext.accountManager), self.context.sharedContext.accountManager.accessChallengeData() |> take(1)).start(next: { [weak self] tooltipValue, passcodeView in
if let strongSelf = self { if let strongSelf = self {
@ -1069,16 +1068,6 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie
return nil return nil
} }
var isEditing = false
self.chatListDisplayNode.chatListNode.updateState { state in
isEditing = state.editing
return state
}
if isEditing {
return nil
}
let listLocation = self.view.convert(location, to: self.chatListDisplayNode.chatListNode.view) let listLocation = self.view.convert(location, to: self.chatListDisplayNode.chatListNode.view)
var selectedNode: ChatListItemNode? var selectedNode: ChatListItemNode?

View File

@ -837,9 +837,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} }
if !mentionBadgeLayout.width.isZero { if !mentionBadgeLayout.width.isZero {
if !badgeSize.isZero { if !badgeSize.isZero {
badgeSize += badgeLayout.width + 4.0 badgeSize += mentionBadgeLayout.width + 4.0
} else { } else {
badgeSize += badgeLayout.width + 5.0 badgeSize += mentionBadgeLayout.width + 5.0
} }
} }
if let currentPinnedIconImage = currentPinnedIconImage { if let currentPinnedIconImage = currentPinnedIconImage {

View File

@ -159,14 +159,15 @@ final class ChatListSearchRecentPeersNode: ASDisplayNode {
let peersDisposable = DisposableSet() let peersDisposable = DisposableSet()
let recent: Signal<([Peer], [PeerId: UnreadSearchBadge], [PeerId : PeerPresence]), NoError> = recentPeers(account: account) let recent: Signal<([Peer], [PeerId: UnreadSearchBadge], [PeerId : PeerPresence]), NoError> = recentPeers(account: account)
|> filter { value -> Bool in |> filter { value -> Bool in
switch value { switch value {
case .disabled: case .disabled:
return false return false
default: default:
return true return true
} }
} |> mapToSignal { recent in }
|> mapToSignal { recent in
switch recent { switch recent {
case .disabled: case .disabled:
return .single(([], [:], [:])) return .single(([], [:], [:]))

View File

@ -317,10 +317,12 @@ private class ChatListStatusChecksNode: ChatListStatusContentNode {
default: default:
break break
} }
var animating = false
if let previousState = self.state, case .delivered = previousState, case .read = state, animated { if let previousState = self.state, case .delivered = previousState, case .read = state, animated {
animating = true
self.animateProgress(from: 1.0, to: 2.0) self.animateProgress(from: 1.0, to: 2.0)
} }
if !animated { if !animating {
if case .delivered = state { if case .delivered = state {
self.effectiveProgress = 1.0 self.effectiveProgress = 1.0
} else if case .read = state { } else if case .read = state {

View File

@ -5,8 +5,6 @@ final class ChatListTitleLockView: UIView {
private let topView: UIImageView private let topView: UIImageView
private let bottomView: UIImageView private let bottomView: UIImageView
private var isLocked: Bool = false
override init(frame: CGRect) { override init(frame: CGRect) {
self.topView = UIImageView() self.topView = UIImageView()
self.bottomView = UIImageView() self.bottomView = UIImageView()
@ -21,58 +19,15 @@ final class ChatListTitleLockView: UIView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
func setIsLocked( _ isLocked: Bool, theme: PresentationTheme, animated: Bool) { func updateTheme(_ theme: PresentationTheme) {
self.isLocked = isLocked self.topView.image = PresentationResourcesChatList.lockTopUnlockedImage(theme)
if animated { self.bottomView.image = PresentationResourcesChatList.lockBottomUnlockedImage(theme)
let topViewCopy = UIImageView(image: self.topView.image) self.layoutItems()
topViewCopy.frame = self.topView.frame
self.addSubview(topViewCopy)
let bottomViewCopy = UIImageView(image: self.bottomView.image)
bottomViewCopy.frame = self.bottomView.frame
self.addSubview(bottomViewCopy)
self.topView.image = self.isLocked ? PresentationResourcesChatList.lockTopLockedImage(theme) : PresentationResourcesChatList.lockTopUnlockedImage(theme)
self.bottomView.image = self.isLocked ? PresentationResourcesChatList.lockBottomLockedImage(theme) : PresentationResourcesChatList.lockBottomUnlockedImage(theme)
self.topView.alpha = 0.5
self.bottomView.alpha = 0.5
let block: () -> Void = {
self.layoutItems()
topViewCopy.frame = self.topView.frame
bottomViewCopy.frame = self.bottomView.frame
}
UIView.animate(withDuration: 0.1, animations: {
topViewCopy.alpha = 0.0
bottomViewCopy.alpha = 0.0
self.topView.alpha = 1.0
self.bottomView.alpha = 1.0
})
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.39, initialSpringVelocity: 0.0, options: [], animations: {
block()
}, completion: { _ in
topViewCopy.removeFromSuperview()
bottomViewCopy.removeFromSuperview()
})
} else {
self.topView.image = self.isLocked ? PresentationResourcesChatList.lockTopLockedImage(theme) : PresentationResourcesChatList.lockTopUnlockedImage(theme)
self.bottomView.image = self.isLocked ? PresentationResourcesChatList.lockBottomLockedImage(theme) : PresentationResourcesChatList.lockBottomUnlockedImage(theme)
self.layoutItems()
}
} }
private func layoutItems() { private func layoutItems() {
if self.isLocked { self.topView.frame = CGRect(x: 6.0, y: 0.0, width: 7.0, height: 6.0)
self.topView.frame = CGRect(x: floorToScreenPixels((10.0 - 7.0) / 2.0), y: 0.0, width: 7.0, height: 6.0) self.bottomView.frame = CGRect(x: 0.0, y: 6.0, width: 10.0, height: 8.0)
self.bottomView.frame = CGRect(x: 0.0, y: 6.0, width: 10.0, height: 7.0)
} else {
self.topView.frame = CGRect(x: 6.0, y: 0.0, width: 7.0, height: 6.0)
self.bottomView.frame = CGRect(x: 0.0, y: 6.0, width: 10.0, height: 7.0)
}
} }
override func layoutSubviews() { override func layoutSubviews() {

View File

@ -39,11 +39,10 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl
self.buttonView.isHidden = !self.title.isPasscodeSet self.buttonView.isHidden = !self.title.isPasscodeSet
if self.title.isPasscodeSet && !self.title.activity { if self.title.isPasscodeSet && !self.title.activity {
self.lockView.isHidden = false self.lockView.isHidden = false
self.lockView.setIsLocked(self.title.isManuallyLocked, theme: self.theme, animated: !self.bounds.size.width.isZero)
} else { } else {
self.lockView.isHidden = true self.lockView.isHidden = true
self.lockView.setIsLocked(false, theme: self.theme, animated: false)
} }
self.lockView.updateTheme(self.theme)
self.setNeedsLayout() self.setNeedsLayout()
} }
@ -60,11 +59,7 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl
didSet { didSet {
self.titleNode.attributedText = NSAttributedString(string: self.title.text, font: Font.bold(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.title.text, font: Font.bold(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
if self.isPasscodeSet { self.lockView.updateTheme(self.theme)
self.lockView.setIsLocked(self.isManuallyLocked, theme: self.theme, animated: false)
} else {
self.lockView.setIsLocked(false, theme: self.theme, animated: false)
}
self.activityIndicator.type = .custom(self.theme.rootController.navigationBar.primaryTextColor, 22.0, 1.5, false) self.activityIndicator.type = .custom(self.theme.rootController.navigationBar.primaryTextColor, 22.0, 1.5, false)
self.proxyNode.theme = self.theme self.proxyNode.theme = self.theme
@ -202,7 +197,7 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl
let buttonX = max(0.0, titleFrame.minX - 10.0) let buttonX = max(0.0, titleFrame.minX - 10.0)
self.buttonView.frame = CGRect(origin: CGPoint(x: buttonX, y: 0.0), size: CGSize(width: min(titleFrame.maxX + 28.0, size.width) - buttonX, height: size.height)) self.buttonView.frame = CGRect(origin: CGPoint(x: buttonX, y: 0.0), size: CGSize(width: min(titleFrame.maxX + 28.0, size.width) - buttonX, height: size.height))
self.lockView.frame = CGRect(x: titleFrame.maxX + 6.0, y: titleFrame.minY + 3.0, width: 2.0, height: 2.0) self.lockView.frame = CGRect(x: titleFrame.maxX + 6.0, y: titleFrame.minY + 2.0, width: 2.0, height: 2.0)
self.activityIndicator.frame = CGRect(origin: CGPoint(x: titleFrame.minX - indicatorSize.width - 4.0, y: titleFrame.minY - 1.0), size: indicatorSize) self.activityIndicator.frame = CGRect(origin: CGPoint(x: titleFrame.minX - indicatorSize.width - 4.0, y: titleFrame.minY - 1.0), size: indicatorSize)
} }

View File

@ -429,6 +429,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty {
item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame)
} else { } else {
if let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, self, avatarNode.frame)
return
}
}
item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message) item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message)
} }
} }

View File

@ -1654,6 +1654,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty {
item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame)
} else { } else {
if let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, self, avatarNode.frame)
return
}
}
item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message) item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message)
} }
} }
@ -1696,6 +1703,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) { if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) {
if let item = self.item, let forwardInfo = item.message.forwardInfo { if let item = self.item, let forwardInfo = item.message.forwardInfo {
if let sourceMessageId = forwardInfo.sourceMessageId { if let sourceMessageId = forwardInfo.sourceMessageId {
if let channel = forwardInfo.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, forwardInfoNode, nil)
return
}
}
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId) item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id { } else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
item.controllerInteraction.openPeer(id, .info, nil) item.controllerInteraction.openPeer(id, .info, nil)

View File

@ -2,6 +2,7 @@ import Foundation
import AsyncDisplayKit import AsyncDisplayKit
import Display import Display
import Postbox import Postbox
import TelegramCore
private let prefixFont = Font.regular(13.0) private let prefixFont = Font.regular(13.0)
private let peerFont = Font.medium(13.0) private let peerFont = Font.medium(13.0)
@ -48,9 +49,21 @@ class ChatMessageForwardInfoNode: ASDisplayNode {
completeSourceString = strings.Message_ForwardedMessageShort(peerString) completeSourceString = strings.Message_ForwardedMessageShort(peerString)
} }
var highlight = true
if let peer = peer {
if let channel = peer as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
highlight = false
}
}
} else {
highlight = false
}
let completeString: NSString = completeSourceString.0 as NSString let completeString: NSString = completeSourceString.0 as NSString
let string = NSMutableAttributedString(string: completeString as String, attributes: [NSAttributedStringKey.foregroundColor: titleColor, NSAttributedStringKey.font: prefixFont]) let string = NSMutableAttributedString(string: completeString as String, attributes: [NSAttributedStringKey.foregroundColor: titleColor, NSAttributedStringKey.font: prefixFont])
if peer != nil, let range = completeSourceString.1.first?.1 { if highlight, let range = completeSourceString.1.first?.1 {
string.addAttributes([NSAttributedStringKey.font: peerFont], range: range) string.addAttributes([NSAttributedStringKey.font: peerFont], range: range)
} }
let (textLayout, textApply) = textNodeLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (textLayout, textApply) = textNodeLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View File

@ -534,6 +534,13 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty {
item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame)
} else { } else {
if let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, forwardInfoNode, nil)
return
}
}
item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message) item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message)
} }
} }
@ -554,6 +561,13 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) { if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) {
if let item = self.item, let forwardInfo = item.message.forwardInfo { if let item = self.item, let forwardInfo = item.message.forwardInfo {
if let sourceMessageId = forwardInfo.sourceMessageId { if let sourceMessageId = forwardInfo.sourceMessageId {
if let channel = forwardInfo.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, forwardInfoNode, nil)
return
}
}
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId) item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id { } else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
item.controllerInteraction.openPeer(id, .chat(textInputState: nil, messageId: nil), nil) item.controllerInteraction.openPeer(id, .chat(textInputState: nil, messageId: nil), nil)

View File

@ -563,6 +563,13 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty { if item.effectiveAuthorId?.namespace == Namespaces.Peer.Empty {
item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame) item.controllerInteraction.displayMessageTooltip(item.content.firstMessage.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, avatarNode.frame)
} else { } else {
if let channel = item.content.firstMessage.forwardInfo?.author as? TelegramChannel, channel.username == nil {
if case .member = channel.participationStatus {
} else {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, self, avatarNode.frame)
return
}
}
item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message) item.controllerInteraction.openPeer(item.effectiveAuthorId ?? author.id, navigate, item.message)
} }
} }

View File

@ -121,6 +121,8 @@ final class HorizontalPeerItemNode: ListViewItemNode {
let badgeTextLayout = TextNode.asyncLayout(self.badgeTextNode) let badgeTextLayout = TextNode.asyncLayout(self.badgeTextNode)
let onlineLayout = self.onlineNode.asyncLayout() let onlineLayout = self.onlineNode.asyncLayout()
let currentItem = self.item
return { [weak self] item, params in return { [weak self] item, params in
let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: 92.0, height: item.customWidth ?? 80.0), insets: UIEdgeInsets()) let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: 92.0, height: item.customWidth ?? 80.0), insets: UIEdgeInsets())
@ -177,6 +179,10 @@ final class HorizontalPeerItemNode: ListViewItemNode {
} }
let (onlineLayout, onlineApply) = onlineLayout(online) let (onlineLayout, onlineApply) = onlineLayout(online)
var animateContent = false
if let currentItem = currentItem, currentItem.peer.id == item.peer.id {
animateContent = true
}
return (itemLayout, { animated in return (itemLayout, { animated in
if let strongSelf = self { if let strongSelf = self {
@ -207,7 +213,7 @@ final class HorizontalPeerItemNode: ListViewItemNode {
strongSelf.onlineNode.frame = CGRect(x: itemLayout.size.width - onlineLayout.width - 18.0, y: itemLayout.size.height - onlineLayout.height - 18.0, width: onlineLayout.width, height: onlineLayout.height) strongSelf.onlineNode.frame = CGRect(x: itemLayout.size.width - onlineLayout.width - 18.0, y: itemLayout.size.height - onlineLayout.height - 18.0, width: onlineLayout.width, height: onlineLayout.height)
let _ = badgeApply() let _ = badgeApply()
let _ = onlineApply(true) let _ = onlineApply(animateContent)
} }
}) })
} }

View File

@ -43,13 +43,13 @@ private func chatMessageGalleryControllerData(context: AccountContext, message:
} else if let image = media as? TelegramMediaImage { } else if let image = media as? TelegramMediaImage {
galleryMedia = image galleryMedia = image
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { } else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
if let file = content.file { if let file = content.file {
galleryMedia = file galleryMedia = file
} else if let image = content.image { } else if let image = content.image {
if ["photo", "document", "video", "gif"].contains(content.type) { if ["photo", "document", "video", "gif", "telegram_album"].contains(content.type) {
galleryMedia = image galleryMedia = image
}
} }
}
if let instantPage = content.instantPage, let galleryMedia = galleryMedia { if let instantPage = content.instantPage, let galleryMedia = galleryMedia {
switch instantPageType(of: content) { switch instantPageType(of: content) {

View File

@ -4,6 +4,16 @@ import AsyncDisplayKit
import SwiftSignalKit import SwiftSignalKit
import Postbox import Postbox
final public class PasscodeEntryControllerPresentationArguments {
let animated: Bool
let lockIconInitialFrame: () -> CGRect
public init(animated: Bool = true, lockIconInitialFrame: @escaping () -> CGRect) {
self.animated = animated
self.lockIconInitialFrame = lockIconInitialFrame
}
}
final public class PasscodeEntryController: ViewController { final public class PasscodeEntryController: ViewController {
private var controllerNode: PasscodeEntryControllerNode { private var controllerNode: PasscodeEntryControllerNode {
return self.displayNode as! PasscodeEntryControllerNode return self.displayNode as! PasscodeEntryControllerNode
@ -15,18 +25,18 @@ final public class PasscodeEntryController: ViewController {
private let challengeData: PostboxAccessChallengeData private let challengeData: PostboxAccessChallengeData
private let enableBiometrics: Bool private let enableBiometrics: Bool
private let animated: Bool private let arguments: PasscodeEntryControllerPresentationArguments
public var presentationCompleted: (() -> Void)? public var presentationCompleted: (() -> Void)?
private let biometricsDisposable = MetaDisposable() private let biometricsDisposable = MetaDisposable()
public init(context: AccountContext, challengeData: PostboxAccessChallengeData, enableBiometrics: Bool, animated: Bool = false) { public init(context: AccountContext, challengeData: PostboxAccessChallengeData, enableBiometrics: Bool, arguments: PasscodeEntryControllerPresentationArguments) {
self.context = context self.context = context
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.challengeData = challengeData self.challengeData = challengeData
self.enableBiometrics = enableBiometrics self.enableBiometrics = enableBiometrics
self.animated = animated self.arguments = arguments
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
@ -123,7 +133,7 @@ final public class PasscodeEntryController: ViewController {
super.viewDidAppear(animated) super.viewDidAppear(animated)
self.controllerNode.activateInput() self.controllerNode.activateInput()
if self.animated { if self.arguments.animated {
Queue.mainQueue().after(0.5) { Queue.mainQueue().after(0.5) {
serviceSoundManager.playLockSound() serviceSoundManager.playLockSound()
} }

View File

@ -116,7 +116,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
switch self.wallpaper { switch self.wallpaper {
case .image, .file: case .image, .file:
if let image = chatControllerBackgroundImage(wallpaper: self.wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox) { if let image = chatControllerBackgroundImage(wallpaper: self.wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, composed: false) {
self.background = ImageBasedPasscodeBackground(image: image, size: validLayout.size) self.background = ImageBasedPasscodeBackground(image: image, size: validLayout.size)
} else { } else {
self.background = DefaultPasscodeBackground(size: validLayout.size) self.background = DefaultPasscodeBackground(size: validLayout.size)
@ -210,7 +210,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
transition.updateFrame(view: self.effectView, frame: bounds) transition.updateFrame(view: self.effectView, frame: bounds)
let iconSize = CGSize(width: 35.0, height: 37.0) let iconSize = CGSize(width: 35.0, height: 37.0)
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0) + 11.0, y: layout.insets(options: .statusBar).top + 15.0), size: iconSize)) transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0) + 6.0, y: layout.insets(options: .statusBar).top + 15.0), size: iconSize))
let titleSize = self.titleNode.updateLayout(layout: layout, transition: transition) let titleSize = self.titleNode.updateLayout(layout: layout, transition: transition)
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 123.0), size: titleSize)) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 123.0), size: titleSize))

View File

@ -3,8 +3,17 @@ import Display
import AsyncDisplayKit import AsyncDisplayKit
import SwiftSignalKit import SwiftSignalKit
private let titleFont = Font.regular(40.0) private let regularTitleFont = Font.regular(36.0)
private let subtitleFont: UIFont = { private let regularSubtitleFont: UIFont = {
if #available(iOS 8.2, *) {
return UIFont.systemFont(ofSize: 10.0, weight: UIFont.Weight.bold)
} else {
return CTFontCreateWithName("HelveticaNeue-Bold" as CFString, 10.0, nil)
}
}()
private let largeTitleFont = Font.regular(40.0)
private let largeSubtitleFont: UIFont = {
if #available(iOS 8.2, *) { if #available(iOS 8.2, *) {
return UIFont.systemFont(ofSize: 12.0, weight: UIFont.Weight.bold) return UIFont.systemFont(ofSize: 12.0, weight: UIFont.Weight.bold)
} else { } else {
@ -35,13 +44,32 @@ private func generateButtonImage(background: PasscodeBackground, frame: CGRect,
context.setAlpha(1.0) context.setAlpha(1.0)
context.textMatrix = .identity context.textMatrix = .identity
var offset: CGFloat = -11.0 let titleFont: UIFont
if subtitle.isEmpty { let subtitleFont: UIFont
offset -= 7.0 let titleOffset: CGFloat
let subtitleOffset: CGFloat
if size.width > 80.0 {
titleFont = largeTitleFont
subtitleFont = largeSubtitleFont
if subtitle.isEmpty {
titleOffset = -18.0
} else {
titleOffset = -11.0
}
subtitleOffset = -54.0
} else {
titleFont = regularTitleFont
subtitleFont = regularSubtitleFont
if subtitle.isEmpty {
titleOffset = -17.0
} else {
titleOffset = -10.0
}
subtitleOffset = -48.0
} }
let titlePath = CGMutablePath() let titlePath = CGMutablePath()
titlePath.addRect(bounds.offsetBy(dx: 0.0, dy: offset)) titlePath.addRect(bounds.offsetBy(dx: 0.0, dy: titleOffset))
let titleString = NSAttributedString(string: title, font: titleFont, textColor: .white, paragraphAlignment: .center) let titleString = NSAttributedString(string: title, font: titleFont, textColor: .white, paragraphAlignment: .center)
let titleFramesetter = CTFramesetterCreateWithAttributedString(titleString as CFAttributedString) let titleFramesetter = CTFramesetterCreateWithAttributedString(titleString as CFAttributedString)
let titleFrame = CTFramesetterCreateFrame(titleFramesetter, CFRangeMake(0, titleString.length), titlePath, nil) let titleFrame = CTFramesetterCreateFrame(titleFramesetter, CFRangeMake(0, titleString.length), titlePath, nil)
@ -49,7 +77,7 @@ private func generateButtonImage(background: PasscodeBackground, frame: CGRect,
if !subtitle.isEmpty { if !subtitle.isEmpty {
let subtitlePath = CGMutablePath() let subtitlePath = CGMutablePath()
subtitlePath.addRect(bounds.offsetBy(dx: 0.0, dy: -54.0)) subtitlePath.addRect(bounds.offsetBy(dx: 0.0, dy: subtitleOffset))
let subtitleString = NSAttributedString(string: subtitle, font: subtitleFont, textColor: .white, paragraphAlignment: .center) let subtitleString = NSAttributedString(string: subtitle, font: subtitleFont, textColor: .white, paragraphAlignment: .center)
let subtitleFramesetter = CTFramesetterCreateWithAttributedString(subtitleString as CFAttributedString) let subtitleFramesetter = CTFramesetterCreateWithAttributedString(subtitleString as CFAttributedString)
let subtitleFrame = CTFramesetterCreateFrame(subtitleFramesetter, CFRangeMake(0, subtitleString.length), subtitlePath, nil) let subtitleFrame = CTFramesetterCreateFrame(subtitleFramesetter, CFRangeMake(0, subtitleString.length), subtitlePath, nil)
@ -205,75 +233,85 @@ final class PasscodeEntryKeyboardNode: ASDisplayNode {
let size: CGSize let size: CGSize
let offset: CGFloat let offset: CGFloat
let height = Int(max(layout.size.width, layout.size.height)) let metrics = DeviceMetrics.forScreenSize(layout.size)
switch height { if let metrics = metrics {
case 1024, 1194, 1366: switch metrics {
buttonSize = 81.0 case .iPhone4:
horizontalSecond = 106.0 buttonSize = 75.0
horizontalThird = 212.0 horizontalSecond = 95.0
verticalSecond = 100.0 + UIScreenPixel horizontalThird = 190.0
verticalThird = 202.0 verticalSecond = 88.0
verticalFourth = 303.0 verticalThird = 176.0
size = CGSize(width: 293.0, height: 384.0) verticalFourth = 264.0
offset = 0.0 size = CGSize(width: 265.0, height: 339.0)
case 896: offset = 0.0
buttonSize = 85.0 case .iPhone5:
horizontalSecond = 115.0 buttonSize = 75.0
horizontalThird = 230.0 horizontalSecond = 95.0
verticalSecond = 100.0 horizontalThird = 190.0
verticalThird = 200.0 verticalSecond = 88.0
verticalFourth = 300.0 verticalThird = 176.0
size = CGSize(width: 315.0, height: 385.0) verticalFourth = 264.0
offset = 240.0 size = CGSize(width: 265.0, height: 339.0)
case 812: offset = 0.0
buttonSize = 85.0 case .iPhone6:
horizontalSecond = 115.0 buttonSize = 75.0
horizontalThird = 230.0 horizontalSecond = 103.0
verticalSecond = 100.0 horizontalThird = 206.0
verticalThird = 200.0 verticalSecond = 90.0
verticalFourth = 300.0 verticalThird = 180.0
size = CGSize(width: 315.0, height: 385.0) verticalFourth = 270.0
offset = 240.0 size = CGSize(width: 281.0, height: 345.0)
case 736: offset = 0.0
buttonSize = 75.0 case .iPhone6Plus:
horizontalSecond = 103.5 buttonSize = 75.0
horizontalThird = 206.0 horizontalSecond = 103.0
verticalSecond = 90.0 horizontalThird = 206.0
verticalThird = 180.0 verticalSecond = 90.0
verticalFourth = 270.0 verticalThird = 180.0
size = CGSize(width: 281.0, height: 345.0) verticalFourth = 270.0
offset = 0.0 size = CGSize(width: 281.0, height: 345.0)
case 667: offset = 0.0
buttonSize = 75.0 case .iPhoneX:
horizontalSecond = 103.5 buttonSize = 75.0
horizontalThird = 206.0 horizontalSecond = 103.0
verticalSecond = 90.0 horizontalThird = 206.0
verticalThird = 180.0 verticalSecond = 91.0
verticalFourth = 270.0 verticalThird = 182.0
size = CGSize(width: 281.0, height: 345.0) verticalFourth = 273.0
offset = 0.0 size = CGSize(width: 281.0, height: 345.0)
case 568: offset = 294.0
buttonSize = 75.0 case .iPhoneXSMax:
horizontalSecond = 95.0 buttonSize = 85.0
horizontalThird = 190.0 horizontalSecond = 115.0
verticalSecond = 88.0 horizontalThird = 230.0
verticalThird = 176.0 verticalSecond = 100.0
verticalFourth = 264.0 verticalThird = 200.0
size = CGSize(width: 265.0, height: 339.0) verticalFourth = 300.0
offset = 0.0 size = CGSize(width: 315.0, height: 385.0)
default: offset = 240.0
buttonSize = 75.0 case .iPad, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen:
horizontalSecond = 95.0 buttonSize = 81.0
horizontalThird = 190.0 horizontalSecond = 106.0
verticalSecond = 88.0 horizontalThird = 212.0
verticalThird = 176.0 verticalSecond = 101.0
verticalFourth = 264.0 verticalThird = 202.0
size = CGSize(width: 265.0, height: 339.0) verticalFourth = 303.0
offset = 0.0 size = CGSize(width: 293.0, height: 384.0)
offset = 0.0
}
} else {
buttonSize = 75.0
horizontalSecond = 95.0
horizontalThird = 190.0
verticalSecond = 88.0
verticalThird = 176.0
verticalFourth = 264.0
size = CGSize(width: 265.0, height: 339.0)
offset = 0.0
} }
let origin = CGPoint(x: floor((layout.size.width - size.width) / 2.0), y: offset) let origin = CGPoint(x: floor((layout.size.width - size.width) / 2.0), y: offset)
if let subnodes = self.subnodes { if let subnodes = self.subnodes {
for i in 0 ..< subnodes.count { for i in 0 ..< subnodes.count {
var origin = origin var origin = origin

View File

@ -209,11 +209,6 @@ private func passcodeOptionsControllerEntries(presentationData: PresentationData
entries.append(.touchId(presentationData.theme, presentationData.strings.PasscodeSettings_UnlockWithFaceId, passcodeOptionsData.presentationSettings.enableBiometrics)) entries.append(.touchId(presentationData.theme, presentationData.strings.PasscodeSettings_UnlockWithFaceId, passcodeOptionsData.presentationSettings.enableBiometrics))
} }
} }
var simplePasscode = false
if case .numericalPassword = passcodeOptionsData.accessChallenge {
simplePasscode = true
}
entries.append(.simplePasscode(presentationData.theme, presentationData.strings.PasscodeSettings_SimplePasscode, simplePasscode))
} }
return entries return entries

View File

@ -54,8 +54,6 @@ enum PresentationResourceKey: Int32 {
case itemListCloseIconImage case itemListCloseIconImage
case chatListLockTopLockedImage
case chatListLockBottomLockedImage
case chatListLockTopUnlockedImage case chatListLockTopUnlockedImage
case chatListLockBottomUnlockedImage case chatListLockBottomUnlockedImage
case chatListPending case chatListPending

View File

@ -99,30 +99,6 @@ struct PresentationResourcesChatList {
}) })
} }
static func lockTopLockedImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatListLockTopLockedImage.rawValue, { theme in
return generateImage(CGSize(width: 7.0, height: 6.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.rootController.navigationBar.accentTextColor.cgColor)
context.setStrokeColor(theme.rootController.navigationBar.accentTextColor.cgColor)
context.setLineWidth(1.5)
context.addPath(UIBezierPath(roundedRect: CGRect(x: 0.75, y: 0.75, width: 5.5, height: 12.0), cornerRadius: 2.5).cgPath)
context.strokePath()
})
})
}
static func lockBottomLockedImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatListLockBottomLockedImage.rawValue, { theme in
return generateImage(CGSize(width: 10.0, height: 7.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.rootController.navigationBar.accentTextColor.cgColor)
context.addPath(UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 7.0), cornerRadius: 1.33).cgPath)
context.fillPath()
})
})
}
static func lockTopUnlockedImage(_ theme: PresentationTheme) -> UIImage? { static func lockTopUnlockedImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatListLockTopUnlockedImage.rawValue, { theme in return theme.image(PresentationResourceKey.chatListLockTopUnlockedImage.rawValue, { theme in
return generateImage(CGSize(width: 7.0, height: 6.0), rotatedContext: { size, context in return generateImage(CGSize(width: 7.0, height: 6.0), rotatedContext: { size, context in
@ -141,17 +117,15 @@ struct PresentationResourcesChatList {
static func lockBottomUnlockedImage(_ theme: PresentationTheme) -> UIImage? { static func lockBottomUnlockedImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatListLockBottomUnlockedImage.rawValue, { theme in return theme.image(PresentationResourceKey.chatListLockBottomUnlockedImage.rawValue, { theme in
return generateImage(CGSize(width: 10.0, height: 7.0), rotatedContext: { size, context in return generateImage(CGSize(width: 10.0, height: 8.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size)) context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.rootController.navigationBar.primaryTextColor.cgColor) context.setFillColor(theme.rootController.navigationBar.primaryTextColor.cgColor)
context.addPath(UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 7.0), cornerRadius: 1.33).cgPath) context.addPath(UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 8.0), cornerRadius: 1.5).cgPath)
context.fillPath() context.fillPath()
}) })
}) })
} }
static func recentStatusOnlineIcon(_ theme: PresentationTheme, state: RecentStatusOnlineIconState) -> UIImage? { static func recentStatusOnlineIcon(_ theme: PresentationTheme, state: RecentStatusOnlineIconState) -> UIImage? {
let key: PresentationResourceKey let key: PresentationResourceKey
switch state { switch state {

File diff suppressed because it is too large Load Diff