mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
cb6377bfac
@ -5114,6 +5114,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Theme.Colors.ColorWallpaperWarning" = "Are you sure you want to change your chat wallpaper to a color?";
|
||||
"Theme.Colors.ColorWallpaperWarningProceed" = "Proceed";
|
||||
|
||||
"ChatSettings.IntentsSettings" = "Share Sheet";
|
||||
"IntentsSettings.Title" = "Share Sheet";
|
||||
"IntentsSettings.MainAccount" = "Main Account";
|
||||
"IntentsSettings.MainAccountInfo" = "Choose an account for Siri and share suggestions.";
|
||||
@ -5146,3 +5147,9 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Map.SendThisPlace" = "Send This Place";
|
||||
"Map.SetThisPlace" = "Set This Place";
|
||||
"Map.AddressOnMap" = "Address On Map";
|
||||
"Map.PlacesNearby" = "Places Nearby";
|
||||
"Map.Home" = "Home";
|
||||
"Map.Work" = "Work";
|
||||
"Map.HomeAndWorkTitle" = "Home & Work Addresses";
|
||||
"Map.HomeAndWorkInfo" = "Telegram uses the Home and Work addresses from your Contact Card.\n\nKeep your Contact Card up to date for quick access to sending Home and Work addresses.";
|
||||
|
@ -135,9 +135,13 @@ final class PeerView: UIView {
|
||||
title.append("\n")
|
||||
title.append(lastName)
|
||||
}
|
||||
|
||||
let systemFontSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||
let fontSize = floor(systemFontSize * 11.0 / 17.0)
|
||||
|
||||
self.titleLabel.text = title
|
||||
self.titleLabel.textColor = primaryColor
|
||||
self.titleLabel.font = UIFont.systemFont(ofSize: 11.0)
|
||||
self.titleLabel.font = UIFont.systemFont(ofSize: fontSize)
|
||||
self.titleLabel.lineBreakMode = .byTruncatingTail
|
||||
self.titleLabel.numberOfLines = 2
|
||||
self.titleLabel.textAlignment = .center
|
||||
|
@ -54,10 +54,12 @@ class TodayViewController: UIViewController, NCWidgetProviding {
|
||||
presentationData = WidgetPresentationData(applicationLockedString: "Unlock the app to use widget")
|
||||
}
|
||||
|
||||
let fontSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
|
||||
let appLockedLabel = UILabel()
|
||||
appLockedLabel.textColor = self.primaryColor
|
||||
appLockedLabel.font = UIFont.systemFont(ofSize: 16.0)
|
||||
appLockedLabel.font = UIFont.systemFont(ofSize: fontSize)
|
||||
appLockedLabel.text = presentationData.applicationLockedString
|
||||
appLockedLabel.sizeToFit()
|
||||
self.appLockedLabel = appLockedLabel
|
||||
|
@ -48,7 +48,7 @@ private let avatarFont = avatarPlaceholderFont(size: 15.0)
|
||||
public class ActionSheetPeerItemNode: ActionSheetItemNode {
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
private let defaultFont: UIFont
|
||||
|
||||
private var item: ActionSheetPeerItem?
|
||||
|
||||
@ -62,6 +62,8 @@ public class ActionSheetPeerItemNode: ActionSheetItemNode {
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
self.button.isAccessibilityElement = false
|
||||
|
||||
@ -114,8 +116,10 @@ public class ActionSheetPeerItemNode: ActionSheetItemNode {
|
||||
func setItem(_ item: ActionSheetPeerItem) {
|
||||
self.item = item
|
||||
|
||||
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
let textColor: UIColor = self.theme.primaryTextColor
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: ActionSheetButtonNode.defaultFont, textColor: textColor)
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: defaultFont, textColor: textColor)
|
||||
|
||||
self.avatarNode.setPeer(account: item.account, theme: item.theme, peer: item.peer)
|
||||
|
||||
|
@ -42,11 +42,11 @@ final class BotCheckoutPaymentMethodSheetController: ActionSheetController {
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
@ -137,7 +137,7 @@ public class BotCheckoutPaymentMethodItem: ActionSheetItem {
|
||||
}
|
||||
|
||||
public class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
private let defaultFont: UIFont
|
||||
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
@ -150,6 +150,7 @@ public class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
|
||||
|
||||
public override init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
|
||||
@ -201,7 +202,7 @@ public class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
|
||||
func setItem(_ item: BotCheckoutPaymentMethodItem) {
|
||||
self.item = item
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: BotCheckoutPaymentMethodItemNode.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: self.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.iconNode.image = item.icon
|
||||
if let value = item.value {
|
||||
self.checkNode.isHidden = !value
|
||||
|
@ -16,11 +16,11 @@ final class BotCheckoutPaymentShippingOptionSheetController: ActionSheetControll
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
@ -113,7 +113,7 @@ public class BotCheckoutPaymentShippingOptionItem: ActionSheetItem {
|
||||
}
|
||||
|
||||
public class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
private let defaultFont: UIFont
|
||||
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
@ -126,6 +126,7 @@ public class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
|
||||
|
||||
public override init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
|
||||
@ -178,8 +179,8 @@ public class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
|
||||
func setItem(_ item: BotCheckoutPaymentShippingOptionItem) {
|
||||
self.item = item
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: BotCheckoutPaymentShippingOptionItemNode.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.labelNode.attributedText = NSAttributedString(string: item.label, font: BotCheckoutPaymentShippingOptionItemNode.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: self.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.labelNode.attributedText = NSAttributedString(string: item.label, font: self.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
if let value = item.value {
|
||||
self.checkNode.isHidden = !value
|
||||
} else {
|
||||
|
@ -17,6 +17,8 @@ public enum ChatListSearchItemHeaderType: Int32 {
|
||||
case phoneNumber
|
||||
case exceptions
|
||||
case addToExceptions
|
||||
case mapAddress
|
||||
case nearbyVenues
|
||||
}
|
||||
|
||||
public final class ChatListSearchItemHeader: ListViewItemHeader {
|
||||
@ -30,7 +32,7 @@ public final class ChatListSearchItemHeader: ListViewItemHeader {
|
||||
|
||||
public let height: CGFloat = 28.0
|
||||
|
||||
public init(type: ChatListSearchItemHeaderType, theme: PresentationTheme, strings: PresentationStrings, actionTitle: String?, action: (() -> Void)?) {
|
||||
public init(type: ChatListSearchItemHeaderType, theme: PresentationTheme, strings: PresentationStrings, actionTitle: String? = nil, action: (() -> Void)? = nil) {
|
||||
self.type = type
|
||||
self.id = Int64(self.type.rawValue)
|
||||
self.theme = theme
|
||||
@ -93,6 +95,10 @@ public final class ChatListSearchItemHeaderNode: ListViewItemHeaderNode {
|
||||
self.sectionHeaderNode.title = strings.GroupInfo_Permissions_Exceptions.uppercased()
|
||||
case .addToExceptions:
|
||||
self.sectionHeaderNode.title = strings.Exceptions_AddToExceptions.uppercased()
|
||||
case .mapAddress:
|
||||
self.sectionHeaderNode.title = strings.Map_AddressOnMap.uppercased()
|
||||
case .nearbyVenues:
|
||||
self.sectionHeaderNode.title = strings.Map_PlacesNearby.uppercased()
|
||||
}
|
||||
|
||||
self.sectionHeaderNode.action = actionTitle
|
||||
|
@ -308,7 +308,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
if case .root = groupId, checkProxy {
|
||||
if strongSelf.proxyUnavailableTooltipController == nil && !strongSelf.didShowProxyUnavailableTooltipController && strongSelf.isNodeLoaded && strongSelf.displayNode.view.window != nil {
|
||||
strongSelf.didShowProxyUnavailableTooltipController = true
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.Proxy_TooltipUnavailable), timeout: 60.0, dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.Proxy_TooltipUnavailable), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, timeout: 60.0, dismissByTapOutside: true)
|
||||
strongSelf.proxyUnavailableTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.proxyUnavailableTooltipController === tooltipController {
|
||||
@ -588,7 +588,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
self.chatListDisplayNode.requestOpenRecentPeerOptions = { [weak self] peer in
|
||||
if let strongSelf = self {
|
||||
strongSelf.view.window?.endEditing(true)
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
|
||||
actionSheet.setItemGroups([
|
||||
ActionSheetItemGroup(items: [
|
||||
@ -669,12 +669,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
case let .groupReference(groupReference):
|
||||
let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupReference.groupId, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
||||
chatListController.navigationPresentation = .master
|
||||
let contextController = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupReference.groupId, chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupReference.groupId, chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
strongSelf.presentInGlobalOverlay(contextController)
|
||||
case let .peer(peer):
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peer.peerId), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peer.peerId, source: .chatList, chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peer.peerId, source: .chatList, chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
strongSelf.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
}
|
||||
@ -687,7 +687,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, source: .search(source), chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, source: .search(source), chatListController: strongSelf), reactionItems: [], gesture: gesture)
|
||||
strongSelf.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
|
||||
@ -798,7 +798,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
if hasPasscode {
|
||||
let _ = ApplicationSpecificNotice.setPasscodeLockTips(accountManager: strongSelf.context.sharedContext.accountManager).start()
|
||||
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.DialogList_PasscodeLockHelp), dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.DialogList_PasscodeLockHelp), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceViewAndRect: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
return (strongSelf.titleView, lockViewFrame.offsetBy(dx: 4.0, dy: 14.0))
|
||||
@ -1199,7 +1199,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
self?.donePressed()
|
||||
})
|
||||
} else if case .right = action, !peerIds.isEmpty {
|
||||
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteConfirmation(Int32(peerIds.count)), color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
@ -1385,7 +1385,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
if let user = chatPeer as? TelegramUser, user.botInfo == nil, canRemoveGlobally {
|
||||
strongSelf.maybeAskForPeerChatRemoval(peer: peer, completion: { _ in }, removed: {})
|
||||
} else {
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
var canClear = true
|
||||
var canStop = false
|
||||
@ -1468,7 +1468,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
}
|
||||
|
||||
if canRemoveGlobally {
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
|
||||
@ -1556,7 +1556,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
}
|
||||
|
||||
if canRemoveGlobally {
|
||||
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .delete, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder))
|
||||
|
@ -774,7 +774,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let enableChatListPhotos = item.context.sharedContext.immediateExperimentalUISettings.chatListPhotos
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + 78.0
|
||||
let avatarDiameter = floor(item.presentationData.fontSize.baseDisplaySize * 60.0 / 17.0)
|
||||
let avatarLeftInset = 18.0 + avatarDiameter
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + avatarLeftInset
|
||||
|
||||
enum ContentData {
|
||||
case chat(itemPeer: RenderedPeer, peer: Peer?, hideAuthor: Bool, messageText: String)
|
||||
@ -1337,7 +1340,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateAlpha(node: strongSelf.statusNode, alpha: 1.0)
|
||||
}
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - 78.0 + editingOffset + 10.0 + revealOffset, y: floor((layout.contentSize.height - 60.0) / 2.0)), size: CGSize(width: 60.0, height: 60.0))
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((layout.contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter))
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: avatarFrame)
|
||||
|
||||
let onlineFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - onlineLayout.width - 2.0, y: avatarFrame.maxY - onlineLayout.height - 2.0), size: onlineLayout)
|
||||
@ -1417,7 +1420,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.secretIconNode = iconNode
|
||||
}
|
||||
iconNode.image = currentSecretIconImage
|
||||
transition.updateFrame(node: iconNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x, y: contentRect.origin.y + 4.0), size: currentSecretIconImage.size))
|
||||
transition.updateFrame(node: iconNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x, y: contentRect.origin.y + floor((strongSelf.titleNode.frame.height - currentSecretIconImage.size.height) / 2.0)), size: currentSecretIconImage.size))
|
||||
titleOffset += currentSecretIconImage.size.width + 3.0
|
||||
} else if let secretIconNode = strongSelf.secretIconNode {
|
||||
strongSelf.secretIconNode = nil
|
||||
@ -1616,7 +1619,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
override func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
super.updateRevealOffset(offset: offset, transition: transition)
|
||||
|
||||
if let _ = self.item, let params = self.layoutParams?.5, let countersSize = self.layoutParams?.6 {
|
||||
if let item = self.item, let params = self.layoutParams?.5, let countersSize = self.layoutParams?.6 {
|
||||
let editingOffset: CGFloat
|
||||
if let selectableControlNode = self.selectableControlNode {
|
||||
editingOffset = selectableControlNode.bounds.size.width
|
||||
@ -1635,14 +1638,17 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: reorderControlNode, frame: reorderControlFrame)
|
||||
}
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + 78.0
|
||||
let avatarDiameter = floor(item.presentationData.fontSize.baseDisplaySize * 60.0 / 17.0)
|
||||
let avatarLeftInset = 18.0 + avatarDiameter
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + avatarLeftInset
|
||||
|
||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: params.width - leftInset - params.rightInset - 10.0 - 1.0 - editingOffset, height: self.bounds.size.height - 12.0 - 9.0))
|
||||
|
||||
let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + offset, dy: 0.0)
|
||||
|
||||
var avatarFrame = self.avatarNode.frame
|
||||
avatarFrame.origin.x = leftInset - 78.0 + editingOffset + 10.0 + offset
|
||||
avatarFrame.origin.x = leftInset - avatarLeftInset + editingOffset + 10.0 + offset
|
||||
transition.updateFrame(node: self.avatarNode, frame: avatarFrame)
|
||||
|
||||
var onlineFrame = self.onlineNode.frame
|
||||
|
@ -40,7 +40,9 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
||||
processed = true
|
||||
break inner
|
||||
case let .Audio(isVoice, _, title, performer, _):
|
||||
if isVoice {
|
||||
if !message.text.isEmpty {
|
||||
messageText = "🎤 \(messageText)"
|
||||
} else if isVoice {
|
||||
if message.text.isEmpty {
|
||||
messageText = strings.Message_Audio
|
||||
} else {
|
||||
|
@ -495,7 +495,7 @@ public class ContactsController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: self.presentationData.strings.Contacts_SortBy))
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByName, color: .accent, action: { [weak actionSheet] in
|
||||
|
@ -193,7 +193,7 @@ final class ContactsControllerNode: ASDisplayNode {
|
||||
}
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: contactContextMenuItems(context: self.context, peerId: peer.id, contactsController: contactsController), reactionItems: [], gesture: gesture)
|
||||
let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: contactContextMenuItems(context: self.context, peerId: peer.id, contactsController: contactsController), reactionItems: [], gesture: gesture)
|
||||
contactsController.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let titleBoldFont = Font.medium(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
let badgeFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
let badgeFont = Font.regular(14.0)
|
||||
let avatarDiameter = min(40.0, floor(item.presentationData.fontSize.itemListBaseFontSize * 40.0 / 17.0))
|
||||
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
@ -611,7 +612,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset - badgeSize), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = statusAttributedString == nil ? 11.0 : 6.0
|
||||
let titleVerticalInset: CGFloat = statusAttributedString == nil ? 13.0 : 6.0
|
||||
let verticalInset: CGFloat = statusAttributedString == nil ? 13.0 : 6.0
|
||||
|
||||
let statusHeightComponent: CGFloat
|
||||
if statusAttributedString == nil {
|
||||
@ -624,7 +626,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let titleFrame: CGRect
|
||||
if statusAttributedString != nil {
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.size)
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: titleVerticalInset), size: titleLayout.size)
|
||||
} else {
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((nodeLayout.contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size)
|
||||
}
|
||||
@ -707,7 +709,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 50.0, y: floor((nodeLayout.contentSize.height - 40.0) / 2.0)), size: CGSize(width: 40.0, height: 40.0)))
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 50.0, y: floor((nodeLayout.contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)))
|
||||
|
||||
let _ = titleApply()
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame.offsetBy(dx: revealOffset, dy: 0.0))
|
||||
|
@ -3,8 +3,6 @@ import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
|
||||
private let textFont = Font.regular(17.0)
|
||||
|
||||
enum ContextActionSibling {
|
||||
case none
|
||||
case item
|
||||
@ -23,17 +21,19 @@ final class ContextActionNode: ASDisplayNode {
|
||||
private let iconNode: ASImageNode
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
|
||||
init(theme: PresentationTheme, action: ContextMenuActionItem, getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void) {
|
||||
init(presentationData: PresentationData, action: ContextMenuActionItem, getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void) {
|
||||
self.action = action
|
||||
self.getController = getController
|
||||
self.actionSelected = actionSelected
|
||||
|
||||
let textFont = Font.regular(presentationData.fontSize.baseDisplaySize)
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isAccessibilityElement = false
|
||||
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor
|
||||
self.backgroundNode.backgroundColor = presentationData.theme.contextMenu.itemBackgroundColor
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isAccessibilityElement = false
|
||||
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor
|
||||
self.highlightedBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
@ -43,9 +43,9 @@ final class ContextActionNode: ASDisplayNode {
|
||||
let textColor: UIColor
|
||||
switch action.textColor {
|
||||
case .primary:
|
||||
textColor = theme.contextMenu.primaryColor
|
||||
textColor = presentationData.theme.contextMenu.primaryColor
|
||||
case .destructive:
|
||||
textColor = theme.contextMenu.destructiveColor
|
||||
textColor = presentationData.theme.contextMenu.destructiveColor
|
||||
}
|
||||
self.textNode.attributedText = NSAttributedString(string: action.text, font: textFont, textColor: textColor)
|
||||
|
||||
@ -62,7 +62,7 @@ final class ContextActionNode: ASDisplayNode {
|
||||
statusNode.isAccessibilityElement = false
|
||||
statusNode.isUserInteractionEnabled = false
|
||||
statusNode.displaysAsynchronously = false
|
||||
statusNode.attributedText = NSAttributedString(string: value, font: textFont, textColor: theme.contextMenu.secondaryColor)
|
||||
statusNode.attributedText = NSAttributedString(string: value, font: textFont, textColor: presentationData.theme.contextMenu.secondaryColor)
|
||||
statusNode.maximumNumberOfLines = 1
|
||||
self.statusNode = statusNode
|
||||
}
|
||||
@ -72,7 +72,7 @@ final class ContextActionNode: ASDisplayNode {
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
self.iconNode.displayWithoutProcessing = true
|
||||
self.iconNode.isUserInteractionEnabled = false
|
||||
self.iconNode.image = action.icon(theme)
|
||||
self.iconNode.image = action.icon(presentationData.theme)
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
self.buttonNode.isAccessibilityElement = true
|
||||
@ -149,27 +149,30 @@ final class ContextActionNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme) {
|
||||
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor
|
||||
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor
|
||||
func updateTheme(presentationData: PresentationData) {
|
||||
self.backgroundNode.backgroundColor = presentationData.theme.contextMenu.itemBackgroundColor
|
||||
self.highlightedBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
|
||||
|
||||
let textColor: UIColor
|
||||
switch action.textColor {
|
||||
case .primary:
|
||||
textColor = theme.contextMenu.primaryColor
|
||||
textColor = presentationData.theme.contextMenu.primaryColor
|
||||
case .destructive:
|
||||
textColor = theme.contextMenu.destructiveColor
|
||||
textColor = presentationData.theme.contextMenu.destructiveColor
|
||||
}
|
||||
|
||||
let textFont = Font.regular(presentationData.fontSize.baseDisplaySize)
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.action.text, font: textFont, textColor: textColor)
|
||||
|
||||
switch self.action.textLayout {
|
||||
case let .secondLineWithValue(value):
|
||||
self.statusNode?.attributedText = NSAttributedString(string: value, font: textFont, textColor: theme.contextMenu.secondaryColor)
|
||||
self.statusNode?.attributedText = NSAttributedString(string: value, font: textFont, textColor: presentationData.theme.contextMenu.secondaryColor)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self.iconNode.image = self.action.icon(theme)
|
||||
self.iconNode.image = self.action.icon(presentationData.theme)
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
|
@ -39,7 +39,7 @@ private enum ContextItemNode {
|
||||
}
|
||||
|
||||
final class ContextActionsContainerNode: ASDisplayNode {
|
||||
private let theme: PresentationTheme
|
||||
private let presentationData: PresentationData
|
||||
private var effectView: UIVisualEffectView?
|
||||
private var itemNodes: [ContextItemNode]
|
||||
private let feedbackTap: () -> Void
|
||||
@ -47,23 +47,23 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
private(set) var gesture: UIGestureRecognizer?
|
||||
private var currentHighlightedActionNode: ContextActionNode?
|
||||
|
||||
init(theme: PresentationTheme, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
init(presentationData: PresentationData, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.feedbackTap = feedbackTap
|
||||
|
||||
var itemNodes: [ContextItemNode] = []
|
||||
for i in 0 ..< items.count {
|
||||
switch items[i] {
|
||||
case let .action(action):
|
||||
itemNodes.append(.action(ContextActionNode(theme: theme, action: action, getController: getController, actionSelected: actionSelected)))
|
||||
itemNodes.append(.action(ContextActionNode(presentationData: presentationData, action: action, getController: getController, actionSelected: actionSelected)))
|
||||
if i != items.count - 1, case .action = items[i + 1] {
|
||||
let separatorNode = ASDisplayNode()
|
||||
separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor
|
||||
separatorNode.backgroundColor = presentationData.theme.contextMenu.itemSeparatorColor
|
||||
itemNodes.append(.itemSeparator(separatorNode))
|
||||
}
|
||||
case .separator:
|
||||
let separatorNode = ASDisplayNode()
|
||||
separatorNode.backgroundColor = theme.contextMenu.sectionSeparatorColor
|
||||
separatorNode.backgroundColor = presentationData.theme.contextMenu.sectionSeparatorColor
|
||||
itemNodes.append(.separator(separatorNode))
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
self.clipsToBounds = true
|
||||
self.cornerRadius = 14.0
|
||||
|
||||
self.backgroundColor = theme.contextMenu.backgroundColor
|
||||
self.backgroundColor = presentationData.theme.contextMenu.backgroundColor
|
||||
|
||||
self.itemNodes.forEach({ itemNode in
|
||||
switch itemNode {
|
||||
@ -133,7 +133,7 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
if self.effectView == nil {
|
||||
let effectView: UIVisualEffectView
|
||||
if #available(iOS 13.0, *) {
|
||||
if self.theme.overallDarkAppearance {
|
||||
if self.presentationData.theme.overallDarkAppearance {
|
||||
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialDark))
|
||||
} else {
|
||||
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialLight))
|
||||
@ -213,19 +213,19 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
return size
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme) {
|
||||
func updateTheme(presentationData: PresentationData) {
|
||||
for itemNode in self.itemNodes {
|
||||
switch itemNode {
|
||||
case let .action(action):
|
||||
action.updateTheme(theme: theme)
|
||||
action.updateTheme(presentationData: presentationData)
|
||||
case let .separator(separator):
|
||||
separator.backgroundColor = theme.contextMenu.sectionSeparatorColor
|
||||
separator.backgroundColor = presentationData.theme.contextMenu.sectionSeparatorColor
|
||||
case let .itemSeparator(itemSeparator):
|
||||
itemSeparator.backgroundColor = theme.contextMenu.itemSeparatorColor
|
||||
itemSeparator.backgroundColor = presentationData.theme.contextMenu.itemSeparatorColor
|
||||
}
|
||||
}
|
||||
|
||||
self.backgroundColor = theme.contextMenu.backgroundColor
|
||||
self.backgroundColor = presentationData.theme.contextMenu.backgroundColor
|
||||
}
|
||||
|
||||
func actionNode(at point: CGPoint) -> ContextActionNode? {
|
||||
|
@ -60,8 +60,7 @@ private func convertFrame(_ frame: CGRect, from fromView: UIView, to toView: UIV
|
||||
}
|
||||
|
||||
private final class ContextControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||
private var theme: PresentationTheme
|
||||
private var strings: PresentationStrings
|
||||
private var presentationData: PresentationData
|
||||
private let source: ContextContentSource
|
||||
private var items: Signal<[ContextMenuItem], NoError>
|
||||
private let beginDismiss: (ContextMenuActionResult) -> Void
|
||||
@ -108,9 +107,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
|
||||
private let itemsDisposable = MetaDisposable()
|
||||
|
||||
init(account: Account, controller: ContextController, theme: PresentationTheme, strings: PresentationStrings, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, reactionSelected: @escaping (String) -> Void, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
init(account: Account, controller: ContextController, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, reactionSelected: @escaping (String) -> Void, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.source = source
|
||||
self.items = items
|
||||
self.beginDismiss = beginDismiss
|
||||
@ -126,7 +124,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
self.effectView = UIVisualEffectView()
|
||||
if #available(iOS 9.0, *) {
|
||||
} else {
|
||||
if theme.rootController.keyboardColor == .dark {
|
||||
if presentationData.theme.rootController.keyboardColor == .dark {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
@ -135,7 +133,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
}
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = theme.contextMenu.dimColor
|
||||
self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor
|
||||
self.dimNode.alpha = 0.0
|
||||
|
||||
self.withoutBlurDimNode = ASDisplayNode()
|
||||
@ -159,7 +157,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
|
||||
var feedbackTap: (() -> Void)?
|
||||
|
||||
self.actionsContainerNode = ContextActionsContainerNode(theme: theme, items: [], getController: { [weak controller] in
|
||||
self.actionsContainerNode = ContextActionsContainerNode(presentationData: presentationData, items: [], getController: { [weak controller] in
|
||||
return controller
|
||||
}, actionSelected: { result in
|
||||
beginDismiss(result)
|
||||
@ -168,7 +166,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
})
|
||||
|
||||
if !reactionItems.isEmpty {
|
||||
let reactionContextNode = ReactionContextNode(account: account, theme: theme, items: reactionItems)
|
||||
let reactionContextNode = ReactionContextNode(account: account, theme: presentationData.theme, items: reactionItems)
|
||||
self.reactionContextNode = reactionContextNode
|
||||
} else {
|
||||
self.reactionContextNode = nil
|
||||
@ -966,7 +964,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
self.currentItems = items
|
||||
|
||||
let previousActionsContainerNode = self.actionsContainerNode
|
||||
self.actionsContainerNode = ContextActionsContainerNode(theme: self.theme, items: items, getController: { [weak self] in
|
||||
self.actionsContainerNode = ContextActionsContainerNode(presentationData: self.presentationData, items: items, getController: { [weak self] in
|
||||
return self?.getController()
|
||||
}, actionSelected: { [weak self] result in
|
||||
self?.beginDismiss(result)
|
||||
@ -988,11 +986,11 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
}
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
func updateTheme(presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.dimNode.backgroundColor = theme.contextMenu.dimColor
|
||||
self.actionsContainerNode.updateTheme(theme: theme)
|
||||
self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor
|
||||
self.actionsContainerNode.updateTheme(presentationData: presentationData)
|
||||
|
||||
if let validLayout = self.validLayout {
|
||||
self.updateLayout(layout: validLayout, transition: .immediate, previousActionsContainerNode: nil)
|
||||
@ -1364,8 +1362,7 @@ public enum ContextContentSource {
|
||||
|
||||
public final class ContextController: ViewController, StandalonePresentableController {
|
||||
private let account: Account
|
||||
private var theme: PresentationTheme
|
||||
private var strings: PresentationStrings
|
||||
private var presentationData: PresentationData
|
||||
private let source: ContextContentSource
|
||||
private var items: Signal<[ContextMenuItem], NoError>
|
||||
private var reactionItems: [ReactionContextItem]
|
||||
@ -1387,10 +1384,9 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
||||
|
||||
public var reactionSelected: ((String) -> Void)?
|
||||
|
||||
public init(account: Account, theme: PresentationTheme, strings: PresentationStrings, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil) {
|
||||
public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil) {
|
||||
self.account = account
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.presentationData = presentationData
|
||||
self.source = source
|
||||
self.items = items
|
||||
self.reactionItems = reactionItems
|
||||
@ -1407,7 +1403,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ContextControllerNode(account: self.account, controller: self, theme: self.theme, strings: self.strings, source: self.source, items: self.items, reactionItems: self.reactionItems, beginDismiss: { [weak self] result in
|
||||
self.displayNode = ContextControllerNode(account: self.account, controller: self, presentationData: self.presentationData, source: self.source, items: self.items, reactionItems: self.reactionItems, beginDismiss: { [weak self] result in
|
||||
self?.dismiss(result: result, completion: nil)
|
||||
}, recognizer: self.recognizer, gesture: self.gesture, reactionSelected: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
@ -1464,10 +1460,10 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
||||
}
|
||||
}
|
||||
|
||||
public func updateTheme(theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
public func updateTheme(presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
if self.isNodeLoaded {
|
||||
self.controllerNode.updateTheme(theme: theme)
|
||||
self.controllerNode.updateTheme(presentationData: presentationData)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,11 @@ public final class DateSelectionActionSheetController: ActionSheetController {
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -56,6 +56,8 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
let peerFont = Font.regular(floor(theme.baseFontSize * 14.0 / 17.0))
|
||||
|
||||
self.avatarNode = AvatarNode(font: avatarFont)
|
||||
self.avatarNode.isAccessibilityElement = false
|
||||
|
||||
@ -88,9 +90,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
||||
case .clearCache, .clearCacheSuggestion:
|
||||
switch action {
|
||||
case .clearCache:
|
||||
attributedText = NSAttributedString(string: strings.ClearCache_Description, font: Font.regular(14.0), textColor: theme.primaryTextColor)
|
||||
attributedText = NSAttributedString(string: strings.ClearCache_Description, font: peerFont, textColor: theme.primaryTextColor)
|
||||
case .clearCacheSuggestion:
|
||||
attributedText = NSAttributedString(string: strings.ClearCache_FreeSpaceDescription, font: Font.regular(14.0), textColor: theme.primaryTextColor)
|
||||
attributedText = NSAttributedString(string: strings.ClearCache_FreeSpaceDescription, font: peerFont, textColor: theme.primaryTextColor)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -115,9 +117,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
||||
break
|
||||
}
|
||||
if let text = text {
|
||||
var formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: Font.regular(14.0), textColor: theme.primaryTextColor))
|
||||
var formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: peerFont, textColor: theme.primaryTextColor))
|
||||
for (_, range) in text.1 {
|
||||
formattedAttributedText.addAttribute(.font, value: Font.semibold(14.0), range: range)
|
||||
formattedAttributedText.addAttribute(.font, value: peerFont, range: range)
|
||||
}
|
||||
attributedText = formattedAttributedText
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ public final class DeviceAccess {
|
||||
}
|
||||
}
|
||||
|
||||
public static func authorizeAccess(to subject: DeviceAccessSubject, registerForNotifications: ((@escaping (Bool) -> Void) -> Void)? = nil, requestSiriAuthorization: ((@escaping (Bool) -> Void) -> Void)? = nil, presentationData: PresentationData? = nil, present: @escaping (ViewController, Any?) -> Void = { _, _ in }, openSettings: @escaping () -> Void = { }, displayNotificationFromBackground: @escaping (String) -> Void = { _ in }, _ completion: @escaping (Bool) -> Void = { _ in }) {
|
||||
public static func authorizeAccess(to subject: DeviceAccessSubject, registerForNotifications: ((@escaping (Bool) -> Void) -> Void)? = nil, requestSiriAuthorization: ((@escaping (Bool) -> Void) -> Void)? = nil, locationManager: CLLocationManager? = nil, presentationData: PresentationData? = nil, present: @escaping (ViewController, Any?) -> Void = { _, _ in }, openSettings: @escaping () -> Void = { }, displayNotificationFromBackground: @escaping (String) -> Void = { _ in }, _ completion: @escaping (Bool) -> Void = { _ in }) {
|
||||
switch subject {
|
||||
case .camera:
|
||||
let status = PGCamera.cameraAuthorizationStatus()
|
||||
@ -382,7 +382,14 @@ public final class DeviceAccess {
|
||||
})]), nil)
|
||||
}
|
||||
case .notDetermined:
|
||||
completion(true)
|
||||
switch locationSubject {
|
||||
case .send:
|
||||
locationManager?.requestWhenInUseAuthorization()
|
||||
case .live:
|
||||
locationManager?.requestAlwaysAuthorization()
|
||||
default:
|
||||
break
|
||||
}
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ public class ActionSheetButtonItem: ActionSheetItem {
|
||||
public class ActionSheetButtonNode: ActionSheetItemNode {
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
public static let boldFont: UIFont = Font.medium(20.0)
|
||||
private let defaultFont: UIFont
|
||||
private let boldFont: UIFont
|
||||
|
||||
private var item: ActionSheetButtonItem?
|
||||
|
||||
@ -59,6 +59,9 @@ public class ActionSheetButtonNode: ActionSheetItemNode {
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
self.boldFont = Font.medium(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
self.button.isAccessibilityElement = false
|
||||
|
||||
@ -113,9 +116,9 @@ public class ActionSheetButtonNode: ActionSheetItemNode {
|
||||
}
|
||||
switch item.font {
|
||||
case .default:
|
||||
textFont = ActionSheetButtonNode.defaultFont
|
||||
textFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
case .bold:
|
||||
textFont = ActionSheetButtonNode.boldFont
|
||||
textFont = Font.medium(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
}
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: textFont, textColor: textColor)
|
||||
self.label.isAccessibilityElement = false
|
||||
|
@ -39,7 +39,7 @@ public class ActionSheetCheckboxItem: ActionSheetItem {
|
||||
}
|
||||
|
||||
public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
private let defaultFont: UIFont
|
||||
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
@ -54,6 +54,7 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
||||
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
self.button.isAccessibilityElement = false
|
||||
@ -118,8 +119,10 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
|
||||
func setItem(_ item: ActionSheetCheckboxItem) {
|
||||
self.item = item
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: ActionSheetCheckboxItemNode.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.labelNode.attributedText = NSAttributedString(string: item.label, font: ActionSheetCheckboxItemNode.defaultFont, textColor: self.theme.secondaryTextColor)
|
||||
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: item.title, font: defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.labelNode.attributedText = NSAttributedString(string: item.label, font: defaultFont, textColor: self.theme.secondaryTextColor)
|
||||
self.checkNode.isHidden = !item.value
|
||||
|
||||
self.accessibilityArea.accessibilityLabel = item.title
|
||||
|
@ -42,6 +42,7 @@ public class ActionSheetSwitchNode: ActionSheetItemNode {
|
||||
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
self.button.isAccessibilityElement = false
|
||||
@ -85,7 +86,9 @@ public class ActionSheetSwitchNode: ActionSheetItemNode {
|
||||
func setItem(_ item: ActionSheetSwitchItem) {
|
||||
self.item = item
|
||||
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: ActionSheetButtonNode.defaultFont, textColor: self.theme.primaryTextColor)
|
||||
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: defaultFont, textColor: self.theme.primaryTextColor)
|
||||
self.label.isAccessibilityElement = false
|
||||
|
||||
self.switchNode.isOn = item.isOn
|
||||
|
@ -26,7 +26,7 @@ public class ActionSheetTextItem: ActionSheetItem {
|
||||
}
|
||||
|
||||
public class ActionSheetTextNode: ActionSheetItemNode {
|
||||
public static let defaultFont: UIFont = Font.regular(13.0)
|
||||
private let defaultFont: UIFont
|
||||
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
@ -38,6 +38,7 @@ public class ActionSheetTextNode: ActionSheetItemNode {
|
||||
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
self.defaultFont = Font.regular(floor(theme.baseFontSize * 13.0 / 17.0))
|
||||
|
||||
self.label = ASTextNode()
|
||||
self.label.isUserInteractionEnabled = false
|
||||
@ -60,7 +61,9 @@ public class ActionSheetTextNode: ActionSheetItemNode {
|
||||
func setItem(_ item: ActionSheetTextItem) {
|
||||
self.item = item
|
||||
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: ActionSheetTextNode.defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center)
|
||||
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.accessibilityArea.accessibilityLabel = item.title
|
||||
|
||||
self.setNeedsLayout()
|
||||
|
@ -21,8 +21,9 @@ public final class ActionSheetControllerTheme: Equatable {
|
||||
public let switchFrameColor: UIColor
|
||||
public let switchContentColor: UIColor
|
||||
public let switchHandleColor: UIColor
|
||||
public let baseFontSize: CGFloat
|
||||
|
||||
public init(dimColor: UIColor, backgroundType: ActionSheetControllerThemeBackgroundType, itemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, standardActionTextColor: UIColor, destructiveActionTextColor: UIColor, disabledActionTextColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, controlAccentColor: UIColor, controlColor: UIColor, switchFrameColor: UIColor, switchContentColor: UIColor, switchHandleColor: UIColor) {
|
||||
public init(dimColor: UIColor, backgroundType: ActionSheetControllerThemeBackgroundType, itemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, standardActionTextColor: UIColor, destructiveActionTextColor: UIColor, disabledActionTextColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, controlAccentColor: UIColor, controlColor: UIColor, switchFrameColor: UIColor, switchContentColor: UIColor, switchHandleColor: UIColor, baseFontSize: CGFloat) {
|
||||
self.dimColor = dimColor
|
||||
self.backgroundType = backgroundType
|
||||
self.itemBackgroundColor = itemBackgroundColor
|
||||
@ -37,6 +38,7 @@ public final class ActionSheetControllerTheme: Equatable {
|
||||
self.switchFrameColor = switchFrameColor
|
||||
self.switchContentColor = switchContentColor
|
||||
self.switchHandleColor = switchHandleColor
|
||||
self.baseFontSize = min(26.0, baseFontSize)
|
||||
}
|
||||
|
||||
public static func ==(lhs: ActionSheetControllerTheme, rhs: ActionSheetControllerTheme) -> Bool {
|
||||
@ -82,6 +84,9 @@ public final class ActionSheetControllerTheme: Equatable {
|
||||
if lhs.switchHandleColor != rhs.switchHandleColor {
|
||||
return false
|
||||
}
|
||||
if lhs.baseFontSize != rhs.baseFontSize {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ public class ImmediateTextNode: TextNode {
|
||||
public var lineSpacing: CGFloat = 0.0
|
||||
public var insets: UIEdgeInsets = UIEdgeInsets()
|
||||
public var textShadowColor: UIColor?
|
||||
public var textStroke: (UIColor, CGFloat)?
|
||||
|
||||
private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer?
|
||||
private var linkHighlightingNode: LinkHighlightingNode?
|
||||
@ -35,7 +36,7 @@ public class ImmediateTextNode: TextNode {
|
||||
|
||||
public func updateLayout(_ constrainedSize: CGSize) -> CGSize {
|
||||
let makeLayout = TextNode.asyncLayout(self)
|
||||
let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: nil, insets: self.insets, textShadowColor: self.textShadowColor))
|
||||
let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: nil, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke))
|
||||
let _ = apply()
|
||||
if layout.numberOfLines > 1 {
|
||||
self.trailingLineWidth = layout.trailingLineWidth
|
||||
|
@ -2413,7 +2413,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
//print("replay after \(self.itemNodes.map({"\($0.index) \(unsafeAddressOf($0))"}))")
|
||||
}
|
||||
|
||||
if let scrollToItem = scrollToItem, !self.areAllItemsOnScreen() {
|
||||
if let scrollToItem = scrollToItem, !self.areAllItemsOnScreen() || updateSizeAndInsets == nil {
|
||||
self.stopScrolling()
|
||||
|
||||
for itemNode in self.itemNodes {
|
||||
|
@ -95,8 +95,9 @@ public final class TextNodeLayoutArguments {
|
||||
public let insets: UIEdgeInsets
|
||||
public let lineColor: UIColor?
|
||||
public let textShadowColor: UIColor?
|
||||
public let textStroke: (UIColor, CGFloat)?
|
||||
|
||||
public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil) {
|
||||
public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil) {
|
||||
self.attributedString = attributedString
|
||||
self.backgroundColor = backgroundColor
|
||||
self.minimumNumberOfLines = minimumNumberOfLines
|
||||
@ -109,6 +110,7 @@ public final class TextNodeLayoutArguments {
|
||||
self.insets = insets
|
||||
self.lineColor = lineColor
|
||||
self.textShadowColor = textShadowColor
|
||||
self.textStroke = textStroke
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,9 +132,10 @@ public final class TextNodeLayout: NSObject {
|
||||
fileprivate let blockQuotes: [TextNodeBlockQuote]
|
||||
fileprivate let lineColor: UIColor?
|
||||
fileprivate let textShadowColor: UIColor?
|
||||
fileprivate let textStroke: (UIColor, CGFloat)?
|
||||
public let hasRTL: Bool
|
||||
|
||||
fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?) {
|
||||
fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) {
|
||||
self.attributedString = attributedString
|
||||
self.maximumNumberOfLines = maximumNumberOfLines
|
||||
self.truncationType = truncationType
|
||||
@ -150,6 +153,7 @@ public final class TextNodeLayout: NSObject {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.lineColor = lineColor
|
||||
self.textShadowColor = textShadowColor
|
||||
self.textStroke = textStroke
|
||||
var hasRTL = false
|
||||
for line in lines {
|
||||
if line.isRTL {
|
||||
@ -780,7 +784,7 @@ public class TextNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?) -> TextNodeLayout {
|
||||
private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) -> TextNodeLayout {
|
||||
if let attributedString = attributedString {
|
||||
let stringLength = attributedString.length
|
||||
|
||||
@ -806,7 +810,7 @@ public class TextNode: ASDisplayNode {
|
||||
var maybeTypesetter: CTTypesetter?
|
||||
maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString)
|
||||
if maybeTypesetter == nil {
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor)
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke)
|
||||
}
|
||||
|
||||
let typesetter = maybeTypesetter!
|
||||
@ -1010,9 +1014,9 @@ public class TextNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor)
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke)
|
||||
} else {
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor)
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1050,6 +1054,14 @@ public class TextNode: ASDisplayNode {
|
||||
context.setShadow(offset: CGSize(width: 0.0, height: 1.0), blur: 0.0, color: textShadowColor.cgColor)
|
||||
}
|
||||
|
||||
// if let (textStrokeColor, textStrokeWidth) = layout.textStroke {
|
||||
// context.setBlendMode(.normal)
|
||||
// context.setLineCap(.round)
|
||||
// context.setLineJoin(.round)
|
||||
// context.setStrokeColor(textStrokeColor.cgColor)
|
||||
// context.setLineWidth(textStrokeWidth)
|
||||
// }
|
||||
|
||||
let textMatrix = context.textMatrix
|
||||
let textPosition = context.textPosition
|
||||
context.textMatrix = CGAffineTransform(scaleX: 1.0, y: -1.0)
|
||||
@ -1156,11 +1168,11 @@ public class TextNode: ASDisplayNode {
|
||||
if stringMatch {
|
||||
layout = existingLayout
|
||||
} else {
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke)
|
||||
updated = true
|
||||
}
|
||||
} else {
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke)
|
||||
updated = true
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ open class TooltipController: ViewController, StandalonePresentableController {
|
||||
}
|
||||
|
||||
public private(set) var content: TooltipControllerContent
|
||||
private let baseFontSize: CGFloat
|
||||
|
||||
open func updateContent(_ content: TooltipControllerContent, animated: Bool, extendTimer: Bool, arrowOnBottom: Bool = true) {
|
||||
if self.content != content {
|
||||
@ -89,8 +90,9 @@ open class TooltipController: ViewController, StandalonePresentableController {
|
||||
|
||||
public var dismissed: ((Bool) -> Void)?
|
||||
|
||||
public init(content: TooltipControllerContent, timeout: Double = 2.0, dismissByTapOutside: Bool = false, dismissByTapOutsideSource: Bool = false, dismissImmediatelyOnLayoutUpdate: Bool = false, arrowOnBottom: Bool = true) {
|
||||
public init(content: TooltipControllerContent, baseFontSize: CGFloat, timeout: Double = 2.0, dismissByTapOutside: Bool = false, dismissByTapOutsideSource: Bool = false, dismissImmediatelyOnLayoutUpdate: Bool = false, arrowOnBottom: Bool = true) {
|
||||
self.content = content
|
||||
self.baseFontSize = baseFontSize
|
||||
self.timeout = timeout
|
||||
self.dismissByTapOutside = dismissByTapOutside
|
||||
self.dismissByTapOutsideSource = dismissByTapOutsideSource
|
||||
@ -111,7 +113,7 @@ open class TooltipController: ViewController, StandalonePresentableController {
|
||||
}
|
||||
|
||||
override open func loadDisplayNode() {
|
||||
self.displayNode = TooltipControllerNode(content: self.content, dismiss: { [weak self] tappedInside in
|
||||
self.displayNode = TooltipControllerNode(content: self.content, baseFontSize: self.baseFontSize, dismiss: { [weak self] tappedInside in
|
||||
self?.dismiss(tappedInside: tappedInside)
|
||||
}, dismissByTapOutside: self.dismissByTapOutside, dismissByTapOutsideSource: self.dismissByTapOutsideSource)
|
||||
self.controllerNode.arrowOnBottom = self.initialArrowOnBottom
|
||||
|
@ -3,6 +3,8 @@ import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
final class TooltipControllerNode: ASDisplayNode {
|
||||
private let baseFontSize: CGFloat
|
||||
|
||||
private let dismiss: (Bool) -> Void
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
@ -19,7 +21,9 @@ final class TooltipControllerNode: ASDisplayNode {
|
||||
private var dismissedByTouchOutside = false
|
||||
private var dismissByTapOutsideSource = false
|
||||
|
||||
init(content: TooltipControllerContent, dismiss: @escaping (Bool) -> Void, dismissByTapOutside: Bool, dismissByTapOutsideSource: Bool) {
|
||||
init(content: TooltipControllerContent, baseFontSize: CGFloat, dismiss: @escaping (Bool) -> Void, dismissByTapOutside: Bool, dismissByTapOutsideSource: Bool) {
|
||||
self.baseFontSize = baseFontSize
|
||||
|
||||
self.dismissByTapOutside = dismissByTapOutside
|
||||
self.dismissByTapOutsideSource = dismissByTapOutsideSource
|
||||
|
||||
@ -33,7 +37,7 @@ final class TooltipControllerNode: ASDisplayNode {
|
||||
if case let .attributedText(text) = content {
|
||||
self.textNode.attributedText = text
|
||||
} else {
|
||||
self.textNode.attributedText = NSAttributedString(string: content.text, font: Font.regular(14.0), textColor: .white, paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: content.text, font: Font.regular(floor(baseFontSize * 14.0 / 17.0)), textColor: .white, paragraphAlignment: .center)
|
||||
}
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
self.textNode.displaysAsynchronously = false
|
||||
@ -58,7 +62,7 @@ final class TooltipControllerNode: ASDisplayNode {
|
||||
})
|
||||
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.12)
|
||||
}
|
||||
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white, paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(floor(self.baseFontSize * 14.0 / 17.0)), textColor: .white, paragraphAlignment: .center)
|
||||
if let layout = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
|
@ -529,7 +529,11 @@ public enum ViewControllerNavigationPresentation {
|
||||
}
|
||||
|
||||
open func dismiss(completion: (() -> Void)? = nil) {
|
||||
(self.navigationController as? NavigationController)?.filterController(self, animated: true)
|
||||
if let navigationController = self.navigationController as? NavigationController {
|
||||
navigationController.filterController(self, animated: true)
|
||||
} else {
|
||||
self.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
||||
|
@ -272,6 +272,8 @@ public class Window1 {
|
||||
public var previewThemeAccentColor: UIColor = .blue
|
||||
public var previewThemeDarkBlur: Bool = false
|
||||
|
||||
private var shouldNotAnimateLikelyKeyboardAutocorrectionSwitch: Bool = false
|
||||
|
||||
public private(set) var forceInCallStatusBarText: String? = nil
|
||||
public var inCallNavigate: (() -> Void)? {
|
||||
didSet {
|
||||
@ -522,7 +524,15 @@ public class Window1 {
|
||||
transitionCurve = .easeInOut
|
||||
}
|
||||
|
||||
strongSelf.updateLayout { $0.update(inputHeight: keyboardHeight.isLessThanOrEqualTo(0.0) ? nil : keyboardHeight, transition: .animated(duration: duration, curve: transitionCurve), overrideTransition: false) }
|
||||
var transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: transitionCurve)
|
||||
|
||||
if strongSelf.shouldNotAnimateLikelyKeyboardAutocorrectionSwitch, let inputHeight = strongSelf.windowLayout.inputHeight {
|
||||
if abs(inputHeight - keyboardHeight) <= 44.1 {
|
||||
transition = .immediate
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.updateLayout { $0.update(inputHeight: keyboardHeight.isLessThanOrEqualTo(0.0) ? nil : keyboardHeight, transition: transition, overrideTransition: false) }
|
||||
}
|
||||
})
|
||||
|
||||
@ -1203,4 +1213,11 @@ public class Window1 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func doNotAnimateLikelyKeyboardAutocorrectionSwitch() {
|
||||
self.shouldNotAnimateLikelyKeyboardAutocorrectionSwitch = true
|
||||
DispatchQueue.main.async {
|
||||
self.shouldNotAnimateLikelyKeyboardAutocorrectionSwitch = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ class CaptionScrollWrapperNode: ASDisplayNode {
|
||||
|
||||
final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private var theme: PresentationTheme
|
||||
private var strings: PresentationStrings
|
||||
private var nameOrder: PresentationPersonNameOrder
|
||||
@ -243,6 +244,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.theme = presentationData.theme
|
||||
self.strings = presentationData.strings
|
||||
self.nameOrder = presentationData.nameDisplayOrder
|
||||
@ -757,7 +759,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
}
|
||||
}
|
||||
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
let items: [ActionSheetItem] = [
|
||||
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
@ -787,7 +789,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
private func commitDeleteMessages(_ messages: [Message], ask: Bool) {
|
||||
self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in
|
||||
if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty {
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
var personalPeerName: String?
|
||||
var isChannel = false
|
||||
@ -947,7 +949,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
}
|
||||
}
|
||||
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
let items: [ActionSheetItem] = [
|
||||
ActionSheetButtonItem(title: singleText, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
@ -609,7 +609,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
} else if canOpenIn {
|
||||
openText = strongSelf.presentationData.strings.Conversation_FileOpenIn
|
||||
}
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: cleanUrl))
|
||||
@ -652,7 +652,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
])])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
case let .peerMention(peerId, mention):
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
if !mention.isEmpty {
|
||||
items.append(ActionSheetTextItem(title: mention))
|
||||
@ -677,7 +677,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
])])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
case let .textMention(mention):
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: mention),
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
|
||||
@ -698,7 +698,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
])])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
case let .botCommand(command):
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: command))
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in
|
||||
@ -712,7 +712,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
])])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
case let .hashtag(peerName, hashtag):
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: hashtag),
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
|
||||
@ -734,7 +734,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
case let .timecode(timecode, text):
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: text),
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
|
||||
|
@ -2,6 +2,19 @@ import Foundation
|
||||
import CoreLocation
|
||||
import SwiftSignalKit
|
||||
|
||||
public func geocodeLocation(address: String) -> Signal<[CLPlacemark]?, NoError> {
|
||||
return Signal { subscriber in
|
||||
let geocoder = CLGeocoder()
|
||||
geocoder.geocodeAddressString(address) { (placemarks, _) in
|
||||
subscriber.putNext(placemarks)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return ActionDisposable {
|
||||
geocoder.cancelGeocode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func geocodeLocation(dictionary: [String: String]) -> Signal<(Double, Double)?, NoError> {
|
||||
return Signal { subscriber in
|
||||
let geocoder = CLGeocoder()
|
||||
|
@ -260,7 +260,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
|
||||
if let strongSelf = self {
|
||||
let canOpenIn = availableOpenInOptions(context: context, item: .url(url: url.url)).count > 1
|
||||
let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: url.url),
|
||||
ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in
|
||||
|
@ -323,7 +323,7 @@ func instantPageThemeForType(_ type: InstantPageThemeType, settings: InstantPage
|
||||
|
||||
extension ActionSheetControllerTheme {
|
||||
convenience init(instantPageTheme: InstantPageTheme) {
|
||||
self.init(dimColor: UIColor(white: 0.0, alpha: 0.4), backgroundType: instantPageTheme.type != .dark ? .light : .dark, itemBackgroundColor: instantPageTheme.overlayPanelColor, itemHighlightedBackgroundColor: instantPageTheme.panelHighlightedBackgroundColor, standardActionTextColor: instantPageTheme.panelAccentColor, destructiveActionTextColor: instantPageTheme.panelAccentColor, disabledActionTextColor: instantPageTheme.panelAccentColor, primaryTextColor: instantPageTheme.textCategories.paragraph.color, secondaryTextColor: instantPageTheme.textCategories.caption.color, controlAccentColor: instantPageTheme.panelAccentColor, controlColor: instantPageTheme.tableBorderColor, switchFrameColor: .white, switchContentColor: .white, switchHandleColor: .white)
|
||||
self.init(dimColor: UIColor(white: 0.0, alpha: 0.4), backgroundType: instantPageTheme.type != .dark ? .light : .dark, itemBackgroundColor: instantPageTheme.overlayPanelColor, itemHighlightedBackgroundColor: instantPageTheme.panelHighlightedBackgroundColor, standardActionTextColor: instantPageTheme.panelAccentColor, destructiveActionTextColor: instantPageTheme.panelAccentColor, disabledActionTextColor: instantPageTheme.panelAccentColor, primaryTextColor: instantPageTheme.textCategories.paragraph.color, secondaryTextColor: instantPageTheme.textCategories.caption.color, controlAccentColor: instantPageTheme.panelAccentColor, controlColor: instantPageTheme.tableBorderColor, switchFrameColor: .white, switchContentColor: .white, switchHandleColor: .white, baseFontSize: 17.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,22 +178,7 @@ public final class ItemListPresentationData: Equatable {
|
||||
|
||||
public extension PresentationFontSize {
|
||||
var itemListBaseHeaderFontSize: CGFloat {
|
||||
switch self {
|
||||
case .extraSmall:
|
||||
return 13.0
|
||||
case .small:
|
||||
return 14.0
|
||||
case .medium:
|
||||
return 15.0
|
||||
case .regular:
|
||||
return 16.0
|
||||
case .large:
|
||||
return 18.0
|
||||
case .extraLarge:
|
||||
return 22.0
|
||||
case .extraLargeX2:
|
||||
return 25.0
|
||||
}
|
||||
return floor(self.itemListBaseFontSize * 13.0 / 17.0)
|
||||
}
|
||||
|
||||
var itemListBaseFontSize: CGFloat {
|
||||
|
@ -14,24 +14,46 @@ public final class ItemListVenueItem: ListViewItem, ItemListItem {
|
||||
let presentationData: ItemListPresentationData
|
||||
let account: Account
|
||||
let venue: TelegramMediaMap
|
||||
|
||||
public let sectionId: ItemListSectionId
|
||||
let title: String?
|
||||
let subtitle: String?
|
||||
let style: ItemListStyle
|
||||
let action: (() -> Void)?
|
||||
let infoAction: (() -> Void)?
|
||||
|
||||
public init(presentationData: ItemListPresentationData, account: Account, venue: TelegramMediaMap, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?) {
|
||||
public let sectionId: ItemListSectionId
|
||||
let header: ListViewItemHeader?
|
||||
|
||||
public init(presentationData: ItemListPresentationData, account: Account, venue: TelegramMediaMap, title: String? = nil, subtitle: String? = nil, sectionId: ItemListSectionId = 0, style: ItemListStyle, action: (() -> Void)?, infoAction: (() -> Void)? = nil, header: ListViewItemHeader? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.account = account
|
||||
self.venue = venue
|
||||
self.title = title
|
||||
self.subtitle = subtitle
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
self.action = action
|
||||
self.infoAction = infoAction
|
||||
self.header = header
|
||||
}
|
||||
|
||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
async {
|
||||
var firstWithHeader = false
|
||||
var last = false
|
||||
if self.style == .plain {
|
||||
if previousItem == nil {
|
||||
firstWithHeader = true
|
||||
} else if let previousItem = previousItem as? ItemListVenueItem, self.header != nil && previousItem.header?.id != self.header?.id {
|
||||
firstWithHeader = true
|
||||
}
|
||||
if nextItem == nil {
|
||||
last = true
|
||||
} else if let nextItem = nextItem as? ItemListVenueItem, self.header != nil && nextItem.header?.id != self.header?.id {
|
||||
last = true
|
||||
}
|
||||
}
|
||||
let node = ItemListVenueItemNode()
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem), firstWithHeader, last)
|
||||
|
||||
node.contentSize = layout.contentSize
|
||||
node.insets = layout.insets
|
||||
@ -55,7 +77,21 @@ public final class ItemListVenueItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
|
||||
async {
|
||||
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
var firstWithHeader = false
|
||||
var last = false
|
||||
if self.style == .plain {
|
||||
if previousItem == nil {
|
||||
firstWithHeader = true
|
||||
} else if let previousItem = previousItem as? ItemListVenueItem, self.header != nil && previousItem.header?.id != self.header?.id {
|
||||
firstWithHeader = true
|
||||
}
|
||||
if nextItem == nil {
|
||||
last = true
|
||||
} else if let nextItem = nextItem as? ItemListVenueItem, self.header != nil && nextItem.header?.id != self.header?.id {
|
||||
last = true
|
||||
}
|
||||
}
|
||||
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem), firstWithHeader, last)
|
||||
Queue.mainQueue().async {
|
||||
completion(layout, { _ in
|
||||
apply()
|
||||
@ -84,8 +120,10 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let iconNode: TransformImageNode
|
||||
private let titleNode: TextNode
|
||||
private let addressNode: TextNode
|
||||
private let infoButton: HighlightableButtonNode
|
||||
|
||||
private var layoutParams: (ItemListVenueItem, ListViewItemLayoutParams, ItemListNeighbors)?
|
||||
private var item: ItemListVenueItem?
|
||||
private var layoutParams: (ItemListVenueItem, ListViewItemLayoutParams, ItemListNeighbors, Bool, Bool)?
|
||||
|
||||
public var tag: ItemListItemTag?
|
||||
|
||||
@ -119,6 +157,8 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.addressNode.isUserInteractionEnabled = false
|
||||
self.addressNode.contentMode = .left
|
||||
self.addressNode.contentsScale = UIScreen.main.scale
|
||||
|
||||
self.infoButton = HighlightableButtonNode()
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
@ -130,16 +170,19 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.addressNode)
|
||||
self.addSubnode(self.infoButton)
|
||||
|
||||
self.infoButton.addTarget(self, action: #selector(self.infoPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
public func asyncLayout() -> (_ item: ItemListVenueItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
public func asyncLayout() -> (_ item: ItemListVenueItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors, _ firstWithHeader: Bool, _ last: Bool) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeAddressLayout = TextNode.asyncLayout(self.addressNode)
|
||||
let iconLayout = self.iconNode.asyncLayout()
|
||||
|
||||
let currentItem = self.layoutParams?.0
|
||||
|
||||
return { item, params, neighbors in
|
||||
return { item, params, neighbors, firstWithHeader, last in
|
||||
var updatedTheme: PresentationTheme?
|
||||
var updatedVenueType: String?
|
||||
|
||||
@ -155,11 +198,29 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
updatedVenueType = venueType
|
||||
}
|
||||
|
||||
let titleAttributedString = NSAttributedString(string: item.venue.venue?.title ?? "", font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let addressAttributedString = NSAttributedString(string: item.venue.venue?.address ?? "", font: addressFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
let title: String
|
||||
if let venueTitle = item.venue.venue?.title {
|
||||
title = venueTitle
|
||||
} else if let customTitle = item.title {
|
||||
title = customTitle
|
||||
} else {
|
||||
title = ""
|
||||
}
|
||||
|
||||
let subtitle: String
|
||||
if let address = item.venue.venue?.address {
|
||||
subtitle = address
|
||||
} else if let customSubtitle = item.subtitle {
|
||||
subtitle = customSubtitle
|
||||
} else {
|
||||
subtitle = ""
|
||||
}
|
||||
|
||||
let titleAttributedString = NSAttributedString(string: title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let addressAttributedString = NSAttributedString(string: subtitle, font: addressFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
||||
let leftInset: CGFloat = 65.0 + params.leftInset
|
||||
let rightInset: CGFloat = 16.0 + params.rightInset
|
||||
let rightInset: CGFloat = 16.0 + params.rightInset + (item.infoAction != nil ? 48.0 : 0.0)
|
||||
let verticalInset: CGFloat = addressAttributedString.string.isEmpty ? 14.0 : 8.0
|
||||
let iconSize: CGFloat = 40.0
|
||||
|
||||
@ -179,6 +240,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
insets.top = firstWithHeader ? 29.0 : 0.0
|
||||
insets.bottom = 0.0
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
@ -193,7 +255,8 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.layoutParams = (item, params, neighbors)
|
||||
strongSelf.item = item
|
||||
strongSelf.layoutParams = (item, params, neighbors, firstWithHeader, last)
|
||||
|
||||
strongSelf.accessibilityLabel = titleAttributedString.string
|
||||
strongSelf.accessibilityValue = addressAttributedString.string
|
||||
@ -203,6 +266,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.infoButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoIcon"), color: item.presentationData.theme.list.itemAccentColor), for: .normal)
|
||||
}
|
||||
|
||||
let transition = ContainedViewLayoutTransition.immediate
|
||||
@ -239,7 +303,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
stripeInset = leftInset
|
||||
}
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: stripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - stripeInset, height: separatorHeight))
|
||||
strongSelf.bottomStripeNode.isHidden = false
|
||||
strongSelf.bottomStripeNode.isHidden = last
|
||||
case .blocks:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
@ -287,6 +351,9 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
transition.updateFrame(node: strongSelf.iconNode, frame: CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: floorToScreenPixels((layout.contentSize.height - iconSize) / 2.0)), size: CGSize(width: iconSize, height: iconSize)))
|
||||
|
||||
transition.updateFrame(node: strongSelf.infoButton, frame: CGRect(x: layout.contentSize.width - params.rightInset - 60.0, y: 0.0, width: 60.0, height: layout.contentSize.height))
|
||||
strongSelf.infoButton.isHidden = item.infoAction == nil
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
}
|
||||
})
|
||||
@ -338,4 +405,12 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
@objc private func infoPressed() {
|
||||
self.item?.infoAction?()
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
return self.item?.header
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
if (_cameraView)
|
||||
[_collectionView addSubview:_cameraView];
|
||||
|
||||
_sendMediaItemView = [[TGMenuSheetButtonItemView alloc] initWithTitle:nil type:TGMenuSheetButtonTypeSend action:^
|
||||
_sendMediaItemView = [[TGMenuSheetButtonItemView alloc] initWithTitle:nil type:TGMenuSheetButtonTypeSend fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && strongSelf.sendPressed != nil)
|
||||
@ -272,7 +272,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
|
||||
if (!_document)
|
||||
{
|
||||
_sendFileItemView = [[TGMenuSheetButtonItemView alloc] initWithTitle:nil type:TGMenuSheetButtonTypeDefault action:^
|
||||
_sendFileItemView = [[TGMenuSheetButtonItemView alloc] initWithTitle:nil type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && strongSelf.sendPressed != nil)
|
||||
|
@ -1050,7 +1050,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
|
||||
NSArray *items = @
|
||||
[
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Camera.Discard") type:TGMenuSheetButtonTypeDefault action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Camera.Discard") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -1063,7 +1063,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
[strongController dismissAnimated:true manual:false completion:nil];
|
||||
[strongSelf beginTransitionOutWithVelocity:0.0f];
|
||||
}],
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -64,7 +64,7 @@
|
||||
sendTitle = [NSString stringWithFormat:format, [NSString stringWithFormat:@"%ld", photosCount]];
|
||||
}
|
||||
|
||||
TGMenuSheetButtonItemView *sendItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:sendTitle type:TGMenuSheetButtonTypeSend action:^
|
||||
TGMenuSheetButtonItemView *sendItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:sendTitle type:TGMenuSheetButtonTypeSend fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGClipboardPreviewItemView *strongPreviewItem = weakPreviewItem;
|
||||
completed(strongPreviewItem.selectionContext, strongPreviewItem.editingContext, nil);
|
||||
@ -90,7 +90,7 @@
|
||||
[strongPreviewItem setCollapsed:count == 0 animated:true];
|
||||
};
|
||||
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
[strongController dismissAnimated:true];
|
||||
|
@ -167,12 +167,14 @@ const CGFloat TGLocationInfoCellHeight = 134.0f;
|
||||
|
||||
_titleLabel.text = location.venue.title.length > 0 ? location.venue.title : TGLocalized(@"Map.Location");
|
||||
|
||||
UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor];
|
||||
if (color != nil) {
|
||||
[_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], color)];
|
||||
pinColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
if (location.venue.type.length > 0 && [location.venue.provider isEqualToString:@"foursquare"])
|
||||
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 48, 48, TGColorHexCode(_pallete != nil ? _pallete.iconColor : [UIColor whiteColor])] withOptions:nil];
|
||||
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 48, 48, TGColorHexCode(pinColor)] withOptions:nil];
|
||||
|
||||
SSignal *addressSignal = [SSignal single:@""];
|
||||
if (location.venue.address.length > 0)
|
||||
|
@ -23,7 +23,7 @@
|
||||
{
|
||||
bool isUser = [peer isKindOfClass:[TGUser class]];
|
||||
NSString *title = isUser ? ((TGUser *)peer).displayName : ((TGConversation *)peer).chatTitle;
|
||||
self = [super initWithTitle:@"" type:TGMenuSheetButtonTypeDefault action:action];
|
||||
self = [super initWithTitle:@"" type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:action];
|
||||
if (self != nil)
|
||||
{
|
||||
_label = [[UILabel alloc] init];
|
||||
|
@ -491,7 +491,7 @@ const CGFloat TGLocationMapInset = 100.0f;
|
||||
[itemViews addObject:titleItem];
|
||||
|
||||
__weak TGMenuSheetController *weakController = controller;
|
||||
TGMenuSheetButtonItemView *for15MinutesItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor15Minutes") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *for15MinutesItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor15Minutes") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGLocationMapViewController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -508,7 +508,7 @@ const CGFloat TGLocationMapInset = 100.0f;
|
||||
}];
|
||||
[itemViews addObject:for15MinutesItem];
|
||||
|
||||
TGMenuSheetButtonItemView *for1HourItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor1Hour") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *for1HourItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor1Hour") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGLocationMapViewController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -525,7 +525,7 @@ const CGFloat TGLocationMapInset = 100.0f;
|
||||
}];
|
||||
[itemViews addObject:for1HourItem];
|
||||
|
||||
TGMenuSheetButtonItemView *for8HoursItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor8Hours") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *for8HoursItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor8Hours") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGLocationMapViewController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -542,7 +542,7 @@ const CGFloat TGLocationMapInset = 100.0f;
|
||||
}];
|
||||
[itemViews addObject:for8HoursItem];
|
||||
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
|
@ -266,14 +266,16 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
|
||||
_iconView.hidden = false;
|
||||
|
||||
UIColor *color = _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2);
|
||||
UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor];
|
||||
if (locationAnnotation.color != nil) {
|
||||
color = locationAnnotation.color;
|
||||
pinColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
_backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), color);
|
||||
if (location.venue.type.length > 0)
|
||||
{
|
||||
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 64, 64, TGColorHexCode(_pallete != nil ? _pallete.iconColor : [UIColor whiteColor])] withOptions:nil];
|
||||
[_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 64, 64, TGColorHexCode(pinColor)] withOptions:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -742,7 +742,7 @@
|
||||
NSMutableArray *itemViews = [[NSMutableArray alloc] init];
|
||||
|
||||
__weak TGMenuSheetController *weakController = controller;
|
||||
TGMenuSheetButtonItemView *openItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.OpenInMaps") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *openItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.OpenInMaps") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGLocationViewController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -757,7 +757,7 @@
|
||||
}];
|
||||
[itemViews addObject:openItem];
|
||||
|
||||
TGMenuSheetButtonItemView *shareItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Conversation.ContextMenuShare") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *shareItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Conversation.ContextMenuShare") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -770,7 +770,7 @@
|
||||
}];
|
||||
[itemViews addObject:shareItem];
|
||||
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -870,7 +870,7 @@
|
||||
__weak TGMenuSheetController *weakController = controller;
|
||||
NSArray *items = @
|
||||
[
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.GetDirections") type:TGMenuSheetButtonTypeDefault action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.GetDirections") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -879,7 +879,7 @@
|
||||
[strongController dismissAnimated:true];
|
||||
block();
|
||||
}],
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -128,7 +128,7 @@
|
||||
};
|
||||
[itemViews addObject:carouselItem];
|
||||
|
||||
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.ChoosePhoto") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.ChoosePhoto") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -145,7 +145,7 @@
|
||||
|
||||
if (_hasSearchButton)
|
||||
{
|
||||
TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"AttachmentMenu.WebSearch") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"AttachmentMenu.WebSearch") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -164,7 +164,7 @@
|
||||
|
||||
if (_hasViewButton)
|
||||
{
|
||||
TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Settings.ViewPhoto") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Settings.ViewPhoto") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -182,7 +182,7 @@
|
||||
|
||||
if (_hasDeleteButton)
|
||||
{
|
||||
TGMenuSheetButtonItemView *deleteItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"GroupInfo.SetGroupPhotoDelete") type:TGMenuSheetButtonTypeDestructive action:^
|
||||
TGMenuSheetButtonItemView *deleteItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"GroupInfo.SetGroupPhotoDelete") type:TGMenuSheetButtonTypeDestructive fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -198,7 +198,7 @@
|
||||
[itemViews addObject:deleteItem];
|
||||
}
|
||||
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
|
@ -609,7 +609,7 @@
|
||||
|
||||
NSArray *items = @
|
||||
[
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Camera.Discard") type:TGMenuSheetButtonTypeDefault action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Camera.Discard") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -624,7 +624,7 @@
|
||||
|
||||
[strongController dismissAnimated:true manual:false completion:nil];
|
||||
}],
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -21,7 +21,7 @@ typedef enum
|
||||
@property (nonatomic, copy) void (^action)(void);
|
||||
@property (nonatomic, assign) bool thickDivider;
|
||||
|
||||
- (instancetype)initWithTitle:(NSString *)title type:(TGMenuSheetButtonType)type action:(void (^)(void))action;
|
||||
- (instancetype)initWithTitle:(NSString *)title type:(TGMenuSheetButtonType)type fontSize:(CGFloat)fontSize action:(void (^)(void))action;
|
||||
|
||||
@property (nonatomic, assign) bool collapsed;
|
||||
- (void)setCollapsed:(bool)collapsed animated:(bool)animated;
|
||||
|
@ -16,6 +16,7 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
|
||||
bool _dark;
|
||||
bool _requiresDivider;
|
||||
UIView *_customDivider;
|
||||
CGFloat _fontSize;
|
||||
|
||||
TGMenuSheetPallete *_pallete;
|
||||
}
|
||||
@ -23,12 +24,13 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
|
||||
|
||||
@implementation TGMenuSheetButtonItemView
|
||||
|
||||
- (instancetype)initWithTitle:(NSString *)title type:(TGMenuSheetButtonType)type action:(void (^)(void))action
|
||||
- (instancetype)initWithTitle:(NSString *)title type:(TGMenuSheetButtonType)type fontSize:(CGFloat)fontSize action:(void (^)(void))action
|
||||
{
|
||||
self = [super initWithType:(type == TGMenuSheetButtonTypeCancel) ? TGMenuSheetItemTypeFooter : TGMenuSheetItemTypeDefault];
|
||||
if (self != nil)
|
||||
{
|
||||
self.action = action;
|
||||
_fontSize = fontSize;
|
||||
_buttonType = type;
|
||||
_requiresDivider = true;
|
||||
|
||||
@ -115,7 +117,7 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
|
||||
|
||||
- (void)_updateForType:(TGMenuSheetButtonType)type
|
||||
{
|
||||
_button.titleLabel.font = (type == TGMenuSheetButtonTypeCancel || type == TGMenuSheetButtonTypeSend) ? TGMediumSystemFontOfSize(20) : TGSystemFontOfSize(20);
|
||||
_button.titleLabel.font = (type == TGMenuSheetButtonTypeCancel || type == TGMenuSheetButtonTypeSend) ? TGMediumSystemFontOfSize(_fontSize) : TGSystemFontOfSize(_fontSize);
|
||||
UIColor *accentColor = _dark ? UIColorRGB(0x4fbcff) : TGAccentColor();
|
||||
if (_pallete != nil)
|
||||
accentColor = _pallete.accentColor;
|
||||
|
@ -84,7 +84,7 @@
|
||||
};
|
||||
[itemViews addObject:carouselItem];
|
||||
|
||||
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.ChoosePhoto") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.ChoosePhoto") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -101,7 +101,7 @@
|
||||
|
||||
if (iosMajorVersion() >= 8 && intent != TGPassportAttachIntentSelfie)
|
||||
{
|
||||
TGMenuSheetButtonItemView *icloudItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Conversation.FileICloudDrive") type:TGMenuSheetButtonTypeDefault action:^
|
||||
TGMenuSheetButtonItemView *icloudItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Conversation.FileICloudDrive") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -124,7 +124,7 @@
|
||||
}
|
||||
carouselItem.remainingHeight = TGMenuSheetButtonItemViewHeight * (itemViews.count - 1);
|
||||
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
|
@ -625,8 +625,8 @@ NSString * const TGPhotoCropOriginalAspectRatio = @"original";
|
||||
};
|
||||
|
||||
NSMutableArray *items = [[NSMutableArray alloc] init];
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioOriginal") type:TGMenuSheetButtonTypeDefault action:^{ action(TGPhotoCropOriginalAspectRatio); }]];
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioSquare") type:TGMenuSheetButtonTypeDefault action:^{ action(@"1.0"); }]];
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioOriginal") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^{ action(TGPhotoCropOriginalAspectRatio); }]];
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioSquare") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^{ action(@"1.0"); }]];
|
||||
|
||||
CGSize croppedImageSize = _cropView.cropRect.size;
|
||||
if (_cropView.cropOrientation == UIImageOrientationLeft || _cropView.cropOrientation == UIImageOrientationRight)
|
||||
@ -666,10 +666,10 @@ NSString * const TGPhotoCropOriginalAspectRatio = @"original";
|
||||
|
||||
ratio = heightComponent / widthComponent;
|
||||
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:[NSString stringWithFormat:@"%d:%d", (int)widthComponent, (int)heightComponent] type:TGMenuSheetButtonTypeDefault action:^{ action([NSString stringWithFormat:@"%f", ratio]); }]];
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:[NSString stringWithFormat:@"%d:%d", (int)widthComponent, (int)heightComponent] type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^{ action([NSString stringWithFormat:@"%f", ratio]); }]];
|
||||
}
|
||||
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -1341,7 +1341,7 @@
|
||||
|
||||
NSArray *items = @
|
||||
[
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.DiscardChanges") type:TGMenuSheetButtonTypeDefault action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.DiscardChanges") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -1352,7 +1352,7 @@
|
||||
dismiss();
|
||||
}];
|
||||
}],
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -550,7 +550,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
__weak TGPhotoPaintController *weakSelf = self;
|
||||
NSArray *items = @
|
||||
[
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Paint.ClearConfirm") type:TGMenuSheetButtonTypeDestructive action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Paint.ClearConfirm") type:TGMenuSheetButtonTypeDestructive fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
@ -570,7 +570,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
|
||||
|
||||
[strongController dismissAnimated:true manual:false completion:nil];
|
||||
}],
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel action:^
|
||||
[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController != nil)
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
__weak TGMenuSheetController *weakController = controller;
|
||||
__weak TGSecretTimerPickerItemView *weakTimerItem = timerItem;
|
||||
TGMenuSheetButtonItemView *doneItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Done") type:TGMenuSheetButtonTypeSend action:^
|
||||
TGMenuSheetButtonItemView *doneItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Done") type:TGMenuSheetButtonTypeSend fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGSecretTimerPickerItemView *strongTimerItem = weakTimerItem;
|
||||
if (strongTimerItem != nil)
|
||||
|
@ -22,6 +22,8 @@ public struct LegacyAttachmentMenuMediaEditing: OptionSet {
|
||||
}
|
||||
|
||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void) -> TGMenuSheetController {
|
||||
let actionSheetTheme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let controller = TGMenuSheetController(context: parentController.context, dark: false)!
|
||||
@ -99,7 +101,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
carouselItem.editingContext.setInitialCaption(initialCaption, entities: [])
|
||||
itemViews.append(carouselItem)
|
||||
|
||||
let galleryItem = TGMenuSheetButtonItemView(title: editing ? presentationData.strings.Conversation_EditingMessageMediaChange : presentationData.strings.AttachmentMenu_PhotoOrVideo, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||
let galleryItem = TGMenuSheetButtonItemView(title: editing ? presentationData.strings.Conversation_EditingMessageMediaChange : presentationData.strings.AttachmentMenu_PhotoOrVideo, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openGallery()
|
||||
})!
|
||||
@ -117,7 +119,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
}
|
||||
|
||||
if !editing {
|
||||
let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, action: {[weak controller] in
|
||||
let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: {[weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openFileGallery()
|
||||
})!
|
||||
@ -126,7 +128,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
}
|
||||
|
||||
if canEditCurrent {
|
||||
let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, action: {[weak controller] in
|
||||
let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: {[weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openFileGallery()
|
||||
})!
|
||||
@ -134,21 +136,21 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
}
|
||||
|
||||
if editMediaOptions == nil {
|
||||
let locationItem = TGMenuSheetButtonItemView(title: presentationData.strings.Conversation_Location, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||
let locationItem = TGMenuSheetButtonItemView(title: presentationData.strings.Conversation_Location, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openMap()
|
||||
})!
|
||||
itemViews.append(locationItem)
|
||||
|
||||
if (peer is TelegramGroup || peer is TelegramChannel) && canSendMessagesToPeer(peer) && canSendPolls {
|
||||
let pollItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_Poll, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||
let pollItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_Poll, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openPoll()
|
||||
})!
|
||||
itemViews.append(pollItem)
|
||||
}
|
||||
|
||||
let contactItem = TGMenuSheetButtonItemView(title: presentationData.strings.Conversation_Contact, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||
let contactItem = TGMenuSheetButtonItemView(title: presentationData.strings.Conversation_Contact, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openContacts()
|
||||
})!
|
||||
@ -162,7 +164,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
let peer = recentlyUsedInlineBots[i]
|
||||
let addressName = peer.addressName
|
||||
if let addressName = addressName {
|
||||
let botItem = TGMenuSheetButtonItemView(title: "@" + addressName, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||
let botItem = TGMenuSheetButtonItemView(title: "@" + addressName, type: TGMenuSheetButtonTypeDefault, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
|
||||
selectRecentlyUsedInlineBot(peer)
|
||||
@ -175,7 +177,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
|
||||
carouselItemView?.remainingHeight = TGMenuSheetButtonItemViewHeight * CGFloat(itemViews.count - 1)
|
||||
|
||||
let cancelItem = TGMenuSheetButtonItemView(title: presentationData.strings.Common_Cancel, type: TGMenuSheetButtonTypeCancel, action: { [weak controller] in
|
||||
let cancelItem = TGMenuSheetButtonItemView(title: presentationData.strings.Common_Cancel, type: TGMenuSheetButtonTypeCancel, fontSize: actionSheetTheme.baseFontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
})!
|
||||
itemViews.append(cancelItem)
|
||||
|
@ -134,9 +134,14 @@ private let venueColors: [String: UIColor] = [
|
||||
"parks_outdoors": UIColor(rgb: 0x6cc039),
|
||||
"shops": UIColor(rgb: 0xffb300),
|
||||
"travel": UIColor(rgb: 0x1c9fff),
|
||||
"work": UIColor(rgb: 0xad7854),
|
||||
"home": UIColor(rgb: 0x00aeef)
|
||||
]
|
||||
|
||||
public func venueIconColor(type: String) -> UIColor {
|
||||
if type.isEmpty {
|
||||
return UIColor(rgb: 0x008df2)
|
||||
}
|
||||
if let color = venueColors[type] {
|
||||
return color
|
||||
}
|
||||
@ -150,7 +155,8 @@ public func venueIconColor(type: String) -> UIColor {
|
||||
}
|
||||
|
||||
public func venueIcon(postbox: Postbox, type: String, background: Bool) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
let data: Signal<Data?, NoError> = type.isEmpty ? .single(nil) : venueIconData(postbox: postbox, resource: VenueIconResource(type: type))
|
||||
let isBuiltinIcon = ["", "home", "work"].contains(type)
|
||||
let data: Signal<Data?, NoError> = isBuiltinIcon ? .single(nil) : venueIconData(postbox: postbox, resource: VenueIconResource(type: type))
|
||||
return data |> map { data in
|
||||
return { arguments in
|
||||
let context = DrawingContext(size: arguments.drawingSize, clear: true)
|
||||
@ -172,8 +178,21 @@ public func venueIcon(postbox: Postbox, type: String, background: Bool) -> Signa
|
||||
let boundsSize = CGSize(width: arguments.drawingRect.size.width - 4.0 * 2.0, height: arguments.drawingRect.size.height - 4.0 * 2.0)
|
||||
let fittedSize = image.size.aspectFitted(boundsSize)
|
||||
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.width - fittedSize.width) / 2.0), y: floor((arguments.drawingRect.height - fittedSize.height) / 2.0)), size: fittedSize))
|
||||
} else if type.isEmpty, let pinImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/LocationPinForeground"), color: foregroundColor), let cgImage = pinImage.cgImage {
|
||||
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.width - pinImage.size.width) / 2.0), y: floor((arguments.drawingRect.height - pinImage.size.height) / 2.0)), size: pinImage.size))
|
||||
} else if isBuiltinIcon {
|
||||
let image: UIImage?
|
||||
switch type {
|
||||
case "":
|
||||
image = UIImage(bundleImageName: "Chat/Message/LocationPinForeground")
|
||||
case "home":
|
||||
image = UIImage(bundleImageName: "Location/HomeIcon")
|
||||
case "work":
|
||||
image = UIImage(bundleImageName: "Location/WorkIcon")
|
||||
default:
|
||||
image = nil
|
||||
}
|
||||
if let image = image, let pinImage = generateTintedImage(image: image, color: foregroundColor), let cgImage = pinImage.cgImage {
|
||||
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.width - pinImage.size.width) / 2.0), y: floor((arguments.drawingRect.height - pinImage.size.height) / 2.0)), size: pinImage.size))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,9 @@ static_library(
|
||||
"//submodules/MergeLists:MergeLists",
|
||||
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
|
||||
"//submodules/SearchBarNode:SearchBarNode",
|
||||
"//submodules/PresentationDataUtils:PresentationDataUtils",
|
||||
"//submodules/DeviceAccess:DeviceAccess",
|
||||
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
|
||||
],
|
||||
frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
|
@ -80,6 +80,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
let smallIconNode: TransformImageNode
|
||||
let dotNode: ASImageNode
|
||||
var avatarNode: AvatarNode?
|
||||
var labelNode: ImmediateTextNode?
|
||||
|
||||
var appeared = false
|
||||
var animating = false
|
||||
@ -226,6 +227,29 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
|
||||
self.dotNode.alpha = 1.0
|
||||
self.dotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
|
||||
|
||||
if let annotation = self.annotation as? LocationPinAnnotation, let venue = annotation.location?.venue {
|
||||
let labelNode = ImmediateTextNode()
|
||||
labelNode.displaysAsynchronously = false
|
||||
labelNode.isUserInteractionEnabled = false
|
||||
labelNode.attributedText = NSAttributedString(string: venue.title, font: Font.medium(10), textColor: .black)
|
||||
labelNode.maximumNumberOfLines = 2
|
||||
labelNode.textAlignment = .center
|
||||
labelNode.truncationType = .end
|
||||
labelNode.textStroke = (UIColor.white, 1.0)
|
||||
self.labelNode = labelNode
|
||||
self.addSubnode(labelNode)
|
||||
|
||||
let size = labelNode.updateLayout(CGSize(width: 120.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
labelNode.bounds = CGRect(origin: CGPoint(), size: size)
|
||||
labelNode.position = CGPoint(x: 0.0, y: 10.0)
|
||||
|
||||
labelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
} else {
|
||||
self.labelNode?.removeFromSupernode()
|
||||
self.labelNode = nil
|
||||
}
|
||||
} else {
|
||||
let avatarSnapshot = self.avatarNode?.view.snapshotContentTree()
|
||||
if let avatarSnapshot = avatarSnapshot, let avatarNode = self.avatarNode {
|
||||
@ -268,6 +292,13 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
let previousAlpha = self.dotNode.alpha
|
||||
self.dotNode.alpha = 0.0
|
||||
self.dotNode.layer.animateAlpha(from: previousAlpha, to: 0.0, duration: 0.2)
|
||||
|
||||
if let labelNode = self.labelNode {
|
||||
self.labelNode = nil
|
||||
labelNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
|
||||
labelNode.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.smallNode.isHidden = selected
|
||||
@ -279,50 +310,13 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
guard !self.animating else {
|
||||
return
|
||||
}
|
||||
|
||||
self.dotNode.position = CGPoint()
|
||||
self.smallNode.position = CGPoint()
|
||||
self.shadowNode.position = CGPoint(x: UIScreenPixel, y: -36.0)
|
||||
self.backgroundNode.position = CGPoint(x: self.shadowNode.frame.width / 2.0, y: self.shadowNode.frame.height / 2.0)
|
||||
self.iconNode.position = CGPoint(x: self.shadowNode.frame.width / 2.0, y: self.shadowNode.frame.height / 2.0 - 5.0)
|
||||
|
||||
let smallIconLayout = self.smallIconNode.asyncLayout()
|
||||
let smallIconApply = smallIconLayout(TransformImageArguments(corners: ImageCorners(), imageSize: self.smallIconNode.bounds.size, boundingSize: self.smallIconNode.bounds.size, intrinsicInsets: UIEdgeInsets()))
|
||||
smallIconApply()
|
||||
|
||||
let iconLayout = self.iconNode.asyncLayout()
|
||||
let iconApply = iconLayout(TransformImageArguments(corners: ImageCorners(), imageSize: self.iconNode.bounds.size, boundingSize: self.iconNode.bounds.size, intrinsicInsets: UIEdgeInsets()))
|
||||
iconApply()
|
||||
|
||||
if let avatarNode = self.avatarNode {
|
||||
avatarNode.position = self.isSelected ? CGPoint(x: UIScreenPixel, y: -41.0) : CGPoint()
|
||||
avatarNode.transform = self.isSelected ? CATransform3DIdentity : CATransform3DMakeScale(0.64, 0.64, 1.0)
|
||||
avatarNode.view.superview?.bringSubviewToFront(avatarNode.view)
|
||||
}
|
||||
|
||||
if !self.appeared {
|
||||
self.appeared = true
|
||||
|
||||
self.smallNode.transform = CATransform3DMakeScale(0.1, 0.1, 1.0)
|
||||
UIView.animate(withDuration: 0.55, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.5, options: [], animations: {
|
||||
self.smallNode.transform = CATransform3DIdentity
|
||||
}) { _ in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setPeer(account: Account, theme: PresentationTheme, peer: Peer) {
|
||||
let avatarNode: AvatarNode
|
||||
if let currentAvatarNode = self.avatarNode {
|
||||
avatarNode = currentAvatarNode
|
||||
} else {
|
||||
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 24.0))
|
||||
avatarNode.isLayerBacked = false
|
||||
avatarNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 55.0, height: 55.0))
|
||||
avatarNode.position = CGPoint()
|
||||
self.avatarNode = avatarNode
|
||||
@ -332,19 +326,23 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
avatarNode.setPeer(account: account, theme: theme, peer: peer)
|
||||
}
|
||||
|
||||
private var raised = false
|
||||
var isRaised = false
|
||||
func setRaised(_ raised: Bool, animated: Bool, completion: @escaping () -> Void = {}) {
|
||||
guard raised != self.raised else {
|
||||
guard raised != self.isRaised else {
|
||||
return
|
||||
}
|
||||
|
||||
self.raised = raised
|
||||
self.isRaised = raised
|
||||
self.shadowNode.layer.removeAllAnimations()
|
||||
|
||||
if animated {
|
||||
self.animating = true
|
||||
|
||||
if raised {
|
||||
let previousPosition = self.shadowNode.position
|
||||
self.shadowNode.layer.animatePosition(from: previousPosition, to: CGPoint(x: UIScreenPixel, y: -66.0), duration: 0.2, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring) { finished in
|
||||
self.shadowNode.position = CGPoint(x: UIScreenPixel, y: -66.0)
|
||||
self.shadowNode.layer.animatePosition(from: previousPosition, to: self.shadowNode.position, duration: 0.2, delay: 0.0, timingFunction: kCAMediaTimingFunctionSpring) { finished in
|
||||
self.animating = false
|
||||
if finished {
|
||||
completion()
|
||||
}
|
||||
@ -353,6 +351,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
UIView.animate(withDuration: 0.2, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.0, options: [.allowAnimatedContent], animations: {
|
||||
self.shadowNode.position = CGPoint(x: UIScreenPixel, y: -36.0)
|
||||
}) { finished in
|
||||
self.animating = false
|
||||
if finished {
|
||||
completion()
|
||||
}
|
||||
@ -396,7 +395,6 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
self.addSubnode(avatarNode)
|
||||
}
|
||||
self.animating = false
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,4 +403,42 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
|
||||
self.dotNode.isHidden = !custom
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
guard !self.animating else {
|
||||
return
|
||||
}
|
||||
|
||||
self.dotNode.position = CGPoint()
|
||||
self.smallNode.position = CGPoint()
|
||||
self.shadowNode.position = CGPoint(x: UIScreenPixel, y: self.isRaised ? -66.0 : -36.0)
|
||||
self.backgroundNode.position = CGPoint(x: self.shadowNode.frame.width / 2.0, y: self.shadowNode.frame.height / 2.0)
|
||||
self.iconNode.position = CGPoint(x: self.shadowNode.frame.width / 2.0, y: self.shadowNode.frame.height / 2.0 - 5.0)
|
||||
|
||||
let smallIconLayout = self.smallIconNode.asyncLayout()
|
||||
let smallIconApply = smallIconLayout(TransformImageArguments(corners: ImageCorners(), imageSize: self.smallIconNode.bounds.size, boundingSize: self.smallIconNode.bounds.size, intrinsicInsets: UIEdgeInsets()))
|
||||
smallIconApply()
|
||||
|
||||
let iconLayout = self.iconNode.asyncLayout()
|
||||
let iconApply = iconLayout(TransformImageArguments(corners: ImageCorners(), imageSize: self.iconNode.bounds.size, boundingSize: self.iconNode.bounds.size, intrinsicInsets: UIEdgeInsets()))
|
||||
iconApply()
|
||||
|
||||
if let avatarNode = self.avatarNode {
|
||||
avatarNode.position = self.isSelected ? CGPoint(x: UIScreenPixel, y: -41.0) : CGPoint()
|
||||
avatarNode.transform = self.isSelected ? CATransform3DIdentity : CATransform3DMakeScale(0.64, 0.64, 1.0)
|
||||
avatarNode.view.superview?.bringSubviewToFront(avatarNode.view)
|
||||
}
|
||||
|
||||
if !self.appeared {
|
||||
self.appeared = true
|
||||
|
||||
self.smallNode.transform = CATransform3DMakeScale(0.1, 0.1, 1.0)
|
||||
UIView.animate(withDuration: 0.55, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.5, options: [], animations: {
|
||||
self.smallNode.transform = CATransform3DIdentity
|
||||
}) { _ in
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,19 +100,21 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
self.shadowNode.image = generateShadowImage(theme: presentationData.theme, highlighted: false)
|
||||
}
|
||||
|
||||
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, padding: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
transition.updateFrame(node: self.mapNode, frame: CGRect(x: 0.0, y: floorToScreenPixels((size.height - layout.size.height + navigationBarHeight) / 2.0), width: size.width, height: layout.size.height))
|
||||
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
let mapHeight: CGFloat = floor(layout.size.height * 1.5)
|
||||
let mapFrame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - mapHeight + navigationBarHeight) / 2.0) + offset, width: size.width, height: mapHeight)
|
||||
transition.updateFrame(node: self.mapNode, frame: mapFrame)
|
||||
self.mapNode.updateLayout(size: mapFrame.size)
|
||||
|
||||
transition.updateFrame(node: self.shadowNode, frame: CGRect(x: 0.0, y: size.height - 14.0, width: size.width, height: 14.0))
|
||||
|
||||
let inset: CGFloat = 6.0
|
||||
transition.updateFrame(node: self.optionsBackgroundNode, frame: CGRect(x: size.width - inset - panelSize.width - panelInset * 2.0, y: navigationBarHeight + padding + inset, width: panelSize.width + panelInset * 2.0, height: panelSize.height + panelInset * 2.0))
|
||||
|
||||
transition.updateFrame(node: self.optionsBackgroundNode, frame: CGRect(x: size.width - inset - panelSize.width - panelInset * 2.0, y: navigationBarHeight + topPadding + inset, width: panelSize.width + panelInset * 2.0, height: panelSize.height + panelInset * 2.0))
|
||||
transition.updateFrame(node: self.infoButtonNode, frame: CGRect(x: panelInset, y: panelInset, width: panelSize.width, height: panelSize.height / 2.0))
|
||||
transition.updateFrame(node: self.locationButtonNode, frame: CGRect(x: panelInset, y: panelInset + panelSize.height / 2.0, width: panelSize.width, height: panelSize.height / 2.0))
|
||||
|
||||
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||
let optionsAlpha: CGFloat = size.height > 124.0 + navigationBarHeight ? 1.0 : 0.0
|
||||
let optionsAlpha: CGFloat = size.height > 160.0 + navigationBarHeight ? 1.0 : 0.0
|
||||
alphaTransition.updateAlpha(node: self.optionsBackgroundNode, alpha: optionsAlpha)
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,13 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
private let pickerAnnotationContainerView: PickerAnnotationContainerView
|
||||
private weak var userLocationAnnotationView: MKAnnotationView?
|
||||
|
||||
private let pinDisposable = MetaDisposable()
|
||||
|
||||
private var mapView: MKMapView? {
|
||||
return self.view as? MKMapView
|
||||
}
|
||||
|
||||
var returnedToUserLocation = true
|
||||
var ignoreRegionChanges = false
|
||||
var isDragging = false
|
||||
var beganInteractiveDragging: (() -> Void)?
|
||||
@ -101,6 +104,11 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.mapView?.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: offset.y, left: offset.x, bottom: 0.0, right: 0.0), animated: animated)
|
||||
}
|
||||
self.ignoreRegionChanges = false
|
||||
|
||||
if isUserLocation && !self.returnedToUserLocation {
|
||||
self.returnedToUserLocation = true
|
||||
self.pickerAnnotationView?.setRaised(true, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
|
||||
@ -111,13 +119,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
for gestureRecognizer in gestureRecognizers {
|
||||
if gestureRecognizer.state == .began || gestureRecognizer.state == .ended {
|
||||
self.isDragging = true
|
||||
self.returnedToUserLocation = false
|
||||
self.beganInteractiveDragging?()
|
||||
|
||||
if self.hasPickerAnnotation {
|
||||
self.customUserLocationAnnotationView?.isHidden = true
|
||||
self.pickerAnnotationContainerView.isHidden = false
|
||||
self.pickerAnnotationView?.setCustom(true, animated: true)
|
||||
if let pickerAnnotationView = self.pickerAnnotationView, !pickerAnnotationView.isRaised {
|
||||
pickerAnnotationView.setCustom(true, animated: true)
|
||||
pickerAnnotationView.setRaised(true, animated: true)
|
||||
}
|
||||
self.resetAnnotationSelection()
|
||||
self.resetScheduledPin()
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -125,9 +138,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
|
||||
if self.isDragging, let coordinate = self.mapCenterCoordinate {
|
||||
let wasDragging = self.isDragging
|
||||
if self.isDragging {
|
||||
self.isDragging = false
|
||||
self.endedInteractiveDragging?(coordinate)
|
||||
if let coordinate = self.mapCenterCoordinate {
|
||||
self.endedInteractiveDragging?(coordinate)
|
||||
}
|
||||
}
|
||||
|
||||
if let pickerAnnotationView = self.pickerAnnotationView {
|
||||
if pickerAnnotationView.isRaised && (wasDragging || self.returnedToUserLocation) {
|
||||
self.schedulePin(wasDragging: wasDragging)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,12 +315,41 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.pickerAnnotationContainerView.frame = CGRect(x: 0.0, y: floorToScreenPixels((self.frame.size.height - self.frame.size.width) / 2.0), width: self.frame.size.width, height: self.frame.size.width)
|
||||
private func schedulePin(wasDragging: Bool) {
|
||||
let timeout: Double = wasDragging ? 0.38 : 0.05
|
||||
|
||||
let signal: Signal<Never, NoError> = .complete()
|
||||
|> delay(timeout, queue: Queue.mainQueue())
|
||||
self.pinDisposable.set(signal.start(completed: { [weak self] in
|
||||
guard let strongSelf = self, let pickerAnnotationView = strongSelf.pickerAnnotationView else {
|
||||
return
|
||||
}
|
||||
|
||||
pickerAnnotationView.setRaised(false, animated: true) { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if strongSelf.returnedToUserLocation {
|
||||
strongSelf.pickerAnnotationContainerView.isHidden = true
|
||||
strongSelf.customUserLocationAnnotationView?.isHidden = false
|
||||
}
|
||||
}
|
||||
|
||||
if strongSelf.returnedToUserLocation {
|
||||
pickerAnnotationView.setCustom(false, animated: true)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
private func resetScheduledPin() {
|
||||
self.pinDisposable.set(nil)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
self.pickerAnnotationContainerView.frame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - size.width) / 2.0), width: size.width, height: size.width)
|
||||
if let pickerAnnotationView = self.pickerAnnotationView {
|
||||
pickerAnnotationView.center = CGPoint(x: self.pickerAnnotationContainerView.frame.width / 2.0, y: self.pickerAnnotationContainerView.frame.height / 2.0 + 16.0)
|
||||
pickerAnnotationView.center = CGPoint(x: self.pickerAnnotationContainerView.frame.width / 2.0, y: self.pickerAnnotationContainerView.frame.height / 2.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import TelegramPresentationData
|
||||
import AccountContext
|
||||
import AppBundle
|
||||
import CoreLocation
|
||||
import PresentationDataUtils
|
||||
import DeviceAccess
|
||||
|
||||
public enum LocationPickerMode {
|
||||
case share(peer: Peer?, selfPeer: Peer?, hasLiveLocation: Bool)
|
||||
@ -23,24 +25,28 @@ class LocationPickerInteraction {
|
||||
let toggleMapModeSelection: () -> Void
|
||||
let updateMapMode: (LocationMapMode) -> Void
|
||||
let goToUserLocation: () -> Void
|
||||
let goToCoordinate: (CLLocationCoordinate2D) -> Void
|
||||
let openSearch: () -> Void
|
||||
let updateSearchQuery: (String) -> Void
|
||||
let dismissSearch: () -> Void
|
||||
let dismissInput: () -> Void
|
||||
let updateSendActionHighlight: (Bool) -> Void
|
||||
let openHomeWorkInfo: () -> Void
|
||||
|
||||
init(sendLocation: @escaping (CLLocationCoordinate2D) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D) -> Void, sendVenue: @escaping (TelegramMediaMap) -> Void, toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, goToUserLocation: @escaping () -> Void, openSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void, dismissSearch: @escaping () -> Void, dismissInput: @escaping () -> Void, updateSendActionHighlight: @escaping (Bool) -> Void) {
|
||||
init(sendLocation: @escaping (CLLocationCoordinate2D) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D) -> Void, sendVenue: @escaping (TelegramMediaMap) -> Void, toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, goToUserLocation: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, openSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void, dismissSearch: @escaping () -> Void, dismissInput: @escaping () -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, openHomeWorkInfo: @escaping () -> Void) {
|
||||
self.sendLocation = sendLocation
|
||||
self.sendLiveLocation = sendLiveLocation
|
||||
self.sendVenue = sendVenue
|
||||
self.toggleMapModeSelection = toggleMapModeSelection
|
||||
self.updateMapMode = updateMapMode
|
||||
self.goToUserLocation = goToUserLocation
|
||||
self.goToCoordinate = goToCoordinate
|
||||
self.openSearch = openSearch
|
||||
self.updateSearchQuery = updateSearchQuery
|
||||
self.dismissSearch = dismissSearch
|
||||
self.dismissInput = dismissInput
|
||||
self.updateSendActionHighlight = updateSendActionHighlight
|
||||
self.openHomeWorkInfo = openHomeWorkInfo
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +62,10 @@ public final class LocationPickerController: ViewController {
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private var searchNavigationContentNode: LocationSearchNavigationContentNode?
|
||||
private var isSearchingDisposable = MetaDisposable()
|
||||
|
||||
private let locationManager = CLLocationManager()
|
||||
private var permissionDisposable: Disposable?
|
||||
|
||||
private var interaction: LocationPickerInteraction?
|
||||
|
||||
@ -88,6 +98,29 @@ public final class LocationPickerController: ViewController {
|
||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||
})
|
||||
|
||||
self.permissionDisposable = (DeviceAccess.authorizationStatus(subject: .location(.send))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] next in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch next {
|
||||
case .notDetermined:
|
||||
DeviceAccess.authorizeAccess(to: .location(.send), locationManager: strongSelf.locationManager, presentationData: strongSelf.presentationData, present: { c, a in
|
||||
strongSelf.present(c, in: .window(.root), with: a)
|
||||
}, openSettings: {
|
||||
strongSelf.context.sharedContext.applicationBindings.openSettings()
|
||||
})
|
||||
case .denied:
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.forceSelection = true
|
||||
return state
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
let locationWithTimeout: (CLLocationCoordinate2D, Int32?) -> TelegramMediaMap = { coordinate, timeout in
|
||||
return TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, geoPlace: nil, venue: nil, liveBroadcastingTimeout: timeout)
|
||||
}
|
||||
@ -102,7 +135,7 @@ public final class LocationPickerController: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var title = strongSelf.presentationData.strings.Map_LiveLocationGroupDescription
|
||||
if case let .share(peer, _, _) = strongSelf.mode, let receiver = peer {
|
||||
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(receiver.compactDisplayTitle).0
|
||||
@ -143,7 +176,12 @@ public final class LocationPickerController: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
completion(venue, nil)
|
||||
let venueType = venue.venue?.type ?? ""
|
||||
if ["home", "work"].contains(venueType) {
|
||||
completion(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil), nil)
|
||||
} else {
|
||||
completion(venue, nil)
|
||||
}
|
||||
strongSelf.dismiss()
|
||||
}, toggleMapModeSelection: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
@ -174,6 +212,16 @@ public final class LocationPickerController: ViewController {
|
||||
state.selectedLocation = .none
|
||||
return state
|
||||
}
|
||||
}, goToCoordinate: { [weak self] coordinate in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.displayingMapModeOptions = false
|
||||
state.selectedLocation = .location(coordinate, nil)
|
||||
return state
|
||||
}
|
||||
}, openSearch: { [weak self] in
|
||||
guard let strongSelf = self, let interaction = strongSelf.interaction, let navigationBar = strongSelf.navigationBar else {
|
||||
return
|
||||
@ -186,8 +234,15 @@ public final class LocationPickerController: ViewController {
|
||||
let contentNode = LocationSearchNavigationContentNode(presentationData: strongSelf.presentationData, interaction: interaction)
|
||||
strongSelf.searchNavigationContentNode = contentNode
|
||||
navigationBar.setContentNode(contentNode, animated: true)
|
||||
strongSelf.controllerNode.activateSearch(navigationBar: navigationBar)
|
||||
let isSearching = strongSelf.controllerNode.activateSearch(navigationBar: navigationBar)
|
||||
contentNode.activate()
|
||||
|
||||
strongSelf.isSearchingDisposable.set((isSearching
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
if let strongSelf = self, let searchNavigationContentNode = strongSelf.searchNavigationContentNode {
|
||||
searchNavigationContentNode.updateActivity(value)
|
||||
}
|
||||
}))
|
||||
}, updateSearchQuery: { [weak self] query in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -197,6 +252,7 @@ public final class LocationPickerController: ViewController {
|
||||
guard let strongSelf = self, let navigationBar = strongSelf.navigationBar else {
|
||||
return
|
||||
}
|
||||
strongSelf.isSearchingDisposable.set(nil)
|
||||
strongSelf.searchNavigationContentNode?.deactivate()
|
||||
strongSelf.searchNavigationContentNode = nil
|
||||
navigationBar.setContentNode(nil, animated: true)
|
||||
@ -211,6 +267,13 @@ public final class LocationPickerController: ViewController {
|
||||
return
|
||||
}
|
||||
strongSelf.controllerNode.updateSendActionHighlight(highlighted)
|
||||
}, openHomeWorkInfo: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let controller = textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Map_HomeAndWorkTitle, text: strongSelf.presentationData.strings.Map_HomeAndWorkInfo, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})])
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
})
|
||||
|
||||
self.scrollToTop = { [weak self] in
|
||||
@ -218,8 +281,6 @@ public final class LocationPickerController: ViewController {
|
||||
strongSelf.controllerNode.scrollToTop()
|
||||
}
|
||||
}
|
||||
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
@ -228,6 +289,8 @@ public final class LocationPickerController: ViewController {
|
||||
|
||||
deinit {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
self.permissionDisposable?.dispose()
|
||||
self.isSearchingDisposable.dispose()
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
|
@ -151,9 +151,12 @@ private enum LocationPickerEntry: Comparable, Identifiable {
|
||||
case let .header(theme, title):
|
||||
return LocationSectionHeaderItem(presentationData: ItemListPresentationData(presentationData), title: title)
|
||||
case let .venue(theme, venue, _):
|
||||
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: venue, sectionId: 0, style: .plain, action: {
|
||||
let venueType = venue.venue?.type ?? ""
|
||||
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: venue, style: .plain, action: {
|
||||
interaction?.sendVenue(venue)
|
||||
})
|
||||
}, infoAction: ["home", "work"].contains(venueType) ? {
|
||||
interaction?.openHomeWorkInfo()
|
||||
} : nil)
|
||||
case let .attribution(theme):
|
||||
return LocationAttributionItem(presentationData: ItemListPresentationData(presentationData))
|
||||
}
|
||||
@ -220,11 +223,13 @@ struct LocationPickerState {
|
||||
var mapMode: LocationMapMode
|
||||
var displayingMapModeOptions: Bool
|
||||
var selectedLocation: LocationPickerLocation
|
||||
var forceSelection: Bool
|
||||
|
||||
init() {
|
||||
self.mapMode = .map
|
||||
self.displayingMapModeOptions = false
|
||||
self.selectedLocation = .none
|
||||
self.forceSelection = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,10 +420,23 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
strongSelf.headerNode.mapNode.resetAnnotationSelection()
|
||||
case .selecting:
|
||||
strongSelf.headerNode.mapNode.resetAnnotationSelection()
|
||||
case let .location(coordinate, _):
|
||||
var updateMap = false
|
||||
switch previousState.selectedLocation {
|
||||
case .none, .venue:
|
||||
updateMap = true
|
||||
case let .location(previousCoordinate, address):
|
||||
if previousCoordinate != coordinate {
|
||||
updateMap = true
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
if updateMap {
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: coordinate, isUserLocation: false, animated: true)
|
||||
}
|
||||
case let .venue(venue):
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: venue.coordinate, animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let annotations: [LocationPinAnnotation]
|
||||
@ -482,7 +500,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
strongSelf.listOffset = max(0.0, offset)
|
||||
let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(0.0, offset + overlap)))
|
||||
listTransition.updateFrame(node: strongSelf.headerNode, frame: headerFrame)
|
||||
strongSelf.headerNode.updateLayout(layout: layout, navigationBarHeight: navigationBarHeight, padding: strongSelf.state.displayingMapModeOptions ? 38.0 : 0.0, size: headerFrame.size, transition: listTransition)
|
||||
strongSelf.headerNode.updateLayout(layout: layout, navigationBarHeight: navigationBarHeight, topPadding: strongSelf.state.displayingMapModeOptions ? 38.0 : 0.0, offset: 0.0, size: headerFrame.size, transition: listTransition)
|
||||
strongSelf.layoutActivityIndicator(transition: listTransition)
|
||||
}
|
||||
|
||||
@ -590,9 +608,9 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
})
|
||||
}
|
||||
|
||||
func activateSearch(navigationBar: NavigationBar) {
|
||||
func activateSearch(navigationBar: NavigationBar) -> Signal<Bool, NoError> {
|
||||
guard let (layout, navigationBarHeight) = self.validLayout, self.searchContainerNode == nil, let coordinate = self.headerNode.mapNode.mapCenterCoordinate else {
|
||||
return
|
||||
return .complete()
|
||||
}
|
||||
|
||||
let searchContainerNode = LocationSearchContainerNode(context: self.context, coordinate: coordinate, interaction: self.interaction)
|
||||
@ -602,6 +620,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
searchContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationBarHeight, transition: .immediate)
|
||||
|
||||
return searchContainerNode.isSearching
|
||||
}
|
||||
|
||||
func deactivateSearch() {
|
||||
@ -643,10 +663,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
let isFirstLayout = self.validLayout == nil
|
||||
self.validLayout = (layout, navigationHeight)
|
||||
|
||||
let isPickingLocation = self.state.selectedLocation.isCustom || self.state.forceSelection
|
||||
let optionsHeight: CGFloat = 38.0
|
||||
|
||||
let pickingCustomLocation = self.state.selectedLocation.isCustom
|
||||
|
||||
var actionHeight: CGFloat?
|
||||
self.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? LocationActionListItemNode {
|
||||
@ -659,7 +677,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
let topInset: CGFloat = floor((layout.size.height - navigationHeight) / 2.0 + navigationHeight)
|
||||
let overlap: CGFloat = 6.0
|
||||
let headerHeight: CGFloat
|
||||
if pickingCustomLocation, let actionHeight = actionHeight {
|
||||
if isPickingLocation, let actionHeight = actionHeight {
|
||||
self.listOffset = topInset
|
||||
headerHeight = layout.size.height - actionHeight - layout.intrinsicInsets.bottom + overlap - 2.0
|
||||
} else if let listOffset = self.listOffset {
|
||||
@ -669,26 +687,29 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: headerHeight))
|
||||
transition.updateFrame(node: self.headerNode, frame: headerFrame)
|
||||
self.headerNode.updateLayout(layout: layout, navigationBarHeight: navigationHeight, padding: self.state.displayingMapModeOptions ? optionsHeight : 0.0, size: headerFrame.size, transition: transition)
|
||||
|
||||
self.headerNode.updateLayout(layout: layout, navigationBarHeight: navigationHeight, topPadding: self.state.displayingMapModeOptions ? optionsHeight : 0.0, offset: 0.0, size: headerFrame.size, transition: transition)
|
||||
|
||||
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
|
||||
let scrollToItem: ListViewScrollToItem?
|
||||
if pickingCustomLocation {
|
||||
if isPickingLocation {
|
||||
scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: curve, directionHint: .Up)
|
||||
} else {
|
||||
scrollToItem = nil
|
||||
}
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: scrollToItem, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: UIEdgeInsets(top: topInset, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), headerInsets: UIEdgeInsets(top: navigationHeight, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), scrollIndicatorInsets: UIEdgeInsets(top: topInset + 3.0, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
self.listNode.scrollEnabled = !pickingCustomLocation
|
||||
|
||||
let insets = UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: scrollToItem, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, headerInsets: UIEdgeInsets(top: navigationHeight, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), scrollIndicatorInsets: UIEdgeInsets(top: topInset + 3.0, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
self.listNode.scrollEnabled = !isPickingLocation
|
||||
|
||||
var listFrame: CGRect = CGRect(origin: CGPoint(), size: layout.size)
|
||||
if pickingCustomLocation {
|
||||
if isPickingLocation {
|
||||
listFrame.origin.y = headerHeight - topInset - overlap
|
||||
}
|
||||
transition.updateFrame(node: self.listNode, frame: listFrame)
|
||||
transition.updateAlpha(node: self.shadeNode, alpha: pickingCustomLocation ? 1.0 : 0.0)
|
||||
transition.updateAlpha(node: self.shadeNode, alpha: isPickingLocation ? 1.0 : 0.0)
|
||||
transition.updateFrame(node: self.shadeNode, frame: CGRect(x: 0.0, y: listFrame.minY + topInset + (actionHeight ?? 0.0) - 3.0, width: layout.size.width, height: 10000.0))
|
||||
self.shadeNode.isUserInteractionEnabled = pickingCustomLocation
|
||||
self.shadeNode.isUserInteractionEnabled = isPickingLocation
|
||||
self.innerShadeNode.frame = CGRect(x: 0.0, y: 4.0, width: layout.size.width, height: 10000.0)
|
||||
self.innerShadeNode.alpha = layout.intrinsicInsets.bottom > 0.0 ? 1.0 : 0.0
|
||||
|
||||
|
@ -13,14 +13,18 @@ import AccountContext
|
||||
import ItemListVenueItem
|
||||
import ItemListUI
|
||||
import MapKit
|
||||
import Geocoding
|
||||
import ChatListSearchItemHeader
|
||||
|
||||
private struct LocationSearchEntry: Identifiable, Comparable {
|
||||
let index: Int
|
||||
let theme: PresentationTheme
|
||||
let venue: TelegramMediaMap
|
||||
|
||||
let location: TelegramMediaMap
|
||||
let title: String?
|
||||
let distance: Double
|
||||
|
||||
var stableId: String {
|
||||
return self.venue.venue?.id ?? ""
|
||||
return self.location.venue?.id ?? ""
|
||||
}
|
||||
|
||||
static func ==(lhs: LocationSearchEntry, rhs: LocationSearchEntry) -> Bool {
|
||||
@ -30,7 +34,13 @@ private struct LocationSearchEntry: Identifiable, Comparable {
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.venue.venue?.id != rhs.venue.venue?.id {
|
||||
if lhs.location.venue?.id != rhs.location.venue?.id {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.distance != rhs.distance {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -41,10 +51,19 @@ private struct LocationSearchEntry: Identifiable, Comparable {
|
||||
}
|
||||
|
||||
func item(account: Account, presentationData: PresentationData, sendVenue: @escaping (TelegramMediaMap) -> Void) -> ListViewItem {
|
||||
let venue = self.venue
|
||||
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: self.venue, sectionId: 0, style: .plain, action: {
|
||||
let venue = self.location
|
||||
let header: ChatListSearchItemHeader
|
||||
let subtitle: String?
|
||||
if let _ = venue.venue {
|
||||
header = ChatListSearchItemHeader(type: .nearbyVenues, theme: presentationData.theme, strings: presentationData.strings)
|
||||
subtitle = nil
|
||||
} else {
|
||||
header = ChatListSearchItemHeader(type: .mapAddress, theme: presentationData.theme, strings: presentationData.strings)
|
||||
subtitle = presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: self.distance)).0
|
||||
}
|
||||
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: self.location, title: self.title, subtitle: subtitle, style: .plain, action: {
|
||||
sendVenue(venue)
|
||||
})
|
||||
}, header: header)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,10 +100,17 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
||||
private var containerViewLayout: (ContainerViewLayout, CGFloat)?
|
||||
private var enqueuedTransitions: [LocationSearchContainerTransition] = []
|
||||
|
||||
private let _isSearching = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
var isSearching: Signal<Bool, NoError> {
|
||||
return self._isSearching.get()
|
||||
}
|
||||
|
||||
public init(context: AccountContext, coordinate: CLLocationCoordinate2D, interaction: LocationPickerInteraction) {
|
||||
self.context = context
|
||||
self.interaction = interaction
|
||||
|
||||
let currentLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
|
||||
@ -107,6 +133,7 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
||||
|
||||
let themeAndStringsPromise = self.themeAndStringsPromise
|
||||
|
||||
let isSearching = self._isSearching
|
||||
let searchItems = self.searchQuery.get()
|
||||
|> mapToSignal { query -> Signal<String?, NoError> in
|
||||
if let query = query, !query.isEmpty {
|
||||
@ -119,19 +146,43 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
||||
|> mapToSignal { query -> Signal<[LocationSearchEntry]?, NoError> in
|
||||
if let query = query, !query.isEmpty {
|
||||
let foundVenues = nearbyVenues(account: context.account, latitude: coordinate.latitude, longitude: coordinate.longitude, query: query)
|
||||
return combineLatest(foundVenues, themeAndStringsPromise.get())
|
||||
|> afterCompleted {
|
||||
isSearching.set(false)
|
||||
}
|
||||
let foundPlacemarks = geocodeLocation(address: query)
|
||||
return combineLatest(foundVenues, foundPlacemarks, themeAndStringsPromise.get())
|
||||
|> delay(0.1, queue: Queue.concurrentDefaultQueue())
|
||||
|> map { venues, themeAndStrings -> [LocationSearchEntry] in
|
||||
|> beforeStarted {
|
||||
isSearching.set(true)
|
||||
}
|
||||
|> map { venues, placemarks, themeAndStrings -> [LocationSearchEntry] in
|
||||
var entries: [LocationSearchEntry] = []
|
||||
var index: Int = 0
|
||||
|
||||
if let placemarks = placemarks {
|
||||
for placemark in placemarks {
|
||||
guard let placemarkLocation = placemark.location else {
|
||||
continue
|
||||
}
|
||||
let location = TelegramMediaMap(latitude: placemarkLocation.coordinate.latitude, longitude: placemarkLocation.coordinate.longitude, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil)
|
||||
|
||||
entries.append(LocationSearchEntry(index: index, theme: themeAndStrings.0, location: location, title: placemark.name ?? "Name", distance: placemarkLocation.distance(from: currentLocation)))
|
||||
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
||||
for venue in venues {
|
||||
entries.append(LocationSearchEntry(index: index, theme: themeAndStrings.0, venue: venue))
|
||||
entries.append(LocationSearchEntry(index: index, theme: themeAndStrings.0, location: venue, title: nil, distance: 0.0))
|
||||
index += 1
|
||||
}
|
||||
return entries
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
|> afterCompleted {
|
||||
isSearching.set(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +192,12 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
||||
if let strongSelf = self {
|
||||
let previousItems = previousSearchItems.swap(items ?? [])
|
||||
let transition = locationSearchContainerPreparedTransition(from: previousItems, to: items ?? [], isSearching: items != nil, account: context.account, presentationData: strongSelf.presentationData, sendVenue: { venue in self?.listNode.clearHighlightAnimated(true)
|
||||
self?.interaction.sendVenue(venue)
|
||||
if let _ = venue.venue {
|
||||
self?.interaction.sendVenue(venue)
|
||||
} else {
|
||||
self?.interaction.goToCoordinate(venue.coordinate)
|
||||
self?.interaction.dismissSearch()
|
||||
}
|
||||
})
|
||||
strongSelf.enqueueTransition(transition)
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
|
||||
self.searchBar.deactivate(clear: false)
|
||||
}
|
||||
|
||||
func updateActivity(_ activity: Bool) {
|
||||
self.searchBar.activity = activity
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings)
|
||||
|
@ -22,7 +22,7 @@
|
||||
- (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet;
|
||||
- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo;
|
||||
- (void)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken;
|
||||
- (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId;
|
||||
- (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId shouldReset:(bool)shouldReset;
|
||||
- (void)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId;
|
||||
- (void)contextDatacenterPublicKeysUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
|
||||
- (MTSignal *)fetchContextDatacenterPublicKeys:(MTContext *)context datacenterId:(NSInteger)datacenterId;
|
||||
|
@ -491,10 +491,11 @@ static int32_t fixedTimeDifferenceValue = 0;
|
||||
[listener contextDatacenterAddressSetUpdated:self datacenterId:datacenterId addressSet:addressSet];
|
||||
}
|
||||
|
||||
if (previousAddressSetWasEmpty || updateSchemes || true) {
|
||||
if (true) {
|
||||
bool shouldReset = previousAddressSetWasEmpty || updateSchemes;
|
||||
for (id<MTContextChangeListener> listener in currentListeners) {
|
||||
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:)]) {
|
||||
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId];
|
||||
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:shouldReset:)]) {
|
||||
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId shouldReset:shouldReset];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -664,8 +665,8 @@ static int32_t fixedTimeDifferenceValue = 0;
|
||||
}
|
||||
|
||||
for (id<MTContextChangeListener> listener in currentListeners) {
|
||||
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:)])
|
||||
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId];
|
||||
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:shouldReset:)])
|
||||
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId shouldReset:true];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
@ -2715,15 +2715,20 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId {
|
||||
- (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId shouldReset:(bool)shouldReset {
|
||||
[[MTProto managerQueue] dispatchOnQueue:^ {
|
||||
if (context == _context && datacenterId == _datacenterId && ![self isStopped]) {
|
||||
bool resolvedShouldReset = shouldReset;
|
||||
|
||||
if (_mtState & MTProtoStateAwaitingDatacenterScheme) {
|
||||
[self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterScheme)];
|
||||
resolvedShouldReset = true;
|
||||
}
|
||||
|
||||
[self resetTransport];
|
||||
[self requestTransportTransaction];
|
||||
if (resolvedShouldReset) {
|
||||
[self resetTransport];
|
||||
[self requestTransportTransaction];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public struct NotificationSoundSettings {
|
||||
}
|
||||
|
||||
public func notificationMuteSettingsController(presentationData: PresentationData, notificationSettings: MessageNotificationSettings, soundSettings: NotificationSoundSettings?, openSoundSettings: @escaping () -> Void, updateSettings: @escaping (Int32?) -> Void) -> ViewController {
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ public final class OpenInActionSheetController: ActionSheetController {
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
@ -116,9 +116,6 @@ private final class OpenInActionSheetItem: ActionSheetItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.medium(20.0)
|
||||
private let textFont = Font.regular(11.0)
|
||||
|
||||
private final class OpenInActionSheetItemNode: ActionSheetItemNode {
|
||||
let theme: ActionSheetControllerTheme
|
||||
let strings: PresentationStrings
|
||||
@ -132,6 +129,9 @@ private final class OpenInActionSheetItemNode: ActionSheetItemNode {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
let titleFont = Font.medium(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
let textFont = Font.regular(floor(theme.baseFontSize * 11.0 / 17.0))
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.displaysAsynchronously = true
|
||||
@ -216,6 +216,7 @@ private final class OpenInAppNode : ASDisplayNode {
|
||||
}
|
||||
|
||||
func setup(postbox: Postbox, context: AccountContext, theme: ActionSheetControllerTheme, option: OpenInOption, invokeAction: @escaping (OpenInAction) -> Void) {
|
||||
let textFont = Font.regular(floor(theme.baseFontSize * 11.0 / 17.0))
|
||||
self.textNode.attributedText = NSAttributedString(string: option.title, font: textFont, textColor: theme.primaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
let iconSize = CGSize(width: 60.0, height: 60.0)
|
||||
|
@ -59,7 +59,7 @@ public final class PasscodeSetupController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
self?.controllerNode.activateInput()
|
||||
controller?.dismissAnimated()
|
||||
|
@ -727,7 +727,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
if let currentValue = currentValue {
|
||||
let controller = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: self.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -847,7 +847,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
return
|
||||
}
|
||||
|
||||
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -916,7 +916,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
]
|
||||
}
|
||||
|
||||
let controller = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: self.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -961,7 +961,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
private func deleteAllValues() {
|
||||
let controller = ActionSheetController(presentationTheme: self.presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: self.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -2143,6 +2143,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
return self._itemParams!
|
||||
}
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var theme: PresentationTheme
|
||||
private var strings: PresentationStrings
|
||||
|
||||
@ -2161,6 +2162,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
private let hiddenItemDisposable = MetaDisposable()
|
||||
|
||||
required init(initParams: SecureIdDocumentFormControllerNodeInitParams, presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.theme = presentationData.theme
|
||||
self.strings = presentationData.strings
|
||||
self.context = initParams.context
|
||||
@ -2414,7 +2416,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
strongSelf.view.endEditing(true)
|
||||
strongSelf.present(controller, nil)
|
||||
case .gender:
|
||||
let controller = ActionSheetController(presentationTheme: strongSelf.theme)
|
||||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -2756,7 +2758,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
return
|
||||
}
|
||||
|
||||
let controller = ActionSheetController(presentationTheme: theme)
|
||||
let controller = ActionSheetController(presentationData: self.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -2816,7 +2818,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
|
||||
private func openDocument(document: SecureIdVerificationDocument) {
|
||||
let controller = ActionSheetController(presentationTheme: theme)
|
||||
let controller = ActionSheetController(presentationData: self.presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ final class SecureIdDocumentGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
|
||||
@objc func deleteButtonPressed() {
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
let items: [ActionSheetItem] = [
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
@ -89,11 +89,11 @@ final class SecureIdDocumentTypeSelectionController: ActionSheetController {
|
||||
|
||||
self.completion = completion
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -505,12 +505,12 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.displayWithoutProcessing = true
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.actionSheet.inputBackgroundColor)
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.list.freePlainInputField.backgroundColor)
|
||||
|
||||
self.inputNode = TextFieldNode()
|
||||
self.inputNode.textField.font = Font.regular(17.0)
|
||||
self.inputNode.textField.textColor = theme.actionSheet.inputTextColor
|
||||
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.actionSheet.inputPlaceholderColor)
|
||||
self.inputNode.textField.textColor = theme.list.freePlainInputField.primaryColor
|
||||
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.list.freePlainInputField.placeholderColor)
|
||||
|
||||
self.hideButtonNode = HighlightableButtonNode()
|
||||
|
||||
@ -548,10 +548,10 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
|
||||
}
|
||||
self.inputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
|
||||
self.hideButtonNode.setImage(generateTextHiddenImage(color: theme.actionSheet.inputClearButtonColor, on: false), for: [])
|
||||
self.hideButtonNode.setImage(generateTextHiddenImage(color: theme.list.freePlainInputField.controlColor, on: false), for: [])
|
||||
|
||||
self.clearButtonNode = HighlightableButtonNode()
|
||||
self.clearButtonNode.setImage(generateClearImage(color: theme.actionSheet.inputClearButtonColor), for: [])
|
||||
self.clearButtonNode.setImage(generateClearImage(color: theme.list.freePlainInputField.controlColor), for: [])
|
||||
self.clearButtonNode.isHidden = true
|
||||
|
||||
super.init()
|
||||
@ -1198,11 +1198,27 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
transition.updateFrame(node: self.skipActionButtonNode, frame: buttonFrame)
|
||||
transition.updateFrame(node: self.skipActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX + floor((buttonFrame.width - skipActionSize.width) / 2.0), y: buttonFrame.minY + floor((buttonFrame.height - skipActionSize.height) / 2.0)), size: skipActionSize))
|
||||
|
||||
transition.updateFrame(node: self.changeEmailActionButtonNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height)))
|
||||
transition.updateFrame(node: self.resendCodeActionButtonNode, frame: CGRect(origin: CGPoint(x: buttonFrame.maxX - floor(buttonFrame.width / 2.0), y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height)))
|
||||
let changeEmailActionFrame: CGRect
|
||||
let changeEmailActionButtonFrame: CGRect
|
||||
let resendCodeActionFrame: CGRect
|
||||
let resendCodeActionButtonFrame: CGRect
|
||||
if changeEmailActionSize.width + resendCodeActionSize.width > layout.size.width - 24.0 {
|
||||
changeEmailActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY), size: CGSize(width: buttonFrame.width, height: buttonFrame.height))
|
||||
changeEmailActionFrame = CGRect(origin: CGPoint(x: changeEmailActionButtonFrame.minX + floor((changeEmailActionButtonFrame.width - changeEmailActionSize.width) / 2.0), y: changeEmailActionButtonFrame.minY + floor((changeEmailActionButtonFrame.height - changeEmailActionSize.height) / 2.0)), size: changeEmailActionSize)
|
||||
resendCodeActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.maxY), size: CGSize(width: buttonFrame.width, height: buttonFrame.height))
|
||||
resendCodeActionFrame = CGRect(origin: CGPoint(x: resendCodeActionButtonFrame.minX + floor((resendCodeActionButtonFrame.width - resendCodeActionSize.width) / 2.0), y: resendCodeActionButtonFrame.minY + floor((resendCodeActionButtonFrame.height - resendCodeActionSize.height) / 2.0)), size: resendCodeActionSize)
|
||||
} else {
|
||||
changeEmailActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height))
|
||||
changeEmailActionFrame = CGRect(origin: CGPoint(x: changeEmailActionButtonFrame.minX, y: changeEmailActionButtonFrame.minY + floor((changeEmailActionButtonFrame.height - changeEmailActionSize.height) / 2.0)), size: changeEmailActionSize)
|
||||
resendCodeActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.maxX - floor(buttonFrame.width / 2.0), y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height))
|
||||
resendCodeActionFrame = CGRect(origin: CGPoint(x: resendCodeActionButtonFrame.maxX - resendCodeActionSize.width, y: resendCodeActionButtonFrame.minY + floor((resendCodeActionButtonFrame.height - resendCodeActionSize.height) / 2.0)), size: resendCodeActionSize)
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.changeEmailActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY + floor((buttonFrame.height - changeEmailActionSize.height) / 2.0)), size: changeEmailActionSize))
|
||||
transition.updateFrame(node: self.resendCodeActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.maxX - resendCodeActionSize.width, y: buttonFrame.minY + floor((buttonFrame.height - resendCodeActionSize.height) / 2.0)), size: resendCodeActionSize))
|
||||
transition.updateFrame(node: self.changeEmailActionButtonNode, frame: changeEmailActionButtonFrame)
|
||||
transition.updateFrame(node: self.resendCodeActionButtonNode, frame: resendCodeActionButtonFrame)
|
||||
|
||||
transition.updateFrame(node: self.changeEmailActionTitleNode, frame: changeEmailActionFrame)
|
||||
transition.updateFrame(node: self.resendCodeActionTitleNode, frame: resendCodeActionFrame)
|
||||
|
||||
transition.animateView {
|
||||
self.scrollNode.view.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.insets(options: [.input]).bottom, right: 0.0)
|
||||
|
@ -148,7 +148,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode {
|
||||
|
||||
@objc private func deleteButtonPressed() {
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
let items: [ActionSheetItem] = [
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
@ -868,7 +868,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
}
|
||||
}, dismissAdmin: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_Moderator_AccessLevelRevoke, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
@ -461,7 +461,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
|
||||
})
|
||||
}, openTimeout: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
let intervals: [Int32] = [
|
||||
1 * 60 * 60 * 24,
|
||||
7 * 60 * 60 * 24,
|
||||
@ -499,7 +499,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
|
||||
presentControllerImpl?(actionSheet, nil)
|
||||
}, delete: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_Delete, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
@ -703,7 +703,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0))
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_ApplyAlertAction, color: .accent, font: .default, enabled: true, action: { [weak actionSheet] in
|
||||
|
@ -359,7 +359,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
||||
return
|
||||
}
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
if !participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder).isEmpty {
|
||||
items.append(ActionSheetTextItem(title: participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)))
|
||||
|
@ -75,9 +75,13 @@ private final class ChannelDiscussionGroupActionSheetItemNode: ActionSheetItemNo
|
||||
} else {
|
||||
text = strings.Channel_DiscussionGroup_PrivateChannelLink(groupPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), channelPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: Font.regular(14.0), textColor: theme.primaryTextColor))
|
||||
|
||||
let textFont = Font.regular(floor(theme.baseFontSize * 14.0 / 17.0))
|
||||
let boldFont = Font.semibold(floor(theme.baseFontSize * 14.0 / 17.0))
|
||||
|
||||
let attributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: textFont, textColor: theme.primaryTextColor))
|
||||
for (_, range) in text.1 {
|
||||
attributedText.addAttribute(.font, value: Font.semibold(14.0), range: range)
|
||||
attributedText.addAttribute(.font, value: boldFont, range: range)
|
||||
}
|
||||
|
||||
self.textNode.attributedText = attributedText
|
||||
|
@ -305,7 +305,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ChannelDiscussionGroupActionSheetItem(context: context, channelPeer: channelPeer, groupPeer: groupPeer, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
ActionSheetButtonItem(title: presentationData.strings.Channel_DiscussionGroup_LinkGroup, color: .accent, action: { [weak actionSheet] in
|
||||
|
@ -905,7 +905,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
|
||||
return
|
||||
}
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -929,7 +929,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
|
||||
return
|
||||
}
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -922,7 +922,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
})
|
||||
}, revokePrivateLink: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -869,7 +869,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
|> deliverOnMainQueue).start(next: { user in
|
||||
if let user = user, let phone = user.phone, formatPhoneNumber(phone) == formatPhoneNumber(number) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -992,7 +992,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
inviteAction(subject.contactData.basicData.phoneNumbers[0].value)
|
||||
} else {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -1402,7 +1402,7 @@ private func addContactToExisting(context: AccountContext, parentController: Vie
|
||||
|
||||
func addContactOptionsController(context: AccountContext, peer: Peer?, contactData: DeviceContactExtendedData) -> ActionSheetController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -1998,7 +1998,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
if let channel = peerView.peers[peerView.peerId] as? TelegramChannel, channel.flags.contains(.isCreator), stateValue.with({ $0 }).editingState != nil {
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -2015,7 +2015,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
])
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
} else if let peer = peerView.peers[peerView.peerId] {
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ public func groupsInCommonController(context: AccountContext, peerId: PeerId) ->
|
||||
arguments.openPeer(peer.id)
|
||||
}))
|
||||
]
|
||||
let contextController = ContextController(account: context.account, theme: presentationData.theme, strings: presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture)
|
||||
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture)
|
||||
controller.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
return controller
|
||||
|
@ -23,13 +23,13 @@ final class PeerBanTimeoutController: ActionSheetController {
|
||||
let theme = presentationData.theme
|
||||
let strings = presentationData.strings
|
||||
|
||||
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme))
|
||||
super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
self._ready.set(.single(true))
|
||||
|
||||
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -111,7 +111,7 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro
|
||||
|
||||
public func peerReportOptionsController(context: AccountContext, subject: PeerReportSubject, present: @escaping (ViewController, Any?) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (Bool) -> Void) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme))
|
||||
let controller = ActionSheetController(theme: ActionSheetControllerTheme(presentationData: presentationData))
|
||||
|
||||
let options: [PeerReportOption] = [
|
||||
.spam,
|
||||
|
@ -990,7 +990,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
} else {
|
||||
if value {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -1046,7 +1046,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
})
|
||||
}, deleteContact: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -1112,7 +1112,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
|> deliverOnMainQueue).start(next: { peer, _ in
|
||||
if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(number) == formatPhoneNumber(peerPhoneNumber) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -1584,7 +1584,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String = presentationData.strings.UserInfo_TapToCall
|
||||
|
||||
let tooltipController = TooltipController(content: .text(text), dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
controller.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak resultItemNode] in
|
||||
if let resultItemNode = resultItemNode {
|
||||
return (resultItemNode, callButtonFrame)
|
||||
|
@ -468,7 +468,9 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
||||
entries.append(.useLessVoiceData(presentationData.theme, presentationData.strings.CallSettings_UseLessData, stringForUseLessDataSetting(dataSaving, strings: presentationData.strings)))
|
||||
|
||||
entries.append(.otherHeader(presentationData.theme, presentationData.strings.ChatSettings_Other))
|
||||
entries.append(.shareSheet(presentationData.theme, "Share Sheet"))
|
||||
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
|
||||
entries.append(.shareSheet(presentationData.theme, presentationData.strings.ChatSettings_IntentsSettings))
|
||||
}
|
||||
entries.append(.saveIncomingPhotos(presentationData.theme, presentationData.strings.Settings_SaveIncomingPhotos))
|
||||
entries.append(.saveEditedPhotos(presentationData.theme, presentationData.strings.Settings_SaveEditedPhotos, data.generatedMediaStoreSettings.storeEditedPhotos))
|
||||
entries.append(.openLinksIn(presentationData.theme, presentationData.strings.ChatSettings_OpenLinksIn, defaultWebBrowser))
|
||||
@ -554,7 +556,7 @@ func dataAndStorageController(context: AccountContext, focusOnItemTag: DataAndSt
|
||||
pushControllerImpl?(autodownloadMediaConnectionTypeController(context: context, connectionType: connectionType))
|
||||
}, resetAutomaticDownload: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: presentationData.strings.AutoDownloadSettings_ResetHelp),
|
||||
ActionSheetButtonItem(title: presentationData.strings.AutoDownloadSettings_Reset, color: .destructive, action: { [weak actionSheet] in
|
||||
|
@ -150,7 +150,6 @@ private enum IntentsSettingsControllerEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
case let .suggestHeader(lhsTheme, lhsText):
|
||||
if case let .suggestHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
@ -272,7 +271,7 @@ public func intentsSettingsController(context: AccountContext) -> ViewController
|
||||
let _ = updateIntentsSettingsInteractively(accountManager: context.sharedContext.accountManager, f).start()
|
||||
}, resetAll: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: presentationData.strings.IntentsSettings_Reset, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
@ -389,7 +389,7 @@ func networkUsageStatsController(context: AccountContext) -> ViewController {
|
||||
|
||||
let arguments = NetworkUsageStatsControllerArguments(resetStatistics: { [weak stats] section in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
case let .serversHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .addServer(theme, text, _):
|
||||
return ProxySettingsActionItem(theme: theme, title: text, icon: .add, sectionId: self.section, editing: false, action: {
|
||||
return ProxySettingsActionItem(presentationData: presentationData, title: text, icon: .add, sectionId: self.section, editing: false, action: {
|
||||
arguments.addNewServer()
|
||||
})
|
||||
case let .server(_, theme, strings, settings, active, status, editing, enabled):
|
||||
@ -230,7 +230,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
arguments.removeServer(settings)
|
||||
})
|
||||
case let .shareProxyList(theme, text):
|
||||
return ProxySettingsActionItem(theme: theme, title: text, sectionId: self.section, editing: false, action: {
|
||||
return ProxySettingsActionItem(presentationData: presentationData, title: text, sectionId: self.section, editing: false, action: {
|
||||
arguments.shareProxyList()
|
||||
})
|
||||
case let .useForCalls(theme, text, value):
|
||||
|
@ -29,7 +29,7 @@ public final class ProxyServerActionSheetController: ActionSheetController {
|
||||
}
|
||||
|
||||
public init(presentationData: PresentationData, accountManager: AccountManager, postbox: Postbox, network: Network, server: ProxyServerSettings, updatedPresentationData: Signal<PresentationData, NoError>?) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
super.init(theme: sheetTheme)
|
||||
|
||||
self._ready.set(.single(true))
|
||||
@ -63,7 +63,7 @@ public final class ProxyServerActionSheetController: ActionSheetController {
|
||||
if let updatedPresentationData = updatedPresentationData {
|
||||
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -97,8 +97,6 @@ private final class ProxyServerInfoItem: ActionSheetItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let textFont = Font.regular(16.0)
|
||||
|
||||
private enum ProxyServerInfoStatusType {
|
||||
case generic(String)
|
||||
case failed(String)
|
||||
@ -107,6 +105,7 @@ private enum ProxyServerInfoStatusType {
|
||||
private final class ProxyServerInfoItemNode: ActionSheetItemNode {
|
||||
private let theme: ActionSheetControllerTheme
|
||||
private let strings: PresentationStrings
|
||||
private let textFont: UIFont
|
||||
|
||||
private let network: Network
|
||||
private let server: ProxyServerSettings
|
||||
@ -122,6 +121,8 @@ private final class ProxyServerInfoItemNode: ActionSheetItemNode {
|
||||
self.network = network
|
||||
self.server = server
|
||||
|
||||
self.textFont = Font.regular(floor(theme.baseFontSize * 16.0 / 17.0))
|
||||
|
||||
var fieldNodes: [(ImmediateTextNode, ImmediateTextNode)] = []
|
||||
let serverTitleNode = ImmediateTextNode()
|
||||
serverTitleNode.isUserInteractionEnabled = false
|
||||
@ -317,10 +318,12 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
self.dismiss = dismiss
|
||||
self.present = present
|
||||
|
||||
let titleFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.SocksProxySetup_ConnectAndSave, font: Font.regular(20.0), textColor: theme.controlAccentColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.SocksProxySetup_ConnectAndSave, font: titleFont, textColor: theme.controlAccentColor)
|
||||
|
||||
self.activityIndicator = ActivityIndicator(type: .custom(theme.controlAccentColor, 22.0, 1.5, false))
|
||||
self.activityIndicator.isHidden = true
|
||||
|
@ -13,15 +13,15 @@ enum ProxySettingsActionIcon {
|
||||
}
|
||||
|
||||
final class ProxySettingsActionItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let icon: ProxySettingsActionIcon
|
||||
let editing: Bool
|
||||
let sectionId: ItemListSectionId
|
||||
let action: () -> Void
|
||||
|
||||
init(theme: PresentationTheme, title: String, icon: ProxySettingsActionIcon = .none, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
init(presentationData: ItemListPresentationData, title: String, icon: ProxySettingsActionIcon = .none, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.editing = editing
|
||||
@ -75,8 +75,6 @@ final class ProxySettingsActionItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
private final class ProxySettingsActionItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -130,24 +128,26 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
let leftInset: CGFloat = (item.icon != .none ? 50.0 : 16.0) + params.leftInset
|
||||
|
||||
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - editingOffset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - editingOffset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
let contentSize = CGSize(width: params.width, height: 44.0)
|
||||
let contentSize = CGSize(width: params.width, height: 22.0 + titleLayout.size.height)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
|
||||
let icon = item.icon == .add ? PresentationResourcesItemList.plusIconImage(item.theme) : nil
|
||||
let icon = item.icon == .add ? PresentationResourcesItemList.plusIconImage(item.presentationData.theme) : nil
|
||||
|
||||
return (layout, { [weak self] animated in
|
||||
if let strongSelf = self {
|
||||
@ -156,10 +156,10 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
|
||||
strongSelf.accessibilityLabel = item.title
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -213,7 +213,7 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
@ -22,7 +22,7 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
|
||||
private var isDismissed: Bool = false
|
||||
|
||||
public init(presentationData: PresentationData, updatedPresentationData: Signal<PresentationData, NoError>, link: String) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
super.init(theme: sheetTheme)
|
||||
|
||||
let presentActivityController: (Any) -> Void = { [weak self] item in
|
||||
@ -67,7 +67,7 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
|
||||
|
||||
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -119,13 +119,15 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode {
|
||||
self.link = link
|
||||
self.ready = ready
|
||||
|
||||
let textFont = Font.regular(floor(theme.baseFontSize * 13.0 / 17.0))
|
||||
|
||||
self.label = ASTextNode()
|
||||
self.label.isUserInteractionEnabled = false
|
||||
self.label.maximumNumberOfLines = 0
|
||||
self.label.displaysAsynchronously = false
|
||||
self.label.truncationMode = .byTruncatingTail
|
||||
self.label.isUserInteractionEnabled = false
|
||||
self.label.attributedText = NSAttributedString(string: strings.SocksProxySetup_ShareQRCodeInfo, font: ActionSheetTextNode.defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.label.attributedText = NSAttributedString(string: strings.SocksProxySetup_ShareQRCodeInfo, font: textFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.imageNode = TransformImageNode()
|
||||
self.imageNode.clipsToBounds = true
|
||||
|
@ -402,7 +402,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
||||
|> deliverOnMainQueue).start(next: { [weak statsPromise] result in
|
||||
if let result = result, case let .result(stats) = result {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
@ -624,7 +624,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public func debugAccountsController(context: AccountContext, accountManager: Acc
|
||||
}).start()
|
||||
}, loginNewAccount: {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let controller = ActionSheetController(presentationData: presentationData)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
let _ = (Logger.shared.collectLogs()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
|
||||
var items: [ActionSheetButtonItem] = []
|
||||
|
||||
@ -206,7 +206,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
let _ = (Logger.shared.collectLogs()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
|
||||
var items: [ActionSheetButtonItem] = []
|
||||
|
||||
@ -284,7 +284,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
let _ = (Logger.shared.collectShortLogFiles()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
|
||||
var items: [ActionSheetButtonItem] = []
|
||||
|
||||
@ -409,7 +409,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
case let .resetData(theme):
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Reset Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: "All data will be lost."),
|
||||
ActionSheetButtonItem(title: "Reset Data", color: .destructive, action: { [weak actionSheet] in
|
||||
@ -431,7 +431,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
return
|
||||
}
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: "All secret chats will be lost."),
|
||||
ActionSheetButtonItem(title: "Clear Database", color: .destructive, action: { [weak actionSheet] in
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user