Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
overtake 2019-11-27 15:52:20 +04:00
commit cb6377bfac
159 changed files with 4982 additions and 4326 deletions

View File

@ -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.ColorWallpaperWarning" = "Are you sure you want to change your chat wallpaper to a color?";
"Theme.Colors.ColorWallpaperWarningProceed" = "Proceed"; "Theme.Colors.ColorWallpaperWarningProceed" = "Proceed";
"ChatSettings.IntentsSettings" = "Share Sheet";
"IntentsSettings.Title" = "Share Sheet"; "IntentsSettings.Title" = "Share Sheet";
"IntentsSettings.MainAccount" = "Main Account"; "IntentsSettings.MainAccount" = "Main Account";
"IntentsSettings.MainAccountInfo" = "Choose an account for Siri and share suggestions."; "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.SendThisPlace" = "Send This Place";
"Map.SetThisPlace" = "Set 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.";

View File

@ -135,9 +135,13 @@ final class PeerView: UIView {
title.append("\n") title.append("\n")
title.append(lastName) title.append(lastName)
} }
let systemFontSize = UIFont.preferredFont(forTextStyle: .body).pointSize
let fontSize = floor(systemFontSize * 11.0 / 17.0)
self.titleLabel.text = title self.titleLabel.text = title
self.titleLabel.textColor = primaryColor 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.lineBreakMode = .byTruncatingTail
self.titleLabel.numberOfLines = 2 self.titleLabel.numberOfLines = 2
self.titleLabel.textAlignment = .center self.titleLabel.textAlignment = .center

View File

@ -54,10 +54,12 @@ class TodayViewController: UIViewController, NCWidgetProviding {
presentationData = WidgetPresentationData(applicationLockedString: "Unlock the app to use widget") 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) { 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() let appLockedLabel = UILabel()
appLockedLabel.textColor = self.primaryColor appLockedLabel.textColor = self.primaryColor
appLockedLabel.font = UIFont.systemFont(ofSize: 16.0) appLockedLabel.font = UIFont.systemFont(ofSize: fontSize)
appLockedLabel.text = presentationData.applicationLockedString appLockedLabel.text = presentationData.applicationLockedString
appLockedLabel.sizeToFit() appLockedLabel.sizeToFit()
self.appLockedLabel = appLockedLabel self.appLockedLabel = appLockedLabel

View File

@ -48,7 +48,7 @@ private let avatarFont = avatarPlaceholderFont(size: 15.0)
public class ActionSheetPeerItemNode: ActionSheetItemNode { public class ActionSheetPeerItemNode: ActionSheetItemNode {
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
public static let defaultFont: UIFont = Font.regular(20.0) private let defaultFont: UIFont
private var item: ActionSheetPeerItem? private var item: ActionSheetPeerItem?
@ -62,6 +62,8 @@ public class ActionSheetPeerItemNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) { override public init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton() self.button = HighlightTrackingButton()
self.button.isAccessibilityElement = false self.button.isAccessibilityElement = false
@ -114,8 +116,10 @@ public class ActionSheetPeerItemNode: ActionSheetItemNode {
func setItem(_ item: ActionSheetPeerItem) { func setItem(_ item: ActionSheetPeerItem) {
self.item = item self.item = item
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
let textColor: UIColor = self.theme.primaryTextColor 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) self.avatarNode.setPeer(account: item.account, theme: item.theme, peer: item.peer)

View File

@ -42,11 +42,11 @@ final class BotCheckoutPaymentMethodSheetController: ActionSheetController {
let theme = presentationData.theme let theme = presentationData.theme
let strings = presentationData.strings 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 self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { 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 class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
public static let defaultFont: UIFont = Font.regular(20.0) private let defaultFont: UIFont
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
@ -150,6 +150,7 @@ public class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
public override init(theme: ActionSheetControllerTheme) { public override init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton() self.button = HighlightTrackingButton()
@ -201,7 +202,7 @@ public class BotCheckoutPaymentMethodItemNode: ActionSheetItemNode {
func setItem(_ item: BotCheckoutPaymentMethodItem) { func setItem(_ item: BotCheckoutPaymentMethodItem) {
self.item = item 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 self.iconNode.image = item.icon
if let value = item.value { if let value = item.value {
self.checkNode.isHidden = !value self.checkNode.isHidden = !value

View File

@ -16,11 +16,11 @@ final class BotCheckoutPaymentShippingOptionSheetController: ActionSheetControll
let theme = presentationData.theme let theme = presentationData.theme
let strings = presentationData.strings 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 self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { 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 class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
public static let defaultFont: UIFont = Font.regular(20.0) private let defaultFont: UIFont
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
@ -126,6 +126,7 @@ public class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
public override init(theme: ActionSheetControllerTheme) { public override init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton() self.button = HighlightTrackingButton()
@ -178,8 +179,8 @@ public class BotCheckoutPaymentShippingOptionItemNode: ActionSheetItemNode {
func setItem(_ item: BotCheckoutPaymentShippingOptionItem) { func setItem(_ item: BotCheckoutPaymentShippingOptionItem) {
self.item = item self.item = item
self.titleNode.attributedText = NSAttributedString(string: item.title, 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: BotCheckoutPaymentShippingOptionItemNode.defaultFont, textColor: self.theme.primaryTextColor) self.labelNode.attributedText = NSAttributedString(string: item.label, font: self.defaultFont, textColor: self.theme.primaryTextColor)
if let value = item.value { if let value = item.value {
self.checkNode.isHidden = !value self.checkNode.isHidden = !value
} else { } else {

View File

@ -17,6 +17,8 @@ public enum ChatListSearchItemHeaderType: Int32 {
case phoneNumber case phoneNumber
case exceptions case exceptions
case addToExceptions case addToExceptions
case mapAddress
case nearbyVenues
} }
public final class ChatListSearchItemHeader: ListViewItemHeader { public final class ChatListSearchItemHeader: ListViewItemHeader {
@ -30,7 +32,7 @@ public final class ChatListSearchItemHeader: ListViewItemHeader {
public let height: CGFloat = 28.0 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.type = type
self.id = Int64(self.type.rawValue) self.id = Int64(self.type.rawValue)
self.theme = theme self.theme = theme
@ -93,6 +95,10 @@ public final class ChatListSearchItemHeaderNode: ListViewItemHeaderNode {
self.sectionHeaderNode.title = strings.GroupInfo_Permissions_Exceptions.uppercased() self.sectionHeaderNode.title = strings.GroupInfo_Permissions_Exceptions.uppercased()
case .addToExceptions: case .addToExceptions:
self.sectionHeaderNode.title = strings.Exceptions_AddToExceptions.uppercased() 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 self.sectionHeaderNode.action = actionTitle

View File

@ -308,7 +308,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
if case .root = groupId, checkProxy { if case .root = groupId, checkProxy {
if strongSelf.proxyUnavailableTooltipController == nil && !strongSelf.didShowProxyUnavailableTooltipController && strongSelf.isNodeLoaded && strongSelf.displayNode.view.window != nil { if strongSelf.proxyUnavailableTooltipController == nil && !strongSelf.didShowProxyUnavailableTooltipController && strongSelf.isNodeLoaded && strongSelf.displayNode.view.window != nil {
strongSelf.didShowProxyUnavailableTooltipController = true 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 strongSelf.proxyUnavailableTooltipController = tooltipController
tooltipController.dismissed = { [weak tooltipController] _ in tooltipController.dismissed = { [weak tooltipController] _ in
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.proxyUnavailableTooltipController === tooltipController { 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 self.chatListDisplayNode.requestOpenRecentPeerOptions = { [weak self] peer in
if let strongSelf = self { if let strongSelf = self {
strongSelf.view.window?.endEditing(true) strongSelf.view.window?.endEditing(true)
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
actionSheet.setItemGroups([ actionSheet.setItemGroups([
ActionSheetItemGroup(items: [ ActionSheetItemGroup(items: [
@ -669,12 +669,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
case let .groupReference(groupReference): case let .groupReference(groupReference):
let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupReference.groupId, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false) let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupReference.groupId, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
chatListController.navigationPresentation = .master 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) strongSelf.presentInGlobalOverlay(contextController)
case let .peer(peer): 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)) 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) 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) 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)) 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) 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) strongSelf.presentInGlobalOverlay(contextController)
} }
@ -798,7 +798,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
if hasPasscode { if hasPasscode {
let _ = ApplicationSpecificNotice.setPasscodeLockTips(accountManager: strongSelf.context.sharedContext.accountManager).start() 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 strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceViewAndRect: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
return (strongSelf.titleView, lockViewFrame.offsetBy(dx: 4.0, dy: 14.0)) return (strongSelf.titleView, lockViewFrame.offsetBy(dx: 4.0, dy: 14.0))
@ -1199,7 +1199,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
self?.donePressed() self?.donePressed()
}) })
} else if case .right = action, !peerIds.isEmpty { } else if case .right = action, !peerIds.isEmpty {
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteConfirmation(Int32(peerIds.count)), color: .destructive, action: { [weak self, weak actionSheet] in items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteConfirmation(Int32(peerIds.count)), color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -1385,7 +1385,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
if let user = chatPeer as? TelegramUser, user.botInfo == nil, canRemoveGlobally { if let user = chatPeer as? TelegramUser, user.botInfo == nil, canRemoveGlobally {
strongSelf.maybeAskForPeerChatRemoval(peer: peer, completion: { _ in }, removed: {}) strongSelf.maybeAskForPeerChatRemoval(peer: peer, completion: { _ in }, removed: {})
} else { } else {
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
var canClear = true var canClear = true
var canStop = false var canStop = false
@ -1468,7 +1468,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
} }
if canRemoveGlobally { if canRemoveGlobally {
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder)) 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 { if canRemoveGlobally {
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .delete, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder)) items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .delete, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder))

View File

@ -774,7 +774,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let enableChatListPhotos = item.context.sharedContext.immediateExperimentalUISettings.chatListPhotos 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 { enum ContentData {
case chat(itemPeer: RenderedPeer, peer: Peer?, hideAuthor: Bool, messageText: String) 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) 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) 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) 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 strongSelf.secretIconNode = iconNode
} }
iconNode.image = currentSecretIconImage 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 titleOffset += currentSecretIconImage.size.width + 3.0
} else if let secretIconNode = strongSelf.secretIconNode { } else if let secretIconNode = strongSelf.secretIconNode {
strongSelf.secretIconNode = nil strongSelf.secretIconNode = nil
@ -1616,7 +1619,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
override func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) { override func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) {
super.updateRevealOffset(offset: offset, transition: transition) 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 let editingOffset: CGFloat
if let selectableControlNode = self.selectableControlNode { if let selectableControlNode = self.selectableControlNode {
editingOffset = selectableControlNode.bounds.size.width editingOffset = selectableControlNode.bounds.size.width
@ -1635,14 +1638,17 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
transition.updateFrame(node: reorderControlNode, frame: reorderControlFrame) 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 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) let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + offset, dy: 0.0)
var avatarFrame = self.avatarNode.frame 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) transition.updateFrame(node: self.avatarNode, frame: avatarFrame)
var onlineFrame = self.onlineNode.frame var onlineFrame = self.onlineNode.frame

View File

@ -40,7 +40,9 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
processed = true processed = true
break inner break inner
case let .Audio(isVoice, _, title, performer, _): case let .Audio(isVoice, _, title, performer, _):
if isVoice { if !message.text.isEmpty {
messageText = "🎤 \(messageText)"
} else if isVoice {
if message.text.isEmpty { if message.text.isEmpty {
messageText = strings.Message_Audio messageText = strings.Message_Audio
} else { } else {

View File

@ -495,7 +495,7 @@ public class ContactsController: ViewController {
} }
} }
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: self.presentationData.strings.Contacts_SortBy)) items.append(ActionSheetTextItem(title: self.presentationData.strings.Contacts_SortBy))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByName, color: .accent, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByName, color: .accent, action: { [weak actionSheet] in

View File

@ -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)) 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) 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) contactsController.presentInGlobalOverlay(contextController)
} }

View File

@ -435,7 +435,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize) let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
let titleBoldFont = Font.medium(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 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 { if currentItem?.presentationData.theme !== item.presentationData.theme {
updatedTheme = 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 (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 let statusHeightComponent: CGFloat
if statusAttributedString == nil { if statusAttributedString == nil {
@ -624,7 +626,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
let titleFrame: CGRect let titleFrame: CGRect
if statusAttributedString != nil { 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 { } else {
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((nodeLayout.contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size) 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 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() let _ = titleApply()
transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame.offsetBy(dx: revealOffset, dy: 0.0)) transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame.offsetBy(dx: revealOffset, dy: 0.0))

View File

@ -3,8 +3,6 @@ import AsyncDisplayKit
import Display import Display
import TelegramPresentationData import TelegramPresentationData
private let textFont = Font.regular(17.0)
enum ContextActionSibling { enum ContextActionSibling {
case none case none
case item case item
@ -23,17 +21,19 @@ final class ContextActionNode: ASDisplayNode {
private let iconNode: ASImageNode private let iconNode: ASImageNode
private let buttonNode: HighlightTrackingButtonNode 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.action = action
self.getController = getController self.getController = getController
self.actionSelected = actionSelected self.actionSelected = actionSelected
let textFont = Font.regular(presentationData.fontSize.baseDisplaySize)
self.backgroundNode = ASDisplayNode() self.backgroundNode = ASDisplayNode()
self.backgroundNode.isAccessibilityElement = false self.backgroundNode.isAccessibilityElement = false
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor self.backgroundNode.backgroundColor = presentationData.theme.contextMenu.itemBackgroundColor
self.highlightedBackgroundNode = ASDisplayNode() self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isAccessibilityElement = false self.highlightedBackgroundNode.isAccessibilityElement = false
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor self.highlightedBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
self.highlightedBackgroundNode.alpha = 0.0 self.highlightedBackgroundNode.alpha = 0.0
self.textNode = ImmediateTextNode() self.textNode = ImmediateTextNode()
@ -43,9 +43,9 @@ final class ContextActionNode: ASDisplayNode {
let textColor: UIColor let textColor: UIColor
switch action.textColor { switch action.textColor {
case .primary: case .primary:
textColor = theme.contextMenu.primaryColor textColor = presentationData.theme.contextMenu.primaryColor
case .destructive: case .destructive:
textColor = theme.contextMenu.destructiveColor textColor = presentationData.theme.contextMenu.destructiveColor
} }
self.textNode.attributedText = NSAttributedString(string: action.text, font: textFont, textColor: textColor) self.textNode.attributedText = NSAttributedString(string: action.text, font: textFont, textColor: textColor)
@ -62,7 +62,7 @@ final class ContextActionNode: ASDisplayNode {
statusNode.isAccessibilityElement = false statusNode.isAccessibilityElement = false
statusNode.isUserInteractionEnabled = false statusNode.isUserInteractionEnabled = false
statusNode.displaysAsynchronously = 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 statusNode.maximumNumberOfLines = 1
self.statusNode = statusNode self.statusNode = statusNode
} }
@ -72,7 +72,7 @@ final class ContextActionNode: ASDisplayNode {
self.iconNode.displaysAsynchronously = false self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true self.iconNode.displayWithoutProcessing = true
self.iconNode.isUserInteractionEnabled = false self.iconNode.isUserInteractionEnabled = false
self.iconNode.image = action.icon(theme) self.iconNode.image = action.icon(presentationData.theme)
self.buttonNode = HighlightTrackingButtonNode() self.buttonNode = HighlightTrackingButtonNode()
self.buttonNode.isAccessibilityElement = true self.buttonNode.isAccessibilityElement = true
@ -149,27 +149,30 @@ final class ContextActionNode: ASDisplayNode {
} }
} }
func updateTheme(theme: PresentationTheme) { func updateTheme(presentationData: PresentationData) {
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor self.backgroundNode.backgroundColor = presentationData.theme.contextMenu.itemBackgroundColor
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor self.highlightedBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
let textColor: UIColor let textColor: UIColor
switch action.textColor { switch action.textColor {
case .primary: case .primary:
textColor = theme.contextMenu.primaryColor textColor = presentationData.theme.contextMenu.primaryColor
case .destructive: 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) self.textNode.attributedText = NSAttributedString(string: self.action.text, font: textFont, textColor: textColor)
switch self.action.textLayout { switch self.action.textLayout {
case let .secondLineWithValue(value): 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: default:
break break
} }
self.iconNode.image = self.action.icon(theme) self.iconNode.image = self.action.icon(presentationData.theme)
} }
@objc private func buttonPressed() { @objc private func buttonPressed() {

View File

@ -39,7 +39,7 @@ private enum ContextItemNode {
} }
final class ContextActionsContainerNode: ASDisplayNode { final class ContextActionsContainerNode: ASDisplayNode {
private let theme: PresentationTheme private let presentationData: PresentationData
private var effectView: UIVisualEffectView? private var effectView: UIVisualEffectView?
private var itemNodes: [ContextItemNode] private var itemNodes: [ContextItemNode]
private let feedbackTap: () -> Void private let feedbackTap: () -> Void
@ -47,23 +47,23 @@ final class ContextActionsContainerNode: ASDisplayNode {
private(set) var gesture: UIGestureRecognizer? private(set) var gesture: UIGestureRecognizer?
private var currentHighlightedActionNode: ContextActionNode? private var currentHighlightedActionNode: ContextActionNode?
init(theme: PresentationTheme, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void) { init(presentationData: PresentationData, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void) {
self.theme = theme self.presentationData = presentationData
self.feedbackTap = feedbackTap self.feedbackTap = feedbackTap
var itemNodes: [ContextItemNode] = [] var itemNodes: [ContextItemNode] = []
for i in 0 ..< items.count { for i in 0 ..< items.count {
switch items[i] { switch items[i] {
case let .action(action): 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] { if i != items.count - 1, case .action = items[i + 1] {
let separatorNode = ASDisplayNode() let separatorNode = ASDisplayNode()
separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor separatorNode.backgroundColor = presentationData.theme.contextMenu.itemSeparatorColor
itemNodes.append(.itemSeparator(separatorNode)) itemNodes.append(.itemSeparator(separatorNode))
} }
case .separator: case .separator:
let separatorNode = ASDisplayNode() let separatorNode = ASDisplayNode()
separatorNode.backgroundColor = theme.contextMenu.sectionSeparatorColor separatorNode.backgroundColor = presentationData.theme.contextMenu.sectionSeparatorColor
itemNodes.append(.separator(separatorNode)) itemNodes.append(.separator(separatorNode))
} }
} }
@ -75,7 +75,7 @@ final class ContextActionsContainerNode: ASDisplayNode {
self.clipsToBounds = true self.clipsToBounds = true
self.cornerRadius = 14.0 self.cornerRadius = 14.0
self.backgroundColor = theme.contextMenu.backgroundColor self.backgroundColor = presentationData.theme.contextMenu.backgroundColor
self.itemNodes.forEach({ itemNode in self.itemNodes.forEach({ itemNode in
switch itemNode { switch itemNode {
@ -133,7 +133,7 @@ final class ContextActionsContainerNode: ASDisplayNode {
if self.effectView == nil { if self.effectView == nil {
let effectView: UIVisualEffectView let effectView: UIVisualEffectView
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
if self.theme.overallDarkAppearance { if self.presentationData.theme.overallDarkAppearance {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialDark)) effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialDark))
} else { } else {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialLight)) effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialLight))
@ -213,19 +213,19 @@ final class ContextActionsContainerNode: ASDisplayNode {
return size return size
} }
func updateTheme(theme: PresentationTheme) { func updateTheme(presentationData: PresentationData) {
for itemNode in self.itemNodes { for itemNode in self.itemNodes {
switch itemNode { switch itemNode {
case let .action(action): case let .action(action):
action.updateTheme(theme: theme) action.updateTheme(presentationData: presentationData)
case let .separator(separator): case let .separator(separator):
separator.backgroundColor = theme.contextMenu.sectionSeparatorColor separator.backgroundColor = presentationData.theme.contextMenu.sectionSeparatorColor
case let .itemSeparator(itemSeparator): 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? { func actionNode(at point: CGPoint) -> ContextActionNode? {

View File

@ -60,8 +60,7 @@ private func convertFrame(_ frame: CGRect, from fromView: UIView, to toView: UIV
} }
private final class ContextControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { private final class ContextControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
private var theme: PresentationTheme private var presentationData: PresentationData
private var strings: PresentationStrings
private let source: ContextContentSource private let source: ContextContentSource
private var items: Signal<[ContextMenuItem], NoError> private var items: Signal<[ContextMenuItem], NoError>
private let beginDismiss: (ContextMenuActionResult) -> Void private let beginDismiss: (ContextMenuActionResult) -> Void
@ -108,9 +107,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
private let itemsDisposable = MetaDisposable() 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) { 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.theme = theme self.presentationData = presentationData
self.strings = strings
self.source = source self.source = source
self.items = items self.items = items
self.beginDismiss = beginDismiss self.beginDismiss = beginDismiss
@ -126,7 +124,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self.effectView = UIVisualEffectView() self.effectView = UIVisualEffectView()
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
} else { } else {
if theme.rootController.keyboardColor == .dark { if presentationData.theme.rootController.keyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark) self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) self.effectView.effect = UIBlurEffect(style: .light)
@ -135,7 +133,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
} }
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = theme.contextMenu.dimColor self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor
self.dimNode.alpha = 0.0 self.dimNode.alpha = 0.0
self.withoutBlurDimNode = ASDisplayNode() self.withoutBlurDimNode = ASDisplayNode()
@ -159,7 +157,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
var feedbackTap: (() -> Void)? 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 return controller
}, actionSelected: { result in }, actionSelected: { result in
beginDismiss(result) beginDismiss(result)
@ -168,7 +166,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
}) })
if !reactionItems.isEmpty { 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 self.reactionContextNode = reactionContextNode
} else { } else {
self.reactionContextNode = nil self.reactionContextNode = nil
@ -966,7 +964,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self.currentItems = items self.currentItems = items
let previousActionsContainerNode = self.actionsContainerNode 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() return self?.getController()
}, actionSelected: { [weak self] result in }, actionSelected: { [weak self] result in
self?.beginDismiss(result) self?.beginDismiss(result)
@ -988,11 +986,11 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
} }
} }
func updateTheme(theme: PresentationTheme) { func updateTheme(presentationData: PresentationData) {
self.theme = theme self.presentationData = presentationData
self.dimNode.backgroundColor = theme.contextMenu.dimColor self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor
self.actionsContainerNode.updateTheme(theme: theme) self.actionsContainerNode.updateTheme(presentationData: presentationData)
if let validLayout = self.validLayout { if let validLayout = self.validLayout {
self.updateLayout(layout: validLayout, transition: .immediate, previousActionsContainerNode: nil) self.updateLayout(layout: validLayout, transition: .immediate, previousActionsContainerNode: nil)
@ -1364,8 +1362,7 @@ public enum ContextContentSource {
public final class ContextController: ViewController, StandalonePresentableController { public final class ContextController: ViewController, StandalonePresentableController {
private let account: Account private let account: Account
private var theme: PresentationTheme private var presentationData: PresentationData
private var strings: PresentationStrings
private let source: ContextContentSource private let source: ContextContentSource
private var items: Signal<[ContextMenuItem], NoError> private var items: Signal<[ContextMenuItem], NoError>
private var reactionItems: [ReactionContextItem] private var reactionItems: [ReactionContextItem]
@ -1387,10 +1384,9 @@ public final class ContextController: ViewController, StandalonePresentableContr
public var reactionSelected: ((String) -> Void)? 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.account = account
self.theme = theme self.presentationData = presentationData
self.strings = strings
self.source = source self.source = source
self.items = items self.items = items
self.reactionItems = reactionItems self.reactionItems = reactionItems
@ -1407,7 +1403,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
} }
override public func loadDisplayNode() { 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) self?.dismiss(result: result, completion: nil)
}, recognizer: self.recognizer, gesture: self.gesture, reactionSelected: { [weak self] value in }, recognizer: self.recognizer, gesture: self.gesture, reactionSelected: { [weak self] value in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -1464,10 +1460,10 @@ public final class ContextController: ViewController, StandalonePresentableContr
} }
} }
public func updateTheme(theme: PresentationTheme) { public func updateTheme(presentationData: PresentationData) {
self.theme = theme self.presentationData = presentationData
if self.isNodeLoaded { if self.isNodeLoaded {
self.controllerNode.updateTheme(theme: theme) self.controllerNode.updateTheme(presentationData: presentationData)
} }
} }

View File

@ -20,11 +20,11 @@ public final class DateSelectionActionSheetController: ActionSheetController {
let theme = presentationData.theme let theme = presentationData.theme
let strings = presentationData.strings 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 self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { if let strongSelf = self {
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme) strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
} }
}) })

View File

@ -56,6 +56,8 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
let peerFont = Font.regular(floor(theme.baseFontSize * 14.0 / 17.0))
self.avatarNode = AvatarNode(font: avatarFont) self.avatarNode = AvatarNode(font: avatarFont)
self.avatarNode.isAccessibilityElement = false self.avatarNode.isAccessibilityElement = false
@ -88,9 +90,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
case .clearCache, .clearCacheSuggestion: case .clearCache, .clearCacheSuggestion:
switch action { switch action {
case .clearCache: 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: 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: default:
break break
} }
@ -115,9 +117,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
break break
} }
if let text = text { 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 { for (_, range) in text.1 {
formattedAttributedText.addAttribute(.font, value: Font.semibold(14.0), range: range) formattedAttributedText.addAttribute(.font, value: peerFont, range: range)
} }
attributedText = formattedAttributedText attributedText = formattedAttributedText
} }

View File

@ -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 { switch subject {
case .camera: case .camera:
let status = PGCamera.cameraAuthorizationStatus() let status = PGCamera.cameraAuthorizationStatus()
@ -382,7 +382,14 @@ public final class DeviceAccess {
})]), nil) })]), nil)
} }
case .notDetermined: case .notDetermined:
completion(true) switch locationSubject {
case .send:
locationManager?.requestWhenInUseAuthorization()
case .live:
locationManager?.requestAlwaysAuthorization()
default:
break
}
@unknown default: @unknown default:
fatalError() fatalError()
} }

View File

@ -47,8 +47,8 @@ public class ActionSheetButtonItem: ActionSheetItem {
public class ActionSheetButtonNode: ActionSheetItemNode { public class ActionSheetButtonNode: ActionSheetItemNode {
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
public static let defaultFont: UIFont = Font.regular(20.0) private let defaultFont: UIFont
public static let boldFont: UIFont = Font.medium(20.0) private let boldFont: UIFont
private var item: ActionSheetButtonItem? private var item: ActionSheetButtonItem?
@ -59,6 +59,9 @@ public class ActionSheetButtonNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) { override public init(theme: ActionSheetControllerTheme) {
self.theme = theme 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 = HighlightTrackingButton()
self.button.isAccessibilityElement = false self.button.isAccessibilityElement = false
@ -113,9 +116,9 @@ public class ActionSheetButtonNode: ActionSheetItemNode {
} }
switch item.font { switch item.font {
case .default: case .default:
textFont = ActionSheetButtonNode.defaultFont textFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
case .bold: 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.attributedText = NSAttributedString(string: item.title, font: textFont, textColor: textColor)
self.label.isAccessibilityElement = false self.label.isAccessibilityElement = false

View File

@ -39,7 +39,7 @@ public class ActionSheetCheckboxItem: ActionSheetItem {
} }
public class ActionSheetCheckboxItemNode: ActionSheetItemNode { public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
public static let defaultFont: UIFont = Font.regular(20.0) private let defaultFont: UIFont
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
@ -54,6 +54,7 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) { override public init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
self.defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton() self.button = HighlightTrackingButton()
self.button.isAccessibilityElement = false self.button.isAccessibilityElement = false
@ -118,8 +119,10 @@ public class ActionSheetCheckboxItemNode: ActionSheetItemNode {
func setItem(_ item: ActionSheetCheckboxItem) { func setItem(_ item: ActionSheetCheckboxItem) {
self.item = item self.item = item
self.titleNode.attributedText = NSAttributedString(string: item.title, font: ActionSheetCheckboxItemNode.defaultFont, textColor: self.theme.primaryTextColor) let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.labelNode.attributedText = NSAttributedString(string: item.label, font: ActionSheetCheckboxItemNode.defaultFont, textColor: self.theme.secondaryTextColor)
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.checkNode.isHidden = !item.value
self.accessibilityArea.accessibilityLabel = item.title self.accessibilityArea.accessibilityLabel = item.title

View File

@ -42,6 +42,7 @@ public class ActionSheetSwitchNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) { override public init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton() self.button = HighlightTrackingButton()
self.button.isAccessibilityElement = false self.button.isAccessibilityElement = false
@ -85,7 +86,9 @@ public class ActionSheetSwitchNode: ActionSheetItemNode {
func setItem(_ item: ActionSheetSwitchItem) { func setItem(_ item: ActionSheetSwitchItem) {
self.item = item 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.label.isAccessibilityElement = false
self.switchNode.isOn = item.isOn self.switchNode.isOn = item.isOn

View File

@ -26,7 +26,7 @@ public class ActionSheetTextItem: ActionSheetItem {
} }
public class ActionSheetTextNode: ActionSheetItemNode { public class ActionSheetTextNode: ActionSheetItemNode {
public static let defaultFont: UIFont = Font.regular(13.0) private let defaultFont: UIFont
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
@ -38,6 +38,7 @@ public class ActionSheetTextNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) { override public init(theme: ActionSheetControllerTheme) {
self.theme = theme self.theme = theme
self.defaultFont = Font.regular(floor(theme.baseFontSize * 13.0 / 17.0))
self.label = ASTextNode() self.label = ASTextNode()
self.label.isUserInteractionEnabled = false self.label.isUserInteractionEnabled = false
@ -60,7 +61,9 @@ public class ActionSheetTextNode: ActionSheetItemNode {
func setItem(_ item: ActionSheetTextItem) { func setItem(_ item: ActionSheetTextItem) {
self.item = item 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.accessibilityArea.accessibilityLabel = item.title
self.setNeedsLayout() self.setNeedsLayout()

View File

@ -21,8 +21,9 @@ public final class ActionSheetControllerTheme: Equatable {
public let switchFrameColor: UIColor public let switchFrameColor: UIColor
public let switchContentColor: UIColor public let switchContentColor: UIColor
public let switchHandleColor: 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.dimColor = dimColor
self.backgroundType = backgroundType self.backgroundType = backgroundType
self.itemBackgroundColor = itemBackgroundColor self.itemBackgroundColor = itemBackgroundColor
@ -37,6 +38,7 @@ public final class ActionSheetControllerTheme: Equatable {
self.switchFrameColor = switchFrameColor self.switchFrameColor = switchFrameColor
self.switchContentColor = switchContentColor self.switchContentColor = switchContentColor
self.switchHandleColor = switchHandleColor self.switchHandleColor = switchHandleColor
self.baseFontSize = min(26.0, baseFontSize)
} }
public static func ==(lhs: ActionSheetControllerTheme, rhs: ActionSheetControllerTheme) -> Bool { public static func ==(lhs: ActionSheetControllerTheme, rhs: ActionSheetControllerTheme) -> Bool {
@ -82,6 +84,9 @@ public final class ActionSheetControllerTheme: Equatable {
if lhs.switchHandleColor != rhs.switchHandleColor { if lhs.switchHandleColor != rhs.switchHandleColor {
return false return false
} }
if lhs.baseFontSize != rhs.baseFontSize {
return false
}
return true return true
} }
} }

View File

@ -14,6 +14,7 @@ public class ImmediateTextNode: TextNode {
public var lineSpacing: CGFloat = 0.0 public var lineSpacing: CGFloat = 0.0
public var insets: UIEdgeInsets = UIEdgeInsets() public var insets: UIEdgeInsets = UIEdgeInsets()
public var textShadowColor: UIColor? public var textShadowColor: UIColor?
public var textStroke: (UIColor, CGFloat)?
private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer? private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer?
private var linkHighlightingNode: LinkHighlightingNode? private var linkHighlightingNode: LinkHighlightingNode?
@ -35,7 +36,7 @@ public class ImmediateTextNode: TextNode {
public func updateLayout(_ constrainedSize: CGSize) -> CGSize { public func updateLayout(_ constrainedSize: CGSize) -> CGSize {
let makeLayout = TextNode.asyncLayout(self) 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() let _ = apply()
if layout.numberOfLines > 1 { if layout.numberOfLines > 1 {
self.trailingLineWidth = layout.trailingLineWidth self.trailingLineWidth = layout.trailingLineWidth

View File

@ -2413,7 +2413,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
//print("replay after \(self.itemNodes.map({"\($0.index) \(unsafeAddressOf($0))"}))") //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() self.stopScrolling()
for itemNode in self.itemNodes { for itemNode in self.itemNodes {

View File

@ -95,8 +95,9 @@ public final class TextNodeLayoutArguments {
public let insets: UIEdgeInsets public let insets: UIEdgeInsets
public let lineColor: UIColor? public let lineColor: UIColor?
public let textShadowColor: 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.attributedString = attributedString
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
self.minimumNumberOfLines = minimumNumberOfLines self.minimumNumberOfLines = minimumNumberOfLines
@ -109,6 +110,7 @@ public final class TextNodeLayoutArguments {
self.insets = insets self.insets = insets
self.lineColor = lineColor self.lineColor = lineColor
self.textShadowColor = textShadowColor self.textShadowColor = textShadowColor
self.textStroke = textStroke
} }
} }
@ -130,9 +132,10 @@ public final class TextNodeLayout: NSObject {
fileprivate let blockQuotes: [TextNodeBlockQuote] fileprivate let blockQuotes: [TextNodeBlockQuote]
fileprivate let lineColor: UIColor? fileprivate let lineColor: UIColor?
fileprivate let textShadowColor: UIColor? fileprivate let textShadowColor: UIColor?
fileprivate let textStroke: (UIColor, CGFloat)?
public let hasRTL: Bool 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.attributedString = attributedString
self.maximumNumberOfLines = maximumNumberOfLines self.maximumNumberOfLines = maximumNumberOfLines
self.truncationType = truncationType self.truncationType = truncationType
@ -150,6 +153,7 @@ public final class TextNodeLayout: NSObject {
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
self.lineColor = lineColor self.lineColor = lineColor
self.textShadowColor = textShadowColor self.textShadowColor = textShadowColor
self.textStroke = textStroke
var hasRTL = false var hasRTL = false
for line in lines { for line in lines {
if line.isRTL { 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 { if let attributedString = attributedString {
let stringLength = attributedString.length let stringLength = attributedString.length
@ -806,7 +810,7 @@ public class TextNode: ASDisplayNode {
var maybeTypesetter: CTTypesetter? var maybeTypesetter: CTTypesetter?
maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString) maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString)
if maybeTypesetter == nil { 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! 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 { } 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) 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 textMatrix = context.textMatrix
let textPosition = context.textPosition let textPosition = context.textPosition
context.textMatrix = CGAffineTransform(scaleX: 1.0, y: -1.0) context.textMatrix = CGAffineTransform(scaleX: 1.0, y: -1.0)
@ -1156,11 +1168,11 @@ public class TextNode: ASDisplayNode {
if stringMatch { if stringMatch {
layout = existingLayout layout = existingLayout
} else { } 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 updated = true
} }
} else { } 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 updated = true
} }

View File

@ -62,6 +62,7 @@ open class TooltipController: ViewController, StandalonePresentableController {
} }
public private(set) var content: TooltipControllerContent public private(set) var content: TooltipControllerContent
private let baseFontSize: CGFloat
open func updateContent(_ content: TooltipControllerContent, animated: Bool, extendTimer: Bool, arrowOnBottom: Bool = true) { open func updateContent(_ content: TooltipControllerContent, animated: Bool, extendTimer: Bool, arrowOnBottom: Bool = true) {
if self.content != content { if self.content != content {
@ -89,8 +90,9 @@ open class TooltipController: ViewController, StandalonePresentableController {
public var dismissed: ((Bool) -> Void)? 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.content = content
self.baseFontSize = baseFontSize
self.timeout = timeout self.timeout = timeout
self.dismissByTapOutside = dismissByTapOutside self.dismissByTapOutside = dismissByTapOutside
self.dismissByTapOutsideSource = dismissByTapOutsideSource self.dismissByTapOutsideSource = dismissByTapOutsideSource
@ -111,7 +113,7 @@ open class TooltipController: ViewController, StandalonePresentableController {
} }
override open func loadDisplayNode() { 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) self?.dismiss(tappedInside: tappedInside)
}, dismissByTapOutside: self.dismissByTapOutside, dismissByTapOutsideSource: self.dismissByTapOutsideSource) }, dismissByTapOutside: self.dismissByTapOutside, dismissByTapOutsideSource: self.dismissByTapOutsideSource)
self.controllerNode.arrowOnBottom = self.initialArrowOnBottom self.controllerNode.arrowOnBottom = self.initialArrowOnBottom

View File

@ -3,6 +3,8 @@ import UIKit
import AsyncDisplayKit import AsyncDisplayKit
final class TooltipControllerNode: ASDisplayNode { final class TooltipControllerNode: ASDisplayNode {
private let baseFontSize: CGFloat
private let dismiss: (Bool) -> Void private let dismiss: (Bool) -> Void
private var validLayout: ContainerViewLayout? private var validLayout: ContainerViewLayout?
@ -19,7 +21,9 @@ final class TooltipControllerNode: ASDisplayNode {
private var dismissedByTouchOutside = false private var dismissedByTouchOutside = false
private var dismissByTapOutsideSource = 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.dismissByTapOutside = dismissByTapOutside
self.dismissByTapOutsideSource = dismissByTapOutsideSource self.dismissByTapOutsideSource = dismissByTapOutsideSource
@ -33,7 +37,7 @@ final class TooltipControllerNode: ASDisplayNode {
if case let .attributedText(text) = content { if case let .attributedText(text) = content {
self.textNode.attributedText = text self.textNode.attributedText = text
} else { } 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.isUserInteractionEnabled = false
self.textNode.displaysAsynchronously = 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.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 { if let layout = self.validLayout {
self.containerLayoutUpdated(layout, transition: transition) self.containerLayoutUpdated(layout, transition: transition)
} }

View File

@ -529,7 +529,11 @@ public enum ViewControllerNavigationPresentation {
} }
open func dismiss(completion: (() -> Void)? = nil) { 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, *) @available(iOSApplicationExtension 9.0, iOS 9.0, *)

View File

@ -272,6 +272,8 @@ public class Window1 {
public var previewThemeAccentColor: UIColor = .blue public var previewThemeAccentColor: UIColor = .blue
public var previewThemeDarkBlur: Bool = false public var previewThemeDarkBlur: Bool = false
private var shouldNotAnimateLikelyKeyboardAutocorrectionSwitch: Bool = false
public private(set) var forceInCallStatusBarText: String? = nil public private(set) var forceInCallStatusBarText: String? = nil
public var inCallNavigate: (() -> Void)? { public var inCallNavigate: (() -> Void)? {
didSet { didSet {
@ -522,7 +524,15 @@ public class Window1 {
transitionCurve = .easeInOut 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
}
}
} }

View File

@ -106,6 +106,7 @@ class CaptionScrollWrapperNode: ASDisplayNode {
final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScrollViewDelegate { final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScrollViewDelegate {
private let context: AccountContext private let context: AccountContext
private var presentationData: PresentationData
private var theme: PresentationTheme private var theme: PresentationTheme
private var strings: PresentationStrings private var strings: PresentationStrings
private var nameOrder: PresentationPersonNameOrder private var nameOrder: PresentationPersonNameOrder
@ -243,6 +244,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
init(context: AccountContext, presentationData: PresentationData) { init(context: AccountContext, presentationData: PresentationData) {
self.context = context self.context = context
self.presentationData = presentationData
self.theme = presentationData.theme self.theme = presentationData.theme
self.strings = presentationData.strings self.strings = presentationData.strings
self.nameOrder = presentationData.nameDisplayOrder 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] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -787,7 +789,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
private func commitDeleteMessages(_ messages: [Message], ask: Bool) { 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 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 { 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 items: [ActionSheetItem] = []
var personalPeerName: String? var personalPeerName: String?
var isChannel = false 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] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: singleText, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()

View File

@ -609,7 +609,7 @@ public class GalleryController: ViewController, StandalonePresentableController
} else if canOpenIn { } else if canOpenIn {
openText = strongSelf.presentationData.strings.Conversation_FileOpenIn openText = strongSelf.presentationData.strings.Conversation_FileOpenIn
} }
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: cleanUrl)) items.append(ActionSheetTextItem(title: cleanUrl))
@ -652,7 +652,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])]) ])])
strongSelf.present(actionSheet, in: .window(.root)) strongSelf.present(actionSheet, in: .window(.root))
case let .peerMention(peerId, mention): case let .peerMention(peerId, mention):
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
if !mention.isEmpty { if !mention.isEmpty {
items.append(ActionSheetTextItem(title: mention)) items.append(ActionSheetTextItem(title: mention))
@ -677,7 +677,7 @@ public class GalleryController: ViewController, StandalonePresentableController
])]) ])])
strongSelf.present(actionSheet, in: .window(.root)) strongSelf.present(actionSheet, in: .window(.root))
case let .textMention(mention): case let .textMention(mention):
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: mention), ActionSheetTextItem(title: mention),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in 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)) strongSelf.present(actionSheet, in: .window(.root))
case let .botCommand(command): case let .botCommand(command):
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: command)) items.append(ActionSheetTextItem(title: command))
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in 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)) strongSelf.present(actionSheet, in: .window(.root))
case let .hashtag(peerName, hashtag): case let .hashtag(peerName, hashtag):
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: hashtag), ActionSheetTextItem(title: hashtag),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in 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)) strongSelf.present(actionSheet, in: .window(.root))
case let .timecode(timecode, text): case let .timecode(timecode, text):
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: text), ActionSheetTextItem(title: text),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in

View File

@ -2,6 +2,19 @@ import Foundation
import CoreLocation import CoreLocation
import SwiftSignalKit 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> { public func geocodeLocation(dictionary: [String: String]) -> Signal<(Double, Double)?, NoError> {
return Signal { subscriber in return Signal { subscriber in
let geocoder = CLGeocoder() let geocoder = CLGeocoder()

View File

@ -260,7 +260,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
if let strongSelf = self { if let strongSelf = self {
let canOpenIn = availableOpenInOptions(context: context, item: .url(url: url.url)).count > 1 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 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: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: url.url), ActionSheetTextItem(title: url.url),
ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in

View File

@ -323,7 +323,7 @@ func instantPageThemeForType(_ type: InstantPageThemeType, settings: InstantPage
extension ActionSheetControllerTheme { extension ActionSheetControllerTheme {
convenience init(instantPageTheme: InstantPageTheme) { 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)
} }
} }

View File

@ -178,22 +178,7 @@ public final class ItemListPresentationData: Equatable {
public extension PresentationFontSize { public extension PresentationFontSize {
var itemListBaseHeaderFontSize: CGFloat { var itemListBaseHeaderFontSize: CGFloat {
switch self { return floor(self.itemListBaseFontSize * 13.0 / 17.0)
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
}
} }
var itemListBaseFontSize: CGFloat { var itemListBaseFontSize: CGFloat {

View File

@ -14,24 +14,46 @@ public final class ItemListVenueItem: ListViewItem, ItemListItem {
let presentationData: ItemListPresentationData let presentationData: ItemListPresentationData
let account: Account let account: Account
let venue: TelegramMediaMap let venue: TelegramMediaMap
let title: String?
public let sectionId: ItemListSectionId let subtitle: String?
let style: ItemListStyle let style: ItemListStyle
let action: (() -> Void)? 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.presentationData = presentationData
self.account = account self.account = account
self.venue = venue self.venue = venue
self.title = title
self.subtitle = subtitle
self.sectionId = sectionId self.sectionId = sectionId
self.style = style self.style = style
self.action = action 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) { 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 { 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 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.contentSize = layout.contentSize
node.insets = layout.insets node.insets = layout.insets
@ -55,7 +77,21 @@ public final class ItemListVenueItem: ListViewItem, ItemListItem {
} }
async { 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 { Queue.mainQueue().async {
completion(layout, { _ in completion(layout, { _ in
apply() apply()
@ -84,8 +120,10 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
private let iconNode: TransformImageNode private let iconNode: TransformImageNode
private let titleNode: TextNode private let titleNode: TextNode
private let addressNode: 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? public var tag: ItemListItemTag?
@ -120,6 +158,8 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
self.addressNode.contentMode = .left self.addressNode.contentMode = .left
self.addressNode.contentsScale = UIScreen.main.scale self.addressNode.contentsScale = UIScreen.main.scale
self.infoButton = HighlightableButtonNode()
self.highlightedBackgroundNode = ASDisplayNode() self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true self.highlightedBackgroundNode.isLayerBacked = true
@ -130,16 +170,19 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
self.addSubnode(self.iconNode) self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode) self.addSubnode(self.titleNode)
self.addSubnode(self.addressNode) 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 makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeAddressLayout = TextNode.asyncLayout(self.addressNode) let makeAddressLayout = TextNode.asyncLayout(self.addressNode)
let iconLayout = self.iconNode.asyncLayout() let iconLayout = self.iconNode.asyncLayout()
let currentItem = self.layoutParams?.0 let currentItem = self.layoutParams?.0
return { item, params, neighbors in return { item, params, neighbors, firstWithHeader, last in
var updatedTheme: PresentationTheme? var updatedTheme: PresentationTheme?
var updatedVenueType: String? var updatedVenueType: String?
@ -155,11 +198,29 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
updatedVenueType = venueType updatedVenueType = venueType
} }
let titleAttributedString = NSAttributedString(string: item.venue.venue?.title ?? "", font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor) let title: String
let addressAttributedString = NSAttributedString(string: item.venue.venue?.address ?? "", font: addressFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor) 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 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 verticalInset: CGFloat = addressAttributedString.string.isEmpty ? 14.0 : 8.0
let iconSize: CGFloat = 40.0 let iconSize: CGFloat = 40.0
@ -179,6 +240,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
insets = itemListNeighborsPlainInsets(neighbors) insets = itemListNeighborsPlainInsets(neighbors)
insets.top = firstWithHeader ? 29.0 : 0.0
insets.bottom = 0.0 insets.bottom = 0.0
case .blocks: case .blocks:
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
@ -193,7 +255,8 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
return (layout, { [weak self] in return (layout, { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.layoutParams = (item, params, neighbors) strongSelf.item = item
strongSelf.layoutParams = (item, params, neighbors, firstWithHeader, last)
strongSelf.accessibilityLabel = titleAttributedString.string strongSelf.accessibilityLabel = titleAttributedString.string
strongSelf.accessibilityValue = addressAttributedString.string strongSelf.accessibilityValue = addressAttributedString.string
@ -203,6 +266,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor 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 let transition = ContainedViewLayoutTransition.immediate
@ -239,7 +303,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
stripeInset = leftInset stripeInset = leftInset
} }
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: stripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - stripeInset, height: separatorHeight)) 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: case .blocks:
if strongSelf.backgroundNode.supernode == nil { if strongSelf.backgroundNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) 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.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)) 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) { override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) 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
}
} }

View File

@ -257,7 +257,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
if (_cameraView) if (_cameraView)
[_collectionView addSubview:_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; __strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
if (strongSelf != nil && strongSelf.sendPressed != nil) if (strongSelf != nil && strongSelf.sendPressed != nil)
@ -272,7 +272,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
if (!_document) 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; __strong TGAttachmentCarouselItemView *strongSelf = weakSelf;
if (strongSelf != nil && strongSelf.sendPressed != nil) if (strongSelf != nil && strongSelf.sendPressed != nil)

View File

@ -1050,7 +1050,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
NSArray *items = @ 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -1063,7 +1063,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
[strongController dismissAnimated:true manual:false completion:nil]; [strongController dismissAnimated:true manual:false completion:nil];
[strongSelf beginTransitionOutWithVelocity:0.0f]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -64,7 +64,7 @@
sendTitle = [NSString stringWithFormat:format, [NSString stringWithFormat:@"%ld", photosCount]]; 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; __strong TGClipboardPreviewItemView *strongPreviewItem = weakPreviewItem;
completed(strongPreviewItem.selectionContext, strongPreviewItem.editingContext, nil); completed(strongPreviewItem.selectionContext, strongPreviewItem.editingContext, nil);
@ -90,7 +90,7 @@
[strongPreviewItem setCollapsed:count == 0 animated:true]; [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; __strong TGMenuSheetController *strongController = weakController;
[strongController dismissAnimated:true]; [strongController dismissAnimated:true];

View File

@ -167,12 +167,14 @@ const CGFloat TGLocationInfoCellHeight = 134.0f;
_titleLabel.text = location.venue.title.length > 0 ? location.venue.title : TGLocalized(@"Map.Location"); _titleLabel.text = location.venue.title.length > 0 ? location.venue.title : TGLocalized(@"Map.Location");
UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor];
if (color != nil) { if (color != nil) {
[_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], color)]; [_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], color)];
pinColor = [UIColor whiteColor];
} }
if (location.venue.type.length > 0 && [location.venue.provider isEqualToString:@"foursquare"]) 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:@""]; SSignal *addressSignal = [SSignal single:@""];
if (location.venue.address.length > 0) if (location.venue.address.length > 0)

View File

@ -23,7 +23,7 @@
{ {
bool isUser = [peer isKindOfClass:[TGUser class]]; bool isUser = [peer isKindOfClass:[TGUser class]];
NSString *title = isUser ? ((TGUser *)peer).displayName : ((TGConversation *)peer).chatTitle; 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) if (self != nil)
{ {
_label = [[UILabel alloc] init]; _label = [[UILabel alloc] init];

View File

@ -491,7 +491,7 @@ const CGFloat TGLocationMapInset = 100.0f;
[itemViews addObject:titleItem]; [itemViews addObject:titleItem];
__weak TGMenuSheetController *weakController = controller; __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; __strong TGLocationMapViewController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -508,7 +508,7 @@ const CGFloat TGLocationMapInset = 100.0f;
}]; }];
[itemViews addObject:for15MinutesItem]; [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; __strong TGLocationMapViewController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -525,7 +525,7 @@ const CGFloat TGLocationMapInset = 100.0f;
}]; }];
[itemViews addObject:for1HourItem]; [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; __strong TGLocationMapViewController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -542,7 +542,7 @@ const CGFloat TGLocationMapInset = 100.0f;
}]; }];
[itemViews addObject:for8HoursItem]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)

View File

@ -266,14 +266,16 @@ NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation";
_iconView.hidden = false; _iconView.hidden = false;
UIColor *color = _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2); UIColor *color = _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2);
UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor];
if (locationAnnotation.color != nil) { if (locationAnnotation.color != nil) {
color = locationAnnotation.color; color = locationAnnotation.color;
pinColor = [UIColor whiteColor];
} }
_backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), color); _backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), color);
if (location.venue.type.length > 0) 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 else
{ {

View File

@ -742,7 +742,7 @@
NSMutableArray *itemViews = [[NSMutableArray alloc] init]; NSMutableArray *itemViews = [[NSMutableArray alloc] init];
__weak TGMenuSheetController *weakController = controller; __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; __strong TGLocationViewController *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -757,7 +757,7 @@
}]; }];
[itemViews addObject:openItem]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -770,7 +770,7 @@
}]; }];
[itemViews addObject:shareItem]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -870,7 +870,7 @@
__weak TGMenuSheetController *weakController = controller; __weak TGMenuSheetController *weakController = controller;
NSArray *items = @ 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -879,7 +879,7 @@
[strongController dismissAnimated:true]; [strongController dismissAnimated:true];
block(); 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -128,7 +128,7 @@
}; };
[itemViews addObject:carouselItem]; [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; __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -145,7 +145,7 @@
if (_hasSearchButton) 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; __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -164,7 +164,7 @@
if (_hasViewButton) 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; __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -182,7 +182,7 @@
if (_hasDeleteButton) 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; __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)
@ -198,7 +198,7 @@
[itemViews addObject:deleteItem]; [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; __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
if (strongSelf == nil) if (strongSelf == nil)

View File

@ -609,7 +609,7 @@
NSArray *items = @ 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -624,7 +624,7 @@
[strongController dismissAnimated:true manual:false completion:nil]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -21,7 +21,7 @@ typedef enum
@property (nonatomic, copy) void (^action)(void); @property (nonatomic, copy) void (^action)(void);
@property (nonatomic, assign) bool thickDivider; @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; @property (nonatomic, assign) bool collapsed;
- (void)setCollapsed:(bool)collapsed animated:(bool)animated; - (void)setCollapsed:(bool)collapsed animated:(bool)animated;

View File

@ -16,6 +16,7 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
bool _dark; bool _dark;
bool _requiresDivider; bool _requiresDivider;
UIView *_customDivider; UIView *_customDivider;
CGFloat _fontSize;
TGMenuSheetPallete *_pallete; TGMenuSheetPallete *_pallete;
} }
@ -23,12 +24,13 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
@implementation TGMenuSheetButtonItemView @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]; self = [super initWithType:(type == TGMenuSheetButtonTypeCancel) ? TGMenuSheetItemTypeFooter : TGMenuSheetItemTypeDefault];
if (self != nil) if (self != nil)
{ {
self.action = action; self.action = action;
_fontSize = fontSize;
_buttonType = type; _buttonType = type;
_requiresDivider = true; _requiresDivider = true;
@ -115,7 +117,7 @@ const CGFloat TGMenuSheetButtonItemViewHeight = 57.0f;
- (void)_updateForType:(TGMenuSheetButtonType)type - (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(); UIColor *accentColor = _dark ? UIColorRGB(0x4fbcff) : TGAccentColor();
if (_pallete != nil) if (_pallete != nil)
accentColor = _pallete.accentColor; accentColor = _pallete.accentColor;

View File

@ -84,7 +84,7 @@
}; };
[itemViews addObject:carouselItem]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -101,7 +101,7 @@
if (iosMajorVersion() >= 8 && intent != TGPassportAttachIntentSelfie) 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -124,7 +124,7 @@
} }
carouselItem.remainingHeight = TGMenuSheetButtonItemViewHeight * (itemViews.count - 1); 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)

View File

@ -625,8 +625,8 @@ NSString * const TGPhotoCropOriginalAspectRatio = @"original";
}; };
NSMutableArray *items = [[NSMutableArray alloc] init]; 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.CropAspectRatioOriginal") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^{ action(TGPhotoCropOriginalAspectRatio); }]];
[items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioSquare") type:TGMenuSheetButtonTypeDefault action:^{ action(@"1.0"); }]]; [items addObject:[[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"PhotoEditor.CropAspectRatioSquare") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^{ action(@"1.0"); }]];
CGSize croppedImageSize = _cropView.cropRect.size; CGSize croppedImageSize = _cropView.cropRect.size;
if (_cropView.cropOrientation == UIImageOrientationLeft || _cropView.cropOrientation == UIImageOrientationRight) if (_cropView.cropOrientation == UIImageOrientationLeft || _cropView.cropOrientation == UIImageOrientationRight)
@ -666,10 +666,10 @@ NSString * const TGPhotoCropOriginalAspectRatio = @"original";
ratio = heightComponent / widthComponent; 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -1341,7 +1341,7 @@
NSArray *items = @ 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -1352,7 +1352,7 @@
dismiss(); 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -550,7 +550,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
__weak TGPhotoPaintController *weakSelf = self; __weak TGPhotoPaintController *weakSelf = self;
NSArray *items = @ 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; __strong TGMenuSheetController *strongController = weakController;
if (strongController == nil) if (strongController == nil)
@ -570,7 +570,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
[strongController dismissAnimated:true manual:false completion:nil]; [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; __strong TGMenuSheetController *strongController = weakController;
if (strongController != nil) if (strongController != nil)

View File

@ -37,7 +37,7 @@
__weak TGMenuSheetController *weakController = controller; __weak TGMenuSheetController *weakController = controller;
__weak TGSecretTimerPickerItemView *weakTimerItem = timerItem; __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; __strong TGSecretTimerPickerItemView *strongTimerItem = weakTimerItem;
if (strongTimerItem != nil) if (strongTimerItem != nil)

View File

@ -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 { 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 isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
let controller = TGMenuSheetController(context: parentController.context, dark: false)! 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: []) carouselItem.editingContext.setInitialCaption(initialCaption, entities: [])
itemViews.append(carouselItem) 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) controller?.dismiss(animated: true)
openGallery() openGallery()
})! })!
@ -117,7 +119,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
} }
if !editing { 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) controller?.dismiss(animated: true)
openFileGallery() openFileGallery()
})! })!
@ -126,7 +128,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
} }
if canEditCurrent { 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) controller?.dismiss(animated: true)
openFileGallery() openFileGallery()
})! })!
@ -134,21 +136,21 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
} }
if editMediaOptions == nil { 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) controller?.dismiss(animated: true)
openMap() openMap()
})! })!
itemViews.append(locationItem) itemViews.append(locationItem)
if (peer is TelegramGroup || peer is TelegramChannel) && canSendMessagesToPeer(peer) && canSendPolls { 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) controller?.dismiss(animated: true)
openPoll() openPoll()
})! })!
itemViews.append(pollItem) 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) controller?.dismiss(animated: true)
openContacts() openContacts()
})! })!
@ -162,7 +164,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
let peer = recentlyUsedInlineBots[i] let peer = recentlyUsedInlineBots[i]
let addressName = peer.addressName let addressName = peer.addressName
if let addressName = 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) controller?.dismiss(animated: true)
selectRecentlyUsedInlineBot(peer) selectRecentlyUsedInlineBot(peer)
@ -175,7 +177,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
carouselItemView?.remainingHeight = TGMenuSheetButtonItemViewHeight * CGFloat(itemViews.count - 1) 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) controller?.dismiss(animated: true)
})! })!
itemViews.append(cancelItem) itemViews.append(cancelItem)

View File

@ -134,9 +134,14 @@ private let venueColors: [String: UIColor] = [
"parks_outdoors": UIColor(rgb: 0x6cc039), "parks_outdoors": UIColor(rgb: 0x6cc039),
"shops": UIColor(rgb: 0xffb300), "shops": UIColor(rgb: 0xffb300),
"travel": UIColor(rgb: 0x1c9fff), "travel": UIColor(rgb: 0x1c9fff),
"work": UIColor(rgb: 0xad7854),
"home": UIColor(rgb: 0x00aeef)
] ]
public func venueIconColor(type: String) -> UIColor { public func venueIconColor(type: String) -> UIColor {
if type.isEmpty {
return UIColor(rgb: 0x008df2)
}
if let color = venueColors[type] { if let color = venueColors[type] {
return color 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> { 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 data |> map { data in
return { arguments in return { arguments in
let context = DrawingContext(size: arguments.drawingSize, clear: true) 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 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) 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)) 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 { } else if isBuiltinIcon {
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)) 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))
}
} }
} }

View File

@ -29,6 +29,9 @@ static_library(
"//submodules/MergeLists:MergeLists", "//submodules/MergeLists:MergeLists",
"//submodules/TelegramUIPreferences:TelegramUIPreferences", "//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/SearchBarNode:SearchBarNode", "//submodules/SearchBarNode:SearchBarNode",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/DeviceAccess:DeviceAccess",
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
], ],
frameworks = [ frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -80,6 +80,7 @@ class LocationPinAnnotationView: MKAnnotationView {
let smallIconNode: TransformImageNode let smallIconNode: TransformImageNode
let dotNode: ASImageNode let dotNode: ASImageNode
var avatarNode: AvatarNode? var avatarNode: AvatarNode?
var labelNode: ImmediateTextNode?
var appeared = false var appeared = false
var animating = false var animating = false
@ -226,6 +227,29 @@ class LocationPinAnnotationView: MKAnnotationView {
self.dotNode.alpha = 1.0 self.dotNode.alpha = 1.0
self.dotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) 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 { } else {
let avatarSnapshot = self.avatarNode?.view.snapshotContentTree() let avatarSnapshot = self.avatarNode?.view.snapshotContentTree()
if let avatarSnapshot = avatarSnapshot, let avatarNode = self.avatarNode { if let avatarSnapshot = avatarSnapshot, let avatarNode = self.avatarNode {
@ -268,6 +292,13 @@ class LocationPinAnnotationView: MKAnnotationView {
let previousAlpha = self.dotNode.alpha let previousAlpha = self.dotNode.alpha
self.dotNode.alpha = 0.0 self.dotNode.alpha = 0.0
self.dotNode.layer.animateAlpha(from: previousAlpha, to: 0.0, duration: 0.2) 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 { } else {
self.smallNode.isHidden = selected 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) { func setPeer(account: Account, theme: PresentationTheme, peer: Peer) {
let avatarNode: AvatarNode let avatarNode: AvatarNode
if let currentAvatarNode = self.avatarNode { if let currentAvatarNode = self.avatarNode {
avatarNode = currentAvatarNode avatarNode = currentAvatarNode
} else { } else {
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 24.0)) avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 24.0))
avatarNode.isLayerBacked = false
avatarNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 55.0, height: 55.0)) avatarNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 55.0, height: 55.0))
avatarNode.position = CGPoint() avatarNode.position = CGPoint()
self.avatarNode = avatarNode self.avatarNode = avatarNode
@ -332,19 +326,23 @@ class LocationPinAnnotationView: MKAnnotationView {
avatarNode.setPeer(account: account, theme: theme, peer: peer) avatarNode.setPeer(account: account, theme: theme, peer: peer)
} }
private var raised = false var isRaised = false
func setRaised(_ raised: Bool, animated: Bool, completion: @escaping () -> Void = {}) { func setRaised(_ raised: Bool, animated: Bool, completion: @escaping () -> Void = {}) {
guard raised != self.raised else { guard raised != self.isRaised else {
return return
} }
self.raised = raised self.isRaised = raised
self.shadowNode.layer.removeAllAnimations() self.shadowNode.layer.removeAllAnimations()
if animated { if animated {
self.animating = true
if raised { if raised {
let previousPosition = self.shadowNode.position 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 { if finished {
completion() 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: { 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) self.shadowNode.position = CGPoint(x: UIScreenPixel, y: -36.0)
}) { finished in }) { finished in
self.animating = false
if finished { if finished {
completion() completion()
} }
@ -396,7 +395,6 @@ class LocationPinAnnotationView: MKAnnotationView {
self.addSubnode(avatarNode) self.addSubnode(avatarNode)
} }
self.animating = false self.animating = false
self.setNeedsLayout()
} }
} }
@ -405,4 +403,42 @@ class LocationPinAnnotationView: MKAnnotationView {
self.dotNode.isHidden = !custom 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
}
}
}
} }

View File

@ -100,19 +100,21 @@ final class LocationMapHeaderNode: ASDisplayNode {
self.shadowNode.image = generateShadowImage(theme: presentationData.theme, highlighted: false) self.shadowNode.image = generateShadowImage(theme: presentationData.theme, highlighted: false)
} }
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, padding: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) { func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: 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)) 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)) 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 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.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)) 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 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) alphaTransition.updateAlpha(node: self.optionsBackgroundNode, alpha: optionsAlpha)
} }

View File

@ -39,10 +39,13 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
private let pickerAnnotationContainerView: PickerAnnotationContainerView private let pickerAnnotationContainerView: PickerAnnotationContainerView
private weak var userLocationAnnotationView: MKAnnotationView? private weak var userLocationAnnotationView: MKAnnotationView?
private let pinDisposable = MetaDisposable()
private var mapView: MKMapView? { private var mapView: MKMapView? {
return self.view as? MKMapView return self.view as? MKMapView
} }
var returnedToUserLocation = true
var ignoreRegionChanges = false var ignoreRegionChanges = false
var isDragging = false var isDragging = false
var beganInteractiveDragging: (() -> Void)? 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.mapView?.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: offset.y, left: offset.x, bottom: 0.0, right: 0.0), animated: animated)
} }
self.ignoreRegionChanges = false self.ignoreRegionChanges = false
if isUserLocation && !self.returnedToUserLocation {
self.returnedToUserLocation = true
self.pickerAnnotationView?.setRaised(true, animated: true)
}
} }
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
@ -111,13 +119,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
for gestureRecognizer in gestureRecognizers { for gestureRecognizer in gestureRecognizers {
if gestureRecognizer.state == .began || gestureRecognizer.state == .ended { if gestureRecognizer.state == .began || gestureRecognizer.state == .ended {
self.isDragging = true self.isDragging = true
self.returnedToUserLocation = false
self.beganInteractiveDragging?() self.beganInteractiveDragging?()
if self.hasPickerAnnotation { if self.hasPickerAnnotation {
self.customUserLocationAnnotationView?.isHidden = true self.customUserLocationAnnotationView?.isHidden = true
self.pickerAnnotationContainerView.isHidden = false 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.resetAnnotationSelection()
self.resetScheduledPin()
} }
break break
} }
@ -125,9 +138,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
} }
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { 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.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() { private func schedulePin(wasDragging: Bool) {
super.layout() let timeout: Double = wasDragging ? 0.38 : 0.05
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) 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 { 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)
} }
} }
} }

View File

@ -10,6 +10,8 @@ import TelegramPresentationData
import AccountContext import AccountContext
import AppBundle import AppBundle
import CoreLocation import CoreLocation
import PresentationDataUtils
import DeviceAccess
public enum LocationPickerMode { public enum LocationPickerMode {
case share(peer: Peer?, selfPeer: Peer?, hasLiveLocation: Bool) case share(peer: Peer?, selfPeer: Peer?, hasLiveLocation: Bool)
@ -23,24 +25,28 @@ class LocationPickerInteraction {
let toggleMapModeSelection: () -> Void let toggleMapModeSelection: () -> Void
let updateMapMode: (LocationMapMode) -> Void let updateMapMode: (LocationMapMode) -> Void
let goToUserLocation: () -> Void let goToUserLocation: () -> Void
let goToCoordinate: (CLLocationCoordinate2D) -> Void
let openSearch: () -> Void let openSearch: () -> Void
let updateSearchQuery: (String) -> Void let updateSearchQuery: (String) -> Void
let dismissSearch: () -> Void let dismissSearch: () -> Void
let dismissInput: () -> Void let dismissInput: () -> Void
let updateSendActionHighlight: (Bool) -> 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.sendLocation = sendLocation
self.sendLiveLocation = sendLiveLocation self.sendLiveLocation = sendLiveLocation
self.sendVenue = sendVenue self.sendVenue = sendVenue
self.toggleMapModeSelection = toggleMapModeSelection self.toggleMapModeSelection = toggleMapModeSelection
self.updateMapMode = updateMapMode self.updateMapMode = updateMapMode
self.goToUserLocation = goToUserLocation self.goToUserLocation = goToUserLocation
self.goToCoordinate = goToCoordinate
self.openSearch = openSearch self.openSearch = openSearch
self.updateSearchQuery = updateSearchQuery self.updateSearchQuery = updateSearchQuery
self.dismissSearch = dismissSearch self.dismissSearch = dismissSearch
self.dismissInput = dismissInput self.dismissInput = dismissInput
self.updateSendActionHighlight = updateSendActionHighlight self.updateSendActionHighlight = updateSendActionHighlight
self.openHomeWorkInfo = openHomeWorkInfo
} }
} }
@ -56,6 +62,10 @@ public final class LocationPickerController: ViewController {
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
private var searchNavigationContentNode: LocationSearchNavigationContentNode? private var searchNavigationContentNode: LocationSearchNavigationContentNode?
private var isSearchingDisposable = MetaDisposable()
private let locationManager = CLLocationManager()
private var permissionDisposable: Disposable?
private var interaction: LocationPickerInteraction? private var interaction: LocationPickerInteraction?
@ -88,6 +98,29 @@ public final class LocationPickerController: ViewController {
strongSelf.controllerNode.updatePresentationData(presentationData) 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 let locationWithTimeout: (CLLocationCoordinate2D, Int32?) -> TelegramMediaMap = { coordinate, timeout in
return TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, geoPlace: nil, venue: nil, liveBroadcastingTimeout: timeout) 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 { guard let strongSelf = self else {
return return
} }
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let controller = ActionSheetController(presentationData: strongSelf.presentationData)
var title = strongSelf.presentationData.strings.Map_LiveLocationGroupDescription var title = strongSelf.presentationData.strings.Map_LiveLocationGroupDescription
if case let .share(peer, _, _) = strongSelf.mode, let receiver = peer { if case let .share(peer, _, _) = strongSelf.mode, let receiver = peer {
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(receiver.compactDisplayTitle).0 title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(receiver.compactDisplayTitle).0
@ -143,7 +176,12 @@ public final class LocationPickerController: ViewController {
guard let strongSelf = self else { guard let strongSelf = self else {
return 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() strongSelf.dismiss()
}, toggleMapModeSelection: { [weak self] in }, toggleMapModeSelection: { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -174,6 +212,16 @@ public final class LocationPickerController: ViewController {
state.selectedLocation = .none state.selectedLocation = .none
return state 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 }, openSearch: { [weak self] in
guard let strongSelf = self, let interaction = strongSelf.interaction, let navigationBar = strongSelf.navigationBar else { guard let strongSelf = self, let interaction = strongSelf.interaction, let navigationBar = strongSelf.navigationBar else {
return return
@ -186,8 +234,15 @@ public final class LocationPickerController: ViewController {
let contentNode = LocationSearchNavigationContentNode(presentationData: strongSelf.presentationData, interaction: interaction) let contentNode = LocationSearchNavigationContentNode(presentationData: strongSelf.presentationData, interaction: interaction)
strongSelf.searchNavigationContentNode = contentNode strongSelf.searchNavigationContentNode = contentNode
navigationBar.setContentNode(contentNode, animated: true) navigationBar.setContentNode(contentNode, animated: true)
strongSelf.controllerNode.activateSearch(navigationBar: navigationBar) let isSearching = strongSelf.controllerNode.activateSearch(navigationBar: navigationBar)
contentNode.activate() 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 }, updateSearchQuery: { [weak self] query in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@ -197,6 +252,7 @@ public final class LocationPickerController: ViewController {
guard let strongSelf = self, let navigationBar = strongSelf.navigationBar else { guard let strongSelf = self, let navigationBar = strongSelf.navigationBar else {
return return
} }
strongSelf.isSearchingDisposable.set(nil)
strongSelf.searchNavigationContentNode?.deactivate() strongSelf.searchNavigationContentNode?.deactivate()
strongSelf.searchNavigationContentNode = nil strongSelf.searchNavigationContentNode = nil
navigationBar.setContentNode(nil, animated: true) navigationBar.setContentNode(nil, animated: true)
@ -211,6 +267,13 @@ public final class LocationPickerController: ViewController {
return return
} }
strongSelf.controllerNode.updateSendActionHighlight(highlighted) 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 self.scrollToTop = { [weak self] in
@ -218,8 +281,6 @@ public final class LocationPickerController: ViewController {
strongSelf.controllerNode.scrollToTop() strongSelf.controllerNode.scrollToTop()
} }
} }
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
} }
required public init(coder aDecoder: NSCoder) { required public init(coder aDecoder: NSCoder) {
@ -228,6 +289,8 @@ public final class LocationPickerController: ViewController {
deinit { deinit {
self.presentationDataDisposable?.dispose() self.presentationDataDisposable?.dispose()
self.permissionDisposable?.dispose()
self.isSearchingDisposable.dispose()
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {

View File

@ -151,9 +151,12 @@ private enum LocationPickerEntry: Comparable, Identifiable {
case let .header(theme, title): case let .header(theme, title):
return LocationSectionHeaderItem(presentationData: ItemListPresentationData(presentationData), title: title) return LocationSectionHeaderItem(presentationData: ItemListPresentationData(presentationData), title: title)
case let .venue(theme, venue, _): 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) interaction?.sendVenue(venue)
}) }, infoAction: ["home", "work"].contains(venueType) ? {
interaction?.openHomeWorkInfo()
} : nil)
case let .attribution(theme): case let .attribution(theme):
return LocationAttributionItem(presentationData: ItemListPresentationData(presentationData)) return LocationAttributionItem(presentationData: ItemListPresentationData(presentationData))
} }
@ -220,11 +223,13 @@ struct LocationPickerState {
var mapMode: LocationMapMode var mapMode: LocationMapMode
var displayingMapModeOptions: Bool var displayingMapModeOptions: Bool
var selectedLocation: LocationPickerLocation var selectedLocation: LocationPickerLocation
var forceSelection: Bool
init() { init() {
self.mapMode = .map self.mapMode = .map
self.displayingMapModeOptions = false self.displayingMapModeOptions = false
self.selectedLocation = .none self.selectedLocation = .none
self.forceSelection = false
} }
} }
@ -415,10 +420,23 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
strongSelf.headerNode.mapNode.resetAnnotationSelection() strongSelf.headerNode.mapNode.resetAnnotationSelection()
case .selecting: case .selecting:
strongSelf.headerNode.mapNode.resetAnnotationSelection() 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): case let .venue(venue):
strongSelf.headerNode.mapNode.setMapCenter(coordinate: venue.coordinate, animated: true) strongSelf.headerNode.mapNode.setMapCenter(coordinate: venue.coordinate, animated: true)
default:
break
} }
let annotations: [LocationPinAnnotation] let annotations: [LocationPinAnnotation]
@ -482,7 +500,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
strongSelf.listOffset = max(0.0, offset) strongSelf.listOffset = max(0.0, offset)
let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(0.0, offset + overlap))) let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(0.0, offset + overlap)))
listTransition.updateFrame(node: strongSelf.headerNode, frame: headerFrame) 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) 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 { 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) 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) searchContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.containerLayoutUpdated(layout, navigationHeight: navigationBarHeight, transition: .immediate) self.containerLayoutUpdated(layout, navigationHeight: navigationBarHeight, transition: .immediate)
return searchContainerNode.isSearching
} }
func deactivateSearch() { func deactivateSearch() {
@ -643,10 +663,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode {
let isFirstLayout = self.validLayout == nil let isFirstLayout = self.validLayout == nil
self.validLayout = (layout, navigationHeight) self.validLayout = (layout, navigationHeight)
let isPickingLocation = self.state.selectedLocation.isCustom || self.state.forceSelection
let optionsHeight: CGFloat = 38.0 let optionsHeight: CGFloat = 38.0
let pickingCustomLocation = self.state.selectedLocation.isCustom
var actionHeight: CGFloat? var actionHeight: CGFloat?
self.listNode.forEachItemNode { itemNode in self.listNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? LocationActionListItemNode { 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 topInset: CGFloat = floor((layout.size.height - navigationHeight) / 2.0 + navigationHeight)
let overlap: CGFloat = 6.0 let overlap: CGFloat = 6.0
let headerHeight: CGFloat let headerHeight: CGFloat
if pickingCustomLocation, let actionHeight = actionHeight { if isPickingLocation, let actionHeight = actionHeight {
self.listOffset = topInset self.listOffset = topInset
headerHeight = layout.size.height - actionHeight - layout.intrinsicInsets.bottom + overlap - 2.0 headerHeight = layout.size.height - actionHeight - layout.intrinsicInsets.bottom + overlap - 2.0
} else if let listOffset = self.listOffset { } 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)) let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: headerHeight))
transition.updateFrame(node: self.headerNode, frame: headerFrame) 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 (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
let scrollToItem: ListViewScrollToItem? let scrollToItem: ListViewScrollToItem?
if pickingCustomLocation { if isPickingLocation {
scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: curve, directionHint: .Up) scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: curve, directionHint: .Up)
} else { } else {
scrollToItem = nil 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) var listFrame: CGRect = CGRect(origin: CGPoint(), size: layout.size)
if pickingCustomLocation { if isPickingLocation {
listFrame.origin.y = headerHeight - topInset - overlap listFrame.origin.y = headerHeight - topInset - overlap
} }
transition.updateFrame(node: self.listNode, frame: listFrame) 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)) 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.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 self.innerShadeNode.alpha = layout.intrinsicInsets.bottom > 0.0 ? 1.0 : 0.0

View File

@ -13,14 +13,18 @@ import AccountContext
import ItemListVenueItem import ItemListVenueItem
import ItemListUI import ItemListUI
import MapKit import MapKit
import Geocoding
import ChatListSearchItemHeader
private struct LocationSearchEntry: Identifiable, Comparable { private struct LocationSearchEntry: Identifiable, Comparable {
let index: Int let index: Int
let theme: PresentationTheme let theme: PresentationTheme
let venue: TelegramMediaMap let location: TelegramMediaMap
let title: String?
let distance: Double
var stableId: String { var stableId: String {
return self.venue.venue?.id ?? "" return self.location.venue?.id ?? ""
} }
static func ==(lhs: LocationSearchEntry, rhs: LocationSearchEntry) -> Bool { static func ==(lhs: LocationSearchEntry, rhs: LocationSearchEntry) -> Bool {
@ -30,7 +34,13 @@ private struct LocationSearchEntry: Identifiable, Comparable {
if lhs.theme !== rhs.theme { if lhs.theme !== rhs.theme {
return false 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 false
} }
return true return true
@ -41,10 +51,19 @@ private struct LocationSearchEntry: Identifiable, Comparable {
} }
func item(account: Account, presentationData: PresentationData, sendVenue: @escaping (TelegramMediaMap) -> Void) -> ListViewItem { func item(account: Account, presentationData: PresentationData, sendVenue: @escaping (TelegramMediaMap) -> Void) -> ListViewItem {
let venue = self.venue let venue = self.location
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: self.venue, sectionId: 0, style: .plain, action: { 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) sendVenue(venue)
}) }, header: header)
} }
} }
@ -81,10 +100,17 @@ final class LocationSearchContainerNode: ASDisplayNode {
private var containerViewLayout: (ContainerViewLayout, CGFloat)? private var containerViewLayout: (ContainerViewLayout, CGFloat)?
private var enqueuedTransitions: [LocationSearchContainerTransition] = [] 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) { public init(context: AccountContext, coordinate: CLLocationCoordinate2D, interaction: LocationPickerInteraction) {
self.context = context self.context = context
self.interaction = interaction self.interaction = interaction
let currentLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings)) self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
@ -107,6 +133,7 @@ final class LocationSearchContainerNode: ASDisplayNode {
let themeAndStringsPromise = self.themeAndStringsPromise let themeAndStringsPromise = self.themeAndStringsPromise
let isSearching = self._isSearching
let searchItems = self.searchQuery.get() let searchItems = self.searchQuery.get()
|> mapToSignal { query -> Signal<String?, NoError> in |> mapToSignal { query -> Signal<String?, NoError> in
if let query = query, !query.isEmpty { if let query = query, !query.isEmpty {
@ -119,19 +146,43 @@ final class LocationSearchContainerNode: ASDisplayNode {
|> mapToSignal { query -> Signal<[LocationSearchEntry]?, NoError> in |> mapToSignal { query -> Signal<[LocationSearchEntry]?, NoError> in
if let query = query, !query.isEmpty { if let query = query, !query.isEmpty {
let foundVenues = nearbyVenues(account: context.account, latitude: coordinate.latitude, longitude: coordinate.longitude, query: query) 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()) |> 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 entries: [LocationSearchEntry] = []
var index: Int = 0 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 { 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 index += 1
} }
return entries return entries
} }
} else { } else {
return .single(nil) return .single(nil)
|> afterCompleted {
isSearching.set(true)
}
} }
} }
@ -141,7 +192,12 @@ final class LocationSearchContainerNode: ASDisplayNode {
if let strongSelf = self { if let strongSelf = self {
let previousItems = previousSearchItems.swap(items ?? []) 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) 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) strongSelf.enqueueTransition(transition)
} }

View File

@ -54,6 +54,10 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
self.searchBar.deactivate(clear: false) self.searchBar.deactivate(clear: false)
} }
func updateActivity(_ activity: Bool) {
self.searchBar.activity = activity
}
func updatePresentationData(_ presentationData: PresentationData) { func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData self.presentationData = presentationData
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings)

View File

@ -22,7 +22,7 @@
- (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet; - (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet;
- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo; - (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo;
- (void)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken; - (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)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId;
- (void)contextDatacenterPublicKeysUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys; - (void)contextDatacenterPublicKeysUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
- (MTSignal *)fetchContextDatacenterPublicKeys:(MTContext *)context datacenterId:(NSInteger)datacenterId; - (MTSignal *)fetchContextDatacenterPublicKeys:(MTContext *)context datacenterId:(NSInteger)datacenterId;

View File

@ -491,10 +491,11 @@ static int32_t fixedTimeDifferenceValue = 0;
[listener contextDatacenterAddressSetUpdated:self datacenterId:datacenterId addressSet:addressSet]; [listener contextDatacenterAddressSetUpdated:self datacenterId:datacenterId addressSet:addressSet];
} }
if (previousAddressSetWasEmpty || updateSchemes || true) { if (true) {
bool shouldReset = previousAddressSetWasEmpty || updateSchemes;
for (id<MTContextChangeListener> listener in currentListeners) { for (id<MTContextChangeListener> listener in currentListeners) {
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:)]) { if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:shouldReset:)]) {
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId]; [listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId shouldReset:shouldReset];
} }
} }
} else { } else {
@ -664,8 +665,8 @@ static int32_t fixedTimeDifferenceValue = 0;
} }
for (id<MTContextChangeListener> listener in currentListeners) { for (id<MTContextChangeListener> listener in currentListeners) {
if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:)]) if ([listener respondsToSelector:@selector(contextDatacenterTransportSchemesUpdated:datacenterId:shouldReset:)])
[listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId]; [listener contextDatacenterTransportSchemesUpdated:self datacenterId:datacenterId shouldReset:true];
} }
} }
}]; }];

View File

@ -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:^ { [[MTProto managerQueue] dispatchOnQueue:^ {
if (context == _context && datacenterId == _datacenterId && ![self isStopped]) { if (context == _context && datacenterId == _datacenterId && ![self isStopped]) {
bool resolvedShouldReset = shouldReset;
if (_mtState & MTProtoStateAwaitingDatacenterScheme) { if (_mtState & MTProtoStateAwaitingDatacenterScheme) {
[self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterScheme)]; [self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterScheme)];
resolvedShouldReset = true;
} }
[self resetTransport]; if (resolvedShouldReset) {
[self requestTransportTransaction]; [self resetTransport];
[self requestTransportTransaction];
}
} }
}]; }];
} }

View File

@ -23,7 +23,7 @@ public struct NotificationSoundSettings {
} }
public func notificationMuteSettingsController(presentationData: PresentationData, notificationSettings: MessageNotificationSettings, soundSettings: NotificationSoundSettings?, openSoundSettings: @escaping () -> Void, updateSettings: @escaping (Int32?) -> Void) -> ViewController { 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 let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -35,11 +35,11 @@ public final class OpenInActionSheetController: ActionSheetController {
let theme = presentationData.theme let theme = presentationData.theme
let strings = presentationData.strings 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 self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { 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 { private final class OpenInActionSheetItemNode: ActionSheetItemNode {
let theme: ActionSheetControllerTheme let theme: ActionSheetControllerTheme
let strings: PresentationStrings let strings: PresentationStrings
@ -132,6 +129,9 @@ private final class OpenInActionSheetItemNode: ActionSheetItemNode {
self.theme = theme self.theme = theme
self.strings = strings 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 = ASTextNode()
self.titleNode.isUserInteractionEnabled = false self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = true 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) { 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) self.textNode.attributedText = NSAttributedString(string: option.title, font: textFont, textColor: theme.primaryTextColor, paragraphAlignment: .center)
let iconSize = CGSize(width: 60.0, height: 60.0) let iconSize = CGSize(width: 60.0, height: 60.0)

View File

@ -59,7 +59,7 @@ public final class PasscodeSetupController: ViewController {
return return
} }
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let controller = ActionSheetController(presentationData: strongSelf.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
self?.controllerNode.activateInput() self?.controllerNode.activateInput()
controller?.dismissAnimated() controller?.dismissAnimated()

View File

@ -727,7 +727,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
} }
if let currentValue = currentValue { if let currentValue = currentValue {
let controller = ActionSheetController(presentationTheme: self.presentationData.theme) let controller = ActionSheetController(presentationData: self.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -847,7 +847,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
return return
} }
let controller = ActionSheetController(presentationTheme: strongSelf.presentationData.theme) let controller = ActionSheetController(presentationData: strongSelf.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() 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 let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -961,7 +961,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
} }
private func deleteAllValues() { private func deleteAllValues() {
let controller = ActionSheetController(presentationTheme: self.presentationData.theme) let controller = ActionSheetController(presentationData: self.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -2143,6 +2143,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
return self._itemParams! return self._itemParams!
} }
private var presentationData: PresentationData
private var theme: PresentationTheme private var theme: PresentationTheme
private var strings: PresentationStrings private var strings: PresentationStrings
@ -2161,6 +2162,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
private let hiddenItemDisposable = MetaDisposable() private let hiddenItemDisposable = MetaDisposable()
required init(initParams: SecureIdDocumentFormControllerNodeInitParams, presentationData: PresentationData) { required init(initParams: SecureIdDocumentFormControllerNodeInitParams, presentationData: PresentationData) {
self.presentationData = presentationData
self.theme = presentationData.theme self.theme = presentationData.theme
self.strings = presentationData.strings self.strings = presentationData.strings
self.context = initParams.context self.context = initParams.context
@ -2414,7 +2416,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
strongSelf.view.endEditing(true) strongSelf.view.endEditing(true)
strongSelf.present(controller, nil) strongSelf.present(controller, nil)
case .gender: case .gender:
let controller = ActionSheetController(presentationTheme: strongSelf.theme) let controller = ActionSheetController(presentationData: strongSelf.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -2756,7 +2758,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
return return
} }
let controller = ActionSheetController(presentationTheme: theme) let controller = ActionSheetController(presentationData: self.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -2816,7 +2818,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
} }
private func openDocument(document: SecureIdVerificationDocument) { private func openDocument(document: SecureIdVerificationDocument) {
let controller = ActionSheetController(presentationTheme: theme) let controller = ActionSheetController(presentationData: self.presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -143,7 +143,7 @@ final class SecureIdDocumentGalleryFooterContentNode: GalleryFooterContentNode {
@objc func deleteButtonPressed() { @objc func deleteButtonPressed() {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
let items: [ActionSheetItem] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()

View File

@ -89,11 +89,11 @@ final class SecureIdDocumentTypeSelectionController: ActionSheetController {
self.completion = completion 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 self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { if let strongSelf = self {
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme) strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
} }
}) })

View File

@ -505,12 +505,12 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
self.backgroundNode = ASImageNode() self.backgroundNode = ASImageNode()
self.backgroundNode.displaysAsynchronously = false self.backgroundNode.displaysAsynchronously = false
self.backgroundNode.displayWithoutProcessing = true 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 = TextFieldNode()
self.inputNode.textField.font = Font.regular(17.0) self.inputNode.textField.font = Font.regular(17.0)
self.inputNode.textField.textColor = theme.actionSheet.inputTextColor self.inputNode.textField.textColor = theme.list.freePlainInputField.primaryColor
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.actionSheet.inputPlaceholderColor) self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.list.freePlainInputField.placeholderColor)
self.hideButtonNode = HighlightableButtonNode() self.hideButtonNode = HighlightableButtonNode()
@ -548,10 +548,10 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega
} }
self.inputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance 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 = HighlightableButtonNode()
self.clearButtonNode.setImage(generateClearImage(color: theme.actionSheet.inputClearButtonColor), for: []) self.clearButtonNode.setImage(generateClearImage(color: theme.list.freePlainInputField.controlColor), for: [])
self.clearButtonNode.isHidden = true self.clearButtonNode.isHidden = true
super.init() super.init()
@ -1198,11 +1198,27 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
transition.updateFrame(node: self.skipActionButtonNode, frame: buttonFrame) 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.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))) let changeEmailActionFrame: CGRect
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 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.changeEmailActionButtonNode, frame: changeEmailActionButtonFrame)
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.resendCodeActionButtonNode, frame: resendCodeActionButtonFrame)
transition.updateFrame(node: self.changeEmailActionTitleNode, frame: changeEmailActionFrame)
transition.updateFrame(node: self.resendCodeActionTitleNode, frame: resendCodeActionFrame)
transition.animateView { transition.animateView {
self.scrollNode.view.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.insets(options: [.input]).bottom, right: 0.0) self.scrollNode.view.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.insets(options: [.input]).bottom, right: 0.0)

View File

@ -148,7 +148,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode {
@objc private func deleteButtonPressed() { @objc private func deleteButtonPressed() {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
let items: [ActionSheetItem] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()

View File

@ -868,7 +868,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
} }
}, dismissAdmin: { }, dismissAdmin: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_Moderator_AccessLevelRevoke, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_Moderator_AccessLevelRevoke, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()

View File

@ -461,7 +461,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
}) })
}, openTimeout: { }, openTimeout: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
let intervals: [Int32] = [ let intervals: [Int32] = [
1 * 60 * 60 * 24, 1 * 60 * 60 * 24,
7 * 60 * 60 * 24, 7 * 60 * 60 * 24,
@ -499,7 +499,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
presentControllerImpl?(actionSheet, nil) presentControllerImpl?(actionSheet, nil)
}, delete: { }, delete: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_Delete, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_Delete, color: .destructive, font: .default, enabled: true, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -703,7 +703,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0)) 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 items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_ApplyAlertAction, color: .accent, font: .default, enabled: true, action: { [weak actionSheet] in

View File

@ -359,7 +359,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
return return
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
if !participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder).isEmpty { if !participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder).isEmpty {
items.append(ActionSheetTextItem(title: participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))) items.append(ActionSheetTextItem(title: participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)))

View File

@ -75,9 +75,13 @@ private final class ChannelDiscussionGroupActionSheetItemNode: ActionSheetItemNo
} else { } else {
text = strings.Channel_DiscussionGroup_PrivateChannelLink(groupPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), channelPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)) 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 { 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 self.textNode.attributedText = attributedText

View File

@ -305,7 +305,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ChannelDiscussionGroupActionSheetItem(context: context, channelPeer: channelPeer, groupPeer: groupPeer, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder), 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 ActionSheetButtonItem(title: presentationData.strings.Channel_DiscussionGroup_LinkGroup, color: .accent, action: { [weak actionSheet] in

View File

@ -905,7 +905,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
return return
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -929,7 +929,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
return return
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -922,7 +922,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
}) })
}, revokePrivateLink: { }, revokePrivateLink: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -869,7 +869,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|> deliverOnMainQueue).start(next: { user in |> deliverOnMainQueue).start(next: { user in
if let user = user, let phone = user.phone, formatPhoneNumber(phone) == formatPhoneNumber(number) { if let user = user, let phone = user.phone, formatPhoneNumber(phone) == formatPhoneNumber(number) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -992,7 +992,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
inviteAction(subject.contactData.basicData.phoneNumbers[0].value) inviteAction(subject.contactData.basicData.phoneNumbers[0].value)
} else { } else {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -1402,7 +1402,7 @@ private func addContactToExisting(context: AccountContext, parentController: Vie
func addContactOptionsController(context: AccountContext, peer: Peer?, contactData: DeviceContactExtendedData) -> ActionSheetController { func addContactOptionsController(context: AccountContext, peer: Peer?, contactData: DeviceContactExtendedData) -> ActionSheetController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -1998,7 +1998,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
let presentationData = context.sharedContext.currentPresentationData.with { $0 } 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 { 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 let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -2015,7 +2015,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
]) ])
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} else if let peer = peerView.peers[peerView.peerId] { } 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 let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -208,7 +208,7 @@ public func groupsInCommonController(context: AccountContext, peerId: PeerId) ->
arguments.openPeer(peer.id) 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) controller.presentInGlobalOverlay(contextController)
} }
return controller return controller

View File

@ -23,13 +23,13 @@ final class PeerBanTimeoutController: ActionSheetController {
let theme = presentationData.theme let theme = presentationData.theme
let strings = presentationData.strings let strings = presentationData.strings
super.init(theme: ActionSheetControllerTheme(presentationTheme: theme)) super.init(theme: ActionSheetControllerTheme(presentationData: presentationData))
self._ready.set(.single(true)) self._ready.set(.single(true))
self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in self.presentationDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { if let strongSelf = self {
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme) strongSelf.theme = ActionSheetControllerTheme(presentationData: presentationData)
} }
}) })

View File

@ -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 { 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 presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme)) let controller = ActionSheetController(theme: ActionSheetControllerTheme(presentationData: presentationData))
let options: [PeerReportOption] = [ let options: [PeerReportOption] = [
.spam, .spam,

View File

@ -990,7 +990,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
} else { } else {
if value { if value {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -1046,7 +1046,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
}) })
}, deleteContact: { }, deleteContact: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -1112,7 +1112,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|> deliverOnMainQueue).start(next: { peer, _ in |> deliverOnMainQueue).start(next: { peer, _ in
if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(number) == formatPhoneNumber(peerPhoneNumber) { if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(number) == formatPhoneNumber(peerPhoneNumber) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -1584,7 +1584,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let text: String = presentationData.strings.UserInfo_TapToCall 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 controller.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak resultItemNode] in
if let resultItemNode = resultItemNode { if let resultItemNode = resultItemNode {
return (resultItemNode, callButtonFrame) return (resultItemNode, callButtonFrame)

View File

@ -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(.useLessVoiceData(presentationData.theme, presentationData.strings.CallSettings_UseLessData, stringForUseLessDataSetting(dataSaving, strings: presentationData.strings)))
entries.append(.otherHeader(presentationData.theme, presentationData.strings.ChatSettings_Other)) 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(.saveIncomingPhotos(presentationData.theme, presentationData.strings.Settings_SaveIncomingPhotos))
entries.append(.saveEditedPhotos(presentationData.theme, presentationData.strings.Settings_SaveEditedPhotos, data.generatedMediaStoreSettings.storeEditedPhotos)) entries.append(.saveEditedPhotos(presentationData.theme, presentationData.strings.Settings_SaveEditedPhotos, data.generatedMediaStoreSettings.storeEditedPhotos))
entries.append(.openLinksIn(presentationData.theme, presentationData.strings.ChatSettings_OpenLinksIn, defaultWebBrowser)) 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)) pushControllerImpl?(autodownloadMediaConnectionTypeController(context: context, connectionType: connectionType))
}, resetAutomaticDownload: { }, resetAutomaticDownload: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.AutoDownloadSettings_ResetHelp), ActionSheetTextItem(title: presentationData.strings.AutoDownloadSettings_ResetHelp),
ActionSheetButtonItem(title: presentationData.strings.AutoDownloadSettings_Reset, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.AutoDownloadSettings_Reset, color: .destructive, action: { [weak actionSheet] in

View File

@ -150,7 +150,6 @@ private enum IntentsSettingsControllerEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .suggestHeader(lhsTheme, lhsText): case let .suggestHeader(lhsTheme, lhsText):
if case let .suggestHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { if case let .suggestHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true return true
@ -272,7 +271,7 @@ public func intentsSettingsController(context: AccountContext) -> ViewController
let _ = updateIntentsSettingsInteractively(accountManager: context.sharedContext.accountManager, f).start() let _ = updateIntentsSettingsInteractively(accountManager: context.sharedContext.accountManager, f).start()
}, resetAll: { }, resetAll: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.IntentsSettings_Reset, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: presentationData.strings.IntentsSettings_Reset, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()

View File

@ -389,7 +389,7 @@ func networkUsageStatsController(context: AccountContext) -> ViewController {
let arguments = NetworkUsageStatsControllerArguments(resetStatistics: { [weak stats] section in let arguments = NetworkUsageStatsControllerArguments(resetStatistics: { [weak stats] section in
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -216,7 +216,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
case let .serversHeader(theme, text): case let .serversHeader(theme, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .addServer(theme, text, _): 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() arguments.addNewServer()
}) })
case let .server(_, theme, strings, settings, active, status, editing, enabled): case let .server(_, theme, strings, settings, active, status, editing, enabled):
@ -230,7 +230,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
arguments.removeServer(settings) arguments.removeServer(settings)
}) })
case let .shareProxyList(theme, text): 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() arguments.shareProxyList()
}) })
case let .useForCalls(theme, text, value): case let .useForCalls(theme, text, value):

View File

@ -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>?) { 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) super.init(theme: sheetTheme)
self._ready.set(.single(true)) self._ready.set(.single(true))
@ -63,7 +63,7 @@ public final class ProxyServerActionSheetController: ActionSheetController {
if let updatedPresentationData = updatedPresentationData { if let updatedPresentationData = updatedPresentationData {
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { 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 { private enum ProxyServerInfoStatusType {
case generic(String) case generic(String)
case failed(String) case failed(String)
@ -107,6 +105,7 @@ private enum ProxyServerInfoStatusType {
private final class ProxyServerInfoItemNode: ActionSheetItemNode { private final class ProxyServerInfoItemNode: ActionSheetItemNode {
private let theme: ActionSheetControllerTheme private let theme: ActionSheetControllerTheme
private let strings: PresentationStrings private let strings: PresentationStrings
private let textFont: UIFont
private let network: Network private let network: Network
private let server: ProxyServerSettings private let server: ProxyServerSettings
@ -122,6 +121,8 @@ private final class ProxyServerInfoItemNode: ActionSheetItemNode {
self.network = network self.network = network
self.server = server self.server = server
self.textFont = Font.regular(floor(theme.baseFontSize * 16.0 / 17.0))
var fieldNodes: [(ImmediateTextNode, ImmediateTextNode)] = [] var fieldNodes: [(ImmediateTextNode, ImmediateTextNode)] = []
let serverTitleNode = ImmediateTextNode() let serverTitleNode = ImmediateTextNode()
serverTitleNode.isUserInteractionEnabled = false serverTitleNode.isUserInteractionEnabled = false
@ -317,10 +318,12 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
self.dismiss = dismiss self.dismiss = dismiss
self.present = present self.present = present
let titleFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.titleNode = ImmediateTextNode() self.titleNode = ImmediateTextNode()
self.titleNode.isUserInteractionEnabled = false self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = 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 = ActivityIndicator(type: .custom(theme.controlAccentColor, 22.0, 1.5, false))
self.activityIndicator.isHidden = true self.activityIndicator.isHidden = true

View File

@ -13,15 +13,15 @@ enum ProxySettingsActionIcon {
} }
final class ProxySettingsActionItem: ListViewItem, ItemListItem { final class ProxySettingsActionItem: ListViewItem, ItemListItem {
let theme: PresentationTheme let presentationData: ItemListPresentationData
let title: String let title: String
let icon: ProxySettingsActionIcon let icon: ProxySettingsActionIcon
let editing: Bool let editing: Bool
let sectionId: ItemListSectionId let sectionId: ItemListSectionId
let action: () -> Void let action: () -> Void
init(theme: PresentationTheme, title: String, icon: ProxySettingsActionIcon = .none, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) { init(presentationData: ItemListPresentationData, title: String, icon: ProxySettingsActionIcon = .none, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) {
self.theme = theme self.presentationData = presentationData
self.title = title self.title = title
self.icon = icon self.icon = icon
self.editing = editing 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 final class ProxySettingsActionItemNode: ListViewItemNode {
private let backgroundNode: ASDisplayNode private let backgroundNode: ASDisplayNode
private let topStripeNode: ASDisplayNode private let topStripeNode: ASDisplayNode
@ -130,24 +128,26 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
return { item, params, neighbors in return { item, params, neighbors in
var updatedTheme: PresentationTheme? var updatedTheme: PresentationTheme?
if currentItem?.theme !== item.theme { let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
updatedTheme = item.theme
if currentItem?.presentationData.theme !== item.presentationData.theme {
updatedTheme = item.presentationData.theme
} }
let leftInset: CGFloat = (item.icon != .none ? 50.0 : 16.0) + params.leftInset let leftInset: CGFloat = (item.icon != .none ? 50.0 : 16.0) + params.leftInset
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0) 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 separatorHeight = UIScreenPixel
let insets = itemListNeighborsGroupedInsets(neighbors) 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 layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
let layoutSize = layout.size 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 return (layout, { [weak self] animated in
if let strongSelf = self { if let strongSelf = self {
@ -156,10 +156,10 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
strongSelf.accessibilityLabel = item.title strongSelf.accessibilityLabel = item.title
if let _ = updatedTheme { if let _ = updatedTheme {
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
} }
let _ = titleApply() let _ = titleApply()
@ -213,7 +213,7 @@ private final class ProxySettingsActionItemNode: ListViewItemNode {
strongSelf.bottomStripeNode.isHidden = hasCorners 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.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) strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)

View File

@ -22,7 +22,7 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
private var isDismissed: Bool = false private var isDismissed: Bool = false
public init(presentationData: PresentationData, updatedPresentationData: Signal<PresentationData, NoError>, link: String) { 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) super.init(theme: sheetTheme)
let presentActivityController: (Any) -> Void = { [weak self] item in 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 self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
if let strongSelf = self { 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.link = link
self.ready = ready self.ready = ready
let textFont = Font.regular(floor(theme.baseFontSize * 13.0 / 17.0))
self.label = ASTextNode() self.label = ASTextNode()
self.label.isUserInteractionEnabled = false self.label.isUserInteractionEnabled = false
self.label.maximumNumberOfLines = 0 self.label.maximumNumberOfLines = 0
self.label.displaysAsynchronously = false self.label.displaysAsynchronously = false
self.label.truncationMode = .byTruncatingTail self.label.truncationMode = .byTruncatingTail
self.label.isUserInteractionEnabled = false 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 = TransformImageNode()
self.imageNode.clipsToBounds = true self.imageNode.clipsToBounds = true

View File

@ -402,7 +402,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|> deliverOnMainQueue).start(next: { [weak statsPromise] result in |> deliverOnMainQueue).start(next: { [weak statsPromise] result in
if let result = result, case let .result(stats) = result { if let result = result, case let .result(stats) = result {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }
@ -624,7 +624,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -113,7 +113,7 @@ public func debugAccountsController(context: AccountContext, accountManager: Acc
}).start() }).start()
}, loginNewAccount: { }, loginNewAccount: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme) let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated() controller?.dismissAnimated()
} }

View File

@ -155,7 +155,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
let _ = (Logger.shared.collectLogs() let _ = (Logger.shared.collectLogs()
|> deliverOnMainQueue).start(next: { logs in |> deliverOnMainQueue).start(next: { logs in
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetButtonItem] = [] var items: [ActionSheetButtonItem] = []
@ -206,7 +206,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
let _ = (Logger.shared.collectLogs() let _ = (Logger.shared.collectLogs()
|> deliverOnMainQueue).start(next: { logs in |> deliverOnMainQueue).start(next: { logs in
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetButtonItem] = [] var items: [ActionSheetButtonItem] = []
@ -284,7 +284,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
let _ = (Logger.shared.collectShortLogFiles() let _ = (Logger.shared.collectShortLogFiles()
|> deliverOnMainQueue).start(next: { logs in |> deliverOnMainQueue).start(next: { logs in
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetButtonItem] = [] var items: [ActionSheetButtonItem] = []
@ -409,7 +409,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case let .resetData(theme): case let .resetData(theme):
return ItemListActionItem(presentationData: presentationData, title: "Reset Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: { 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 presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: "All data will be lost."), ActionSheetTextItem(title: "All data will be lost."),
ActionSheetButtonItem(title: "Reset Data", color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: "Reset Data", color: .destructive, action: { [weak actionSheet] in
@ -431,7 +431,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return return
} }
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: "All secret chats will be lost."), ActionSheetTextItem(title: "All secret chats will be lost."),
ActionSheetButtonItem(title: "Clear Database", color: .destructive, action: { [weak actionSheet] in 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