mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
891dae914e
commit
7860375458
@ -6978,3 +6978,9 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Notifications.On" = "On";
|
||||
"Notifications.Off" = "Off";
|
||||
|
||||
"AuthSessions.View.Device" = "Device";
|
||||
"AuthSessions.View.Location" = "Location";
|
||||
"AuthSessions.View.IP" = "IP";
|
||||
"AuthSessions.View.TerminateSession" = "Terminate Session";
|
||||
"AuthSessions.View.Logout" = "Log Out";
|
||||
|
@ -208,6 +208,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.topStripeNode = ASDisplayNode()
|
||||
self.topStripeNode.isLayerBacked = true
|
||||
@ -513,64 +514,6 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode != nil {
|
||||
strongSelf.topStripeNode.removeFromSupernode()
|
||||
}
|
||||
if !last && strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 1)
|
||||
} else if last && strongSelf.bottomStripeNode.supernode != nil {
|
||||
strongSelf.bottomStripeNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
transition.updateFrameAdditive(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)))
|
||||
case .blocks:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
}
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: nodeLayout.size.width, height: separatorHeight))
|
||||
transition.updateFrameAdditive(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: nodeLayout.size.width - bottomStripeInset, height: separatorHeight)))
|
||||
}
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: nodeLayout.contentSize.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
@ -600,6 +543,65 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
})
|
||||
}
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode != nil {
|
||||
strongSelf.topStripeNode.removeFromSupernode()
|
||||
}
|
||||
if !last && strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 1)
|
||||
} else if last && strongSelf.bottomStripeNode.supernode != nil {
|
||||
strongSelf.bottomStripeNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
transition.updateFrameAdditive(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)))
|
||||
case .blocks:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: nodeLayout.size.width, height: separatorHeight))
|
||||
transition.updateFrameAdditive(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: nodeLayout.size.width - bottomStripeInset, height: separatorHeight)))
|
||||
}
|
||||
|
||||
|
||||
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)))
|
||||
|
||||
let _ = titleApply()
|
||||
|
@ -130,7 +130,9 @@ class ChatListFilterPresetCategoryItemNode: ItemListRevealOptionsItemNode, ItemL
|
||||
|
||||
self.bottomStripeNode = ASDisplayNode()
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.avatarNode = ASImageNode()
|
||||
self.avatarNode.isUserInteractionEnabled = false
|
||||
@ -311,7 +313,7 @@ class ChatListFilterPresetCategoryItemNode: ItemListRevealOptionsItemNode, ItemL
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
|
@ -139,6 +139,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.titleNode = TextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
@ -315,7 +316,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
|
@ -220,7 +220,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
||||
let arguments = arguments as! InviteLinkEditControllerArguments
|
||||
switch self {
|
||||
case let .title(_, placeholder, value):
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: value, placeholder: placeholder, sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: value, placeholder: placeholder, maxLength: 32, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.title = value
|
||||
|
@ -98,6 +98,7 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
||||
private let topStripeNode: ASDisplayNode
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
private let maskNode: ASImageNode
|
||||
private let imageNode: TransformImageNode
|
||||
private let iconNode: ASImageNode
|
||||
private var selectionNode: ItemListSelectableControlNode?
|
||||
@ -118,6 +119,9 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
||||
self.bottomStripeNode = ASDisplayNode()
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
@ -286,7 +290,10 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0)
|
||||
}
|
||||
|
||||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
||||
case .blocks:
|
||||
leftInset = 16.0 + params.leftInset
|
||||
@ -300,11 +307,19 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
strongSelf.topStripeNode.isHidden = !item.displayDecorations
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners || !item.displayDecorations
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
let bottomStripeOffset: CGFloat
|
||||
@ -315,8 +330,14 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
bottomStripeOffset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public enum ItemListPeerActionItemHeight {
|
||||
public enum ItemListPeerActionItemColor {
|
||||
case accent
|
||||
case destructive
|
||||
case disabled
|
||||
}
|
||||
|
||||
public class ItemListPeerActionItem: ListViewItem, ItemListItem {
|
||||
@ -29,7 +30,7 @@ public class ItemListPeerActionItem: ListViewItem, ItemListItem {
|
||||
public let sectionId: ItemListSectionId
|
||||
let action: (() -> Void)?
|
||||
|
||||
public init(presentationData: ItemListPresentationData, icon: UIImage?, title: String, alwaysPlain: Bool = false, hasSeparator: Bool = true, sectionId: ItemListSectionId, height: ItemListPeerActionItemHeight = .peerList, color: ItemListPeerActionItemColor = .accent, editing: Bool, action: (() -> Void)?) {
|
||||
public init(presentationData: ItemListPresentationData, icon: UIImage?, title: String, alwaysPlain: Bool = false, hasSeparator: Bool = true, sectionId: ItemListSectionId, height: ItemListPeerActionItemHeight = .peerList, color: ItemListPeerActionItemColor = .accent, editing: Bool = false, action: (() -> Void)?) {
|
||||
self.presentationData = presentationData
|
||||
self.icon = icon
|
||||
self.title = title
|
||||
@ -182,6 +183,8 @@ class ItemListPeerActionItemNode: ListViewItemNode {
|
||||
textColor = item.presentationData.theme.list.itemAccentColor
|
||||
case .destructive:
|
||||
textColor = item.presentationData.theme.list.itemDestructiveColor
|
||||
case .disabled:
|
||||
textColor = item.presentationData.theme.list.itemDisabledTextColor
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: textColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - editingOffset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
@ -492,7 +492,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
|
||||
self.bottomStripeNode = ASDisplayNode()
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.containerNode = ContextControllerSourceNode()
|
||||
|
||||
@ -991,7 +993,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params) && !item.noInsets
|
||||
|
@ -204,6 +204,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.imageNode = TransformImageNode()
|
||||
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
|
||||
@ -659,7 +660,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
|
@ -141,7 +141,9 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
self.bottomStripeNode = ASDisplayNode()
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.iconNode = TransformImageNode()
|
||||
|
||||
|
@ -254,6 +254,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
|
||||
if strongSelf.drivingButtonNode == nil {
|
||||
strongSelf.drivingButtonNode = SolidRoundedButtonNode(icon: generateTintedImage(image: UIImage(bundleImageName: "Location/DirectionsDriving"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor), theme: buttonTheme, fontSize: 15.0, height: 32.0, cornerRadius: 16.0)
|
||||
strongSelf.drivingButtonNode?.alpha = 0.0
|
||||
strongSelf.drivingButtonNode?.iconSpacing = 5.0
|
||||
strongSelf.drivingButtonNode?.allowsGroupOpacity = true
|
||||
strongSelf.drivingButtonNode?.pressed = { [weak self] in
|
||||
if let item = self?.item {
|
||||
@ -264,6 +265,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.transitButtonNode = SolidRoundedButtonNode(icon: generateTintedImage(image: UIImage(bundleImageName: "Location/DirectionsTransit"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor), theme: buttonTheme, fontSize: 15.0, height: 32.0, cornerRadius: 16.0)
|
||||
strongSelf.transitButtonNode?.alpha = 0.0
|
||||
strongSelf.transitButtonNode?.iconSpacing = 2.0
|
||||
strongSelf.transitButtonNode?.allowsGroupOpacity = true
|
||||
strongSelf.transitButtonNode?.pressed = { [weak self] in
|
||||
if let item = self?.item {
|
||||
@ -274,6 +276,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.walkingButtonNode = SolidRoundedButtonNode(icon: generateTintedImage(image: UIImage(bundleImageName: "Location/DirectionsWalking"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor), theme: buttonTheme, fontSize: 15.0, height: 32.0, cornerRadius: 16.0)
|
||||
strongSelf.walkingButtonNode?.alpha = 0.0
|
||||
strongSelf.walkingButtonNode?.iconSpacing = 2.0
|
||||
strongSelf.walkingButtonNode?.allowsGroupOpacity = true
|
||||
strongSelf.walkingButtonNode?.pressed = { [weak self] in
|
||||
if let item = self?.item {
|
||||
|
@ -11,6 +11,7 @@ import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import AccountContext
|
||||
import OpenInExternalAppUI
|
||||
import ItemListPeerActionItem
|
||||
|
||||
private final class DataAndStorageControllerArguments {
|
||||
let openStorageUsage: () -> Void
|
||||
@ -322,12 +323,16 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Settings/Menu/WiFi")?.precomposed(), title: text, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openAutomaticDownloadConnectionType(.wifi)
|
||||
})
|
||||
case let .automaticDownloadReset(_, text, enabled):
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
case let .automaticDownloadReset(theme, text, enabled):
|
||||
var icon = PresentationResourcesItemList.resetIcon(theme)
|
||||
if !enabled {
|
||||
icon = generateTintedImage(image: icon, color: theme.list.itemDisabledTextColor)
|
||||
}
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: icon, title: text, sectionId: self.section, height: .generic, color: enabled ? .accent : .disabled, editing: false, action: {
|
||||
if enabled {
|
||||
arguments.resetAutomaticDownload()
|
||||
}
|
||||
}, tag: DataAndStorageEntryTag.automaticDownloadReset)
|
||||
})
|
||||
case let .autoplayHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .autoplayGifs(_, text, value):
|
||||
|
@ -141,6 +141,7 @@ private final class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.infoIconNode = ASImageNode()
|
||||
self.infoIconNode.isLayerBacked = true
|
||||
@ -369,7 +370,7 @@ private final class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
|
@ -46,8 +46,9 @@ final class ItemListRecentSessionItem: ListViewItem, ItemListItem {
|
||||
let sectionId: ItemListSectionId
|
||||
let setSessionIdWithRevealedOptions: (Int64?, Int64?) -> Void
|
||||
let removeSession: (Int64) -> Void
|
||||
let action: (() -> Void)?
|
||||
|
||||
init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, session: RecentAccountSession, enabled: Bool, editable: Bool, editing: Bool, revealed: Bool, sectionId: ItemListSectionId, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void) {
|
||||
init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, session: RecentAccountSession, enabled: Bool, editable: Bool, editing: Bool, revealed: Bool, sectionId: ItemListSectionId, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, action: (() -> Void)?) {
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.session = session
|
||||
@ -58,6 +59,7 @@ final class ItemListRecentSessionItem: ListViewItem, ItemListItem {
|
||||
self.sectionId = sectionId
|
||||
self.setSessionIdWithRevealedOptions = setSessionIdWithRevealedOptions
|
||||
self.removeSession = removeSession
|
||||
self.action = action
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -97,12 +99,21 @@ final class ItemListRecentSessionItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var selectable: Bool = true
|
||||
public func selected(listView: ListView){
|
||||
listView.clearHighlightAnimated(true)
|
||||
|
||||
if self.enabled {
|
||||
self.action?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func iconForSession(_ session: RecentAccountSession) -> UIImage? {
|
||||
let platform = session.platform.lowercased()
|
||||
let device = session.deviceModel.lowercased()
|
||||
if device.contains("chrome") {
|
||||
if device.contains("chrome") && !device.contains("chromebook") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/Chrome")
|
||||
}
|
||||
if device.contains("brave") {
|
||||
@ -120,9 +131,18 @@ private func iconForSession(_ session: RecentAccountSession) -> UIImage? {
|
||||
if device.contains("opera") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/Opera")
|
||||
}
|
||||
if platform.contains("android") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/Android")
|
||||
}
|
||||
if platform.contains("ios") || platform.contains("macos") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/iOS")
|
||||
}
|
||||
if platform.contains("linux") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/Linux")
|
||||
}
|
||||
if platform.contains("windows") {
|
||||
return UIImage(bundleImageName: "Settings/Devices/Windows")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -145,12 +165,25 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
private let appNode: TextNode
|
||||
private let locationNode: TextNode
|
||||
|
||||
private let containerNode: ASDisplayNode
|
||||
override var controlsContainer: ASDisplayNode {
|
||||
return self.containerNode
|
||||
}
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
|
||||
private var layoutParams: (ItemListRecentSessionItem, ListViewItemLayoutParams, ItemListNeighbors)?
|
||||
|
||||
private var editableControlNode: ItemListEditableControlNode?
|
||||
|
||||
override public var canBeSelected: Bool {
|
||||
if let item = self.layoutParams?.0, let _ = item.action {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
@ -162,6 +195,9 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.containerNode = ASDisplayNode()
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.cornerRadius = 7.0
|
||||
@ -189,10 +225,11 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.appNode)
|
||||
self.addSubnode(self.locationNode)
|
||||
self.addSubnode(self.containerNode)
|
||||
self.containerNode.addSubnode(self.iconNode)
|
||||
self.containerNode.addSubnode(self.titleNode)
|
||||
self.containerNode.addSubnode(self.appNode)
|
||||
self.containerNode.addSubnode(self.locationNode)
|
||||
|
||||
self.addSubnode(self.activateArea)
|
||||
}
|
||||
@ -236,23 +273,23 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
titleAttributedString = NSAttributedString(string: "\(item.session.appName) \(item.session.appVersion)", font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
|
||||
var appString = ""
|
||||
var deviceString = ""
|
||||
if !item.session.deviceModel.isEmpty {
|
||||
appString = item.session.deviceModel
|
||||
deviceString = item.session.deviceModel
|
||||
}
|
||||
|
||||
if !item.session.platform.isEmpty {
|
||||
if !appString.isEmpty {
|
||||
appString += ", "
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
appString += item.session.platform
|
||||
deviceString += item.session.platform
|
||||
}
|
||||
|
||||
if !item.session.systemVersion.isEmpty {
|
||||
if !appString.isEmpty {
|
||||
appString += ", "
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
appString += item.session.systemVersion
|
||||
deviceString += item.session.systemVersion
|
||||
}
|
||||
|
||||
var updatedIcon: UIImage?
|
||||
@ -260,7 +297,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
updatedIcon = iconForSession(item.session)
|
||||
}
|
||||
|
||||
appAttributedString = NSAttributedString(string: appString, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
appAttributedString = NSAttributedString(string: deviceString, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
|
||||
let label: String
|
||||
if item.session.isCurrent {
|
||||
@ -418,7 +455,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
@ -447,6 +484,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
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.containerNode.frame = CGRect(origin: CGPoint(), size: strongSelf.backgroundNode.frame.size)
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)))
|
||||
transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)))
|
||||
@ -456,7 +494,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: strongSelf.appNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: appLayout.size))
|
||||
transition.updateFrame(node: strongSelf.locationNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: strongSelf.appNode.frame.maxY + textSpacing), size: locationLayout.size))
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: 75.0 + UIScreenPixel + UIScreenPixel))
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
|
||||
strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
||||
|
||||
@ -467,6 +505,44 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
||||
super.setHighlighted(highlighted, at: point, animated: animated)
|
||||
|
||||
if highlighted && (self.layoutParams?.0.enabled ?? false) {
|
||||
self.highlightedBackgroundNode.alpha = 1.0
|
||||
if self.highlightedBackgroundNode.supernode == nil {
|
||||
var anchorNode: ASDisplayNode?
|
||||
if self.bottomStripeNode.supernode != nil {
|
||||
anchorNode = self.bottomStripeNode
|
||||
} else if self.topStripeNode.supernode != nil {
|
||||
anchorNode = self.topStripeNode
|
||||
} else if self.backgroundNode.supernode != nil {
|
||||
anchorNode = self.backgroundNode
|
||||
}
|
||||
if let anchorNode = anchorNode {
|
||||
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode)
|
||||
} else {
|
||||
self.addSubnode(self.highlightedBackgroundNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.highlightedBackgroundNode.supernode != nil {
|
||||
if animated {
|
||||
self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
||||
if let strongSelf = self {
|
||||
if completed {
|
||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
})
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
} else {
|
||||
self.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
}
|
||||
|
@ -42,8 +42,9 @@ final class ItemListWebsiteItem: ListViewItem, ItemListItem {
|
||||
let sectionId: ItemListSectionId
|
||||
let setSessionIdWithRevealedOptions: (Int64?, Int64?) -> Void
|
||||
let removeSession: (Int64) -> Void
|
||||
let action: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, website: WebAuthorization, peer: Peer?, enabled: Bool, editing: Bool, revealed: Bool, sectionId: ItemListSectionId, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void) {
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, website: WebAuthorization, peer: Peer?, enabled: Bool, editing: Bool, revealed: Bool, sectionId: ItemListSectionId, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, action: (() -> Void)?) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
@ -56,6 +57,7 @@ final class ItemListWebsiteItem: ListViewItem, ItemListItem {
|
||||
self.sectionId = sectionId
|
||||
self.setSessionIdWithRevealedOptions = setSessionIdWithRevealedOptions
|
||||
self.removeSession = removeSession
|
||||
self.action = action
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -95,6 +97,15 @@ final class ItemListWebsiteItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var selectable: Bool = true
|
||||
public func selected(listView: ListView){
|
||||
listView.clearHighlightAnimated(true)
|
||||
|
||||
if self.enabled {
|
||||
self.action?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let avatarFont = avatarPlaceholderFont(size: 11.0)
|
||||
@ -118,12 +129,19 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
private let titleNode: TextNode
|
||||
private let appNode: TextNode
|
||||
private let locationNode: TextNode
|
||||
private let labelNode: TextNode
|
||||
|
||||
private var layoutParams: (ItemListWebsiteItem, ListViewItemLayoutParams, ItemListNeighbors)?
|
||||
|
||||
private var editableControlNode: ItemListEditableControlNode?
|
||||
|
||||
override public var canBeSelected: Bool {
|
||||
if let item = self.layoutParams?.0, let _ = item.action {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
@ -135,6 +153,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
self.avatarNode = AvatarNode(font: avatarFont)
|
||||
self.avatarNode.cornerRadius = 7.0
|
||||
@ -155,11 +174,6 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
self.locationNode.contentMode = .left
|
||||
self.locationNode.contentsScale = UIScreen.main.scale
|
||||
|
||||
self.labelNode = TextNode()
|
||||
self.labelNode.isUserInteractionEnabled = false
|
||||
self.labelNode.contentMode = .left
|
||||
self.labelNode.contentsScale = UIScreen.main.scale
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
@ -169,7 +183,6 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.appNode)
|
||||
self.addSubnode(self.locationNode)
|
||||
self.addSubnode(self.labelNode)
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: ItemListWebsiteItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) {
|
||||
@ -348,7 +361,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
@ -388,7 +401,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: strongSelf.appNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 30.0), size: appLayout.size))
|
||||
transition.updateFrame(node: strongSelf.locationNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 50.0), size: locationLayout.size))
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: 75.0 + UIScreenPixel + UIScreenPixel))
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
|
||||
strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
||||
|
||||
@ -399,6 +412,44 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
||||
super.setHighlighted(highlighted, at: point, animated: animated)
|
||||
|
||||
if highlighted && (self.layoutParams?.0.enabled ?? false) {
|
||||
self.highlightedBackgroundNode.alpha = 1.0
|
||||
if self.highlightedBackgroundNode.supernode == nil {
|
||||
var anchorNode: ASDisplayNode?
|
||||
if self.bottomStripeNode.supernode != nil {
|
||||
anchorNode = self.bottomStripeNode
|
||||
} else if self.topStripeNode.supernode != nil {
|
||||
anchorNode = self.topStripeNode
|
||||
} else if self.backgroundNode.supernode != nil {
|
||||
anchorNode = self.backgroundNode
|
||||
}
|
||||
if let anchorNode = anchorNode {
|
||||
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode)
|
||||
} else {
|
||||
self.addSubnode(self.highlightedBackgroundNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.highlightedBackgroundNode.supernode != nil {
|
||||
if animated {
|
||||
self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
||||
if let strongSelf = self {
|
||||
if completed {
|
||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
})
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
} else {
|
||||
self.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
}
|
||||
@ -427,8 +478,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: params.leftInset + self.revealOffset + editingOffset + 16.0, y: self.avatarNode.frame.minY), size: self.avatarNode.bounds.size))
|
||||
transition.updateFrame(node: self.labelNode, frame: CGRect(origin: CGPoint(x: self.revealOffset + params.width - params.rightInset - self.labelNode.bounds.size.width - 15.0, y: self.labelNode.frame.minY), size: self.labelNode.bounds.size))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + self.revealOffset + editingOffset + 20.0, y: self.titleNode.frame.minY), size: self.titleNode.bounds.size))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + self.revealOffset + editingOffset, y: self.titleNode.frame.minY), size: self.titleNode.bounds.size))
|
||||
transition.updateFrame(node: self.appNode, frame: CGRect(origin: CGPoint(x: leftInset + self.revealOffset + editingOffset, y: self.appNode.frame.minY), size: self.appNode.bounds.size))
|
||||
transition.updateFrame(node: self.locationNode, frame: CGRect(origin: CGPoint(x: leftInset + self.revealOffset + editingOffset, y: self.locationNode.frame.minY), size: self.locationNode.bounds.size))
|
||||
}
|
||||
|
@ -19,19 +19,25 @@ private final class RecentSessionsControllerArguments {
|
||||
let removeSession: (Int64) -> Void
|
||||
let terminateOtherSessions: () -> Void
|
||||
|
||||
let openSession: (RecentAccountSession) -> Void
|
||||
let openWebSession: (WebAuthorization) -> Void
|
||||
|
||||
let removeWebSession: (Int64) -> Void
|
||||
let terminateAllWebSessions: () -> Void
|
||||
|
||||
|
||||
let addDevice: () -> Void
|
||||
|
||||
let openOtherAppsUrl: () -> Void
|
||||
|
||||
init(context: AccountContext, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, terminateOtherSessions: @escaping () -> Void, removeWebSession: @escaping (Int64) -> Void, terminateAllWebSessions: @escaping () -> Void, addDevice: @escaping () -> Void, openOtherAppsUrl: @escaping () -> Void) {
|
||||
init(context: AccountContext, setSessionIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, removeSession: @escaping (Int64) -> Void, terminateOtherSessions: @escaping () -> Void, openSession: @escaping (RecentAccountSession) -> Void, openWebSession: @escaping (WebAuthorization) -> Void, removeWebSession: @escaping (Int64) -> Void, terminateAllWebSessions: @escaping () -> Void, addDevice: @escaping () -> Void, openOtherAppsUrl: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.setSessionIdWithRevealedOptions = setSessionIdWithRevealedOptions
|
||||
self.removeSession = removeSession
|
||||
self.terminateOtherSessions = terminateOtherSessions
|
||||
|
||||
self.openSession = openSession
|
||||
self.openWebSession = openWebSession
|
||||
|
||||
self.removeWebSession = removeWebSession
|
||||
self.terminateAllWebSessions = terminateAllWebSessions
|
||||
|
||||
@ -271,6 +277,8 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
case let .currentSession(_, _, dateTimeFormat, session):
|
||||
return ItemListRecentSessionItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, session: session, enabled: true, editable: false, editing: false, revealed: false, sectionId: self.section, setSessionIdWithRevealedOptions: { _, _ in
|
||||
}, removeSession: { _ in
|
||||
}, action: {
|
||||
|
||||
})
|
||||
case let .terminateOtherSessions(theme, text):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.blockDestructiveIcon(theme), title: text, sectionId: self.section, height: .generic, color: .destructive, editing: false, action: {
|
||||
@ -298,6 +306,8 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
arguments.setSessionIdWithRevealedOptions(previousId, id)
|
||||
}, removeSession: { id in
|
||||
arguments.removeSession(id)
|
||||
}, action: {
|
||||
|
||||
})
|
||||
case let .pendingSessionsInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
@ -312,12 +322,16 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
|
||||
arguments.setSessionIdWithRevealedOptions(previousId, id)
|
||||
}, removeSession: { id in
|
||||
arguments.removeSession(id)
|
||||
}, action: {
|
||||
arguments.openSession(session)
|
||||
})
|
||||
case let .website(_, _, _, dateTimeFormat, nameDisplayOrder, website, peer, enabled, editing, revealed):
|
||||
return ItemListWebsiteItem(context: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, website: website, peer: peer, enabled: enabled, editing: editing, revealed: revealed, sectionId: self.section, setSessionIdWithRevealedOptions: { previousId, id in
|
||||
arguments.setSessionIdWithRevealedOptions(previousId, id)
|
||||
}, removeSession: { id in
|
||||
arguments.removeWebSession(id)
|
||||
}, action: {
|
||||
arguments.openWebSession(website)
|
||||
})
|
||||
case let .devicesInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { action in
|
||||
@ -588,6 +602,16 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont
|
||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||
])
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}, openSession: { session in
|
||||
let controller = RecentSessionScreen(context: context, subject: .session(session), remove: {
|
||||
|
||||
})
|
||||
presentControllerImpl?(controller, nil)
|
||||
}, openWebSession: { session in
|
||||
let controller = RecentSessionScreen(context: context, subject: .website(session), remove: {
|
||||
|
||||
})
|
||||
presentControllerImpl?(controller, nil)
|
||||
}, removeWebSession: { sessionId in
|
||||
updateState {
|
||||
return $0.withUpdatedRemovingSessionId(sessionId)
|
||||
|
@ -0,0 +1,506 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import AccountContext
|
||||
import SolidRoundedButtonNode
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import TelegramStringFormatting
|
||||
import PresentationDataUtils
|
||||
import AnimationUI
|
||||
import MergeLists
|
||||
import MediaResources
|
||||
import StickerResources
|
||||
import AnimatedStickerNode
|
||||
import TelegramAnimatedStickerNode
|
||||
|
||||
private func closeButtonImage(theme: PresentationTheme) -> UIImage? {
|
||||
return generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setFillColor(UIColor(rgb: 0x808084, alpha: 0.1).cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setLineWidth(2.0)
|
||||
context.setLineCap(.round)
|
||||
context.setStrokeColor(theme.actionSheet.inputClearButtonColor.cgColor)
|
||||
|
||||
context.move(to: CGPoint(x: 10.0, y: 10.0))
|
||||
context.addLine(to: CGPoint(x: 20.0, y: 20.0))
|
||||
context.strokePath()
|
||||
|
||||
context.move(to: CGPoint(x: 20.0, y: 10.0))
|
||||
context.addLine(to: CGPoint(x: 10.0, y: 20.0))
|
||||
context.strokePath()
|
||||
})
|
||||
}
|
||||
|
||||
final class RecentSessionScreen: ViewController {
|
||||
enum Subject {
|
||||
case session(RecentAccountSession)
|
||||
case website(WebAuthorization)
|
||||
}
|
||||
private var controllerNode: RecentSessionScreenNode {
|
||||
return self.displayNode as! RecentSessionScreenNode
|
||||
}
|
||||
|
||||
private var animatedIn = false
|
||||
|
||||
private let context: AccountContext
|
||||
private let subject: RecentSessionScreen.Subject
|
||||
private let remove: () -> Void
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
var dismissed: (() -> Void)?
|
||||
|
||||
var passthroughHitTestImpl: ((CGPoint) -> UIView?)? {
|
||||
didSet {
|
||||
if self.isNodeLoaded {
|
||||
self.controllerNode.passthroughHitTestImpl = self.passthroughHitTestImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(context: AccountContext, subject: RecentSessionScreen.Subject, remove: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.subject = subject
|
||||
self.remove = remove
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
|
||||
self.blocksBackgroundWhenInOverlay = true
|
||||
|
||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||
}
|
||||
})
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = RecentSessionScreenNode(context: self.context, presentationData: self.presentationData, controller: self, subject: self.subject)
|
||||
self.controllerNode.passthroughHitTestImpl = self.passthroughHitTestImpl
|
||||
self.controllerNode.present = { [weak self] c in
|
||||
self?.present(c, in: .current)
|
||||
}
|
||||
self.controllerNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
override public func loadView() {
|
||||
super.loadView()
|
||||
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.animatedIn {
|
||||
self.animatedIn = true
|
||||
self.controllerNode.animateIn()
|
||||
}
|
||||
}
|
||||
|
||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||
self.controllerNode.animateOut(completion: completion)
|
||||
|
||||
self.dismissed?()
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private weak var controller: RecentSessionScreen?
|
||||
private let subject: RecentSessionScreen.Subject
|
||||
|
||||
private let dimNode: ASDisplayNode
|
||||
private let wrappingScrollNode: ASScrollNode
|
||||
private let contentContainerNode: ASDisplayNode
|
||||
private let topContentContainerNode: SparseNode
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let contentBackgroundNode: ASDisplayNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let fieldBackgroundNode: ASDisplayNode
|
||||
private let deviceTitleNode: ImmediateTextNode
|
||||
private let deviceValueNode: ImmediateTextNode
|
||||
private let firstSeparatorNode: ASDisplayNode
|
||||
private let locationTitleNode: ImmediateTextNode
|
||||
private let locationValueNode: ImmediateTextNode
|
||||
private let secondSeparatorNode: ASDisplayNode
|
||||
private let ipTitleNode: ImmediateTextNode
|
||||
private let ipValueNode: ImmediateTextNode
|
||||
|
||||
private let cancelButton: HighlightableButtonNode
|
||||
private let terminateButton: SolidRoundedButtonNode
|
||||
|
||||
private var containerLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
var present: ((ViewController) -> Void)?
|
||||
var remove: (() -> Void)?
|
||||
var dismiss: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData, controller: RecentSessionScreen, subject: RecentSessionScreen.Subject) {
|
||||
self.context = context
|
||||
self.controller = controller
|
||||
self.presentationData = presentationData
|
||||
self.subject = subject
|
||||
|
||||
self.wrappingScrollNode = ASScrollNode()
|
||||
self.wrappingScrollNode.view.alwaysBounceVertical = true
|
||||
self.wrappingScrollNode.view.delaysContentTouches = false
|
||||
self.wrappingScrollNode.view.canCancelContentTouches = true
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
|
||||
self.contentContainerNode = ASDisplayNode()
|
||||
self.contentContainerNode.isOpaque = false
|
||||
|
||||
self.topContentContainerNode = SparseNode()
|
||||
self.topContentContainerNode.isOpaque = false
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.clipsToBounds = true
|
||||
self.backgroundNode.cornerRadius = 16.0
|
||||
|
||||
let backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
|
||||
let textColor = self.presentationData.theme.list.itemPrimaryTextColor
|
||||
let accentColor = self.presentationData.theme.list.itemAccentColor
|
||||
let secondaryTextColor = self.presentationData.theme.list.itemSecondaryTextColor
|
||||
|
||||
self.contentBackgroundNode = ASDisplayNode()
|
||||
self.contentBackgroundNode.backgroundColor = backgroundColor
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.textNode = ImmediateTextNode()
|
||||
|
||||
self.fieldBackgroundNode = ASDisplayNode()
|
||||
self.fieldBackgroundNode.clipsToBounds = true
|
||||
self.fieldBackgroundNode.cornerRadius = 11
|
||||
self.fieldBackgroundNode.backgroundColor = self.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
|
||||
self.deviceTitleNode = ImmediateTextNode()
|
||||
self.deviceValueNode = ImmediateTextNode()
|
||||
|
||||
self.locationTitleNode = ImmediateTextNode()
|
||||
self.locationValueNode = ImmediateTextNode()
|
||||
|
||||
self.ipTitleNode = ImmediateTextNode()
|
||||
self.ipValueNode = ImmediateTextNode()
|
||||
|
||||
self.cancelButton = HighlightableButtonNode()
|
||||
self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal)
|
||||
|
||||
self.terminateButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemBlocksBackgroundColor, foregroundColor: self.presentationData.theme.list.itemDestructiveColor), font: .regular, height: 44.0, cornerRadius: 11.0, gloss: false)
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
let title: String
|
||||
let subtitle: String
|
||||
let subtitleActive: Bool
|
||||
let device: String
|
||||
let location: String
|
||||
let ip: String
|
||||
switch subject {
|
||||
case let .session(session):
|
||||
self.terminateButton.title = self.presentationData.strings.AuthSessions_View_TerminateSession
|
||||
title = "\(session.appName) \(session.appVersion)"
|
||||
if session.isCurrent {
|
||||
subtitle = presentationData.strings.Presence_online
|
||||
subtitleActive = true
|
||||
} else {
|
||||
subtitle = stringForRelativeActivityTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, relativeTimestamp: session.activityDate, relativeTo: timestamp)
|
||||
subtitleActive = false
|
||||
}
|
||||
var deviceString = ""
|
||||
if !session.deviceModel.isEmpty {
|
||||
deviceString = session.deviceModel
|
||||
}
|
||||
if !session.platform.isEmpty {
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
deviceString += session.platform
|
||||
}
|
||||
if !session.systemVersion.isEmpty {
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
deviceString += session.systemVersion
|
||||
}
|
||||
device = deviceString
|
||||
location = session.country
|
||||
ip = session.ip
|
||||
case let .website(website):
|
||||
self.terminateButton.title = self.presentationData.strings.AuthSessions_View_Logout
|
||||
title = website.domain
|
||||
subtitle = stringForRelativeActivityTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, relativeTimestamp: website.dateActive, relativeTo: timestamp)
|
||||
subtitleActive = false
|
||||
|
||||
var deviceString = ""
|
||||
if !website.domain.isEmpty {
|
||||
deviceString = website.domain
|
||||
}
|
||||
if !website.browser.isEmpty {
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
deviceString += website.browser
|
||||
}
|
||||
if !website.platform.isEmpty {
|
||||
if !deviceString.isEmpty {
|
||||
deviceString += ", "
|
||||
}
|
||||
deviceString += website.platform
|
||||
}
|
||||
device = deviceString
|
||||
location = website.region
|
||||
ip = website.ip
|
||||
}
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(30.0), textColor: textColor)
|
||||
self.textNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(17.0), textColor: subtitleActive ? accentColor : secondaryTextColor)
|
||||
|
||||
self.deviceTitleNode.attributedText = NSAttributedString(string: self.presentationData.strings.AuthSessions_View_Device, font: Font.regular(17.0), textColor: textColor)
|
||||
self.deviceValueNode.attributedText = NSAttributedString(string: device, font: Font.regular(17.0), textColor: secondaryTextColor)
|
||||
|
||||
self.firstSeparatorNode = ASDisplayNode()
|
||||
|
||||
self.locationTitleNode.attributedText = NSAttributedString(string: self.presentationData.strings.AuthSessions_View_Location, font: Font.regular(17.0), textColor: textColor)
|
||||
self.locationValueNode.attributedText = NSAttributedString(string: location, font: Font.regular(17.0), textColor: secondaryTextColor)
|
||||
|
||||
self.secondSeparatorNode = ASDisplayNode()
|
||||
|
||||
self.ipTitleNode.attributedText = NSAttributedString(string: self.presentationData.strings.AuthSessions_View_IP, font: Font.regular(17.0), textColor: textColor)
|
||||
self.ipValueNode.attributedText = NSAttributedString(string: ip, font: Font.regular(17.0), textColor: secondaryTextColor)
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = nil
|
||||
self.isOpaque = false
|
||||
|
||||
self.addSubnode(self.dimNode)
|
||||
|
||||
self.wrappingScrollNode.view.delegate = self
|
||||
self.addSubnode(self.wrappingScrollNode)
|
||||
|
||||
self.wrappingScrollNode.addSubnode(self.backgroundNode)
|
||||
self.wrappingScrollNode.addSubnode(self.contentContainerNode)
|
||||
self.wrappingScrollNode.addSubnode(self.topContentContainerNode)
|
||||
|
||||
self.backgroundNode.addSubnode(self.contentBackgroundNode)
|
||||
self.contentContainerNode.addSubnode(self.titleNode)
|
||||
self.contentContainerNode.addSubnode(self.textNode)
|
||||
|
||||
self.contentContainerNode.addSubnode(self.fieldBackgroundNode)
|
||||
|
||||
self.contentContainerNode.addSubnode(self.deviceTitleNode)
|
||||
self.contentContainerNode.addSubnode(self.deviceValueNode)
|
||||
|
||||
self.contentContainerNode.addSubnode(self.locationTitleNode)
|
||||
self.contentContainerNode.addSubnode(self.locationValueNode)
|
||||
|
||||
self.contentContainerNode.addSubnode(self.ipTitleNode)
|
||||
self.contentContainerNode.addSubnode(self.ipValueNode)
|
||||
|
||||
self.contentContainerNode.addSubnode(self.terminateButton)
|
||||
self.topContentContainerNode.addSubnode(self.cancelButton)
|
||||
|
||||
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.terminateButton.pressed = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.terminateButton.isUserInteractionEnabled = false
|
||||
strongSelf.remove?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
guard !self.animatedOut else {
|
||||
return
|
||||
}
|
||||
let previousTheme = self.presentationData.theme
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.regular(30.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
||||
self.fieldBackgroundNode.backgroundColor = self.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
|
||||
self.deviceTitleNode.attributedText = NSAttributedString(string: self.deviceTitleNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.locationTitleNode.attributedText = NSAttributedString(string: self.locationTitleNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.ipTitleNode.attributedText = NSAttributedString(string: self.ipTitleNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
|
||||
self.deviceValueNode.attributedText = NSAttributedString(string: self.deviceValueNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
|
||||
self.locationValueNode.attributedText = NSAttributedString(string: self.locationValueNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
|
||||
self.ipValueNode.attributedText = NSAttributedString(string: self.ipValueNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
||||
if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout {
|
||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
}
|
||||
|
||||
self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal)
|
||||
self.terminateButton.updateTheme(SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemBlocksBackgroundColor, foregroundColor: self.presentationData.theme.list.itemDestructiveColor))
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||
self.wrappingScrollNode.view.contentInsetAdjustmentBehavior = .never
|
||||
}
|
||||
|
||||
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture)))
|
||||
}
|
||||
|
||||
@objc func cancelButtonPressed() {
|
||||
self.animateOut()
|
||||
}
|
||||
|
||||
@objc func dimTapGesture() {
|
||||
self.cancelButtonPressed()
|
||||
}
|
||||
|
||||
private var animatedOut = false
|
||||
func animateIn() {
|
||||
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
|
||||
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||
let dimPosition = self.dimNode.layer.position
|
||||
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
|
||||
let targetBounds = self.bounds
|
||||
self.bounds = self.bounds.offsetBy(dx: 0.0, dy: -offset)
|
||||
self.dimNode.position = CGPoint(x: dimPosition.x, y: dimPosition.y - offset)
|
||||
transition.animateView({
|
||||
self.bounds = targetBounds
|
||||
self.dimNode.position = dimPosition
|
||||
})
|
||||
}
|
||||
|
||||
func animateOut(completion: (() -> Void)? = nil) {
|
||||
self.animatedOut = true
|
||||
|
||||
var dimCompleted = false
|
||||
var offsetCompleted = false
|
||||
|
||||
let internalCompletion: () -> Void = { [weak self] in
|
||||
if let strongSelf = self, dimCompleted && offsetCompleted {
|
||||
strongSelf.dismiss?()
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
|
||||
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
|
||||
dimCompleted = true
|
||||
internalCompletion()
|
||||
})
|
||||
|
||||
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||
self.wrappingScrollNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
|
||||
offsetCompleted = true
|
||||
internalCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
var passthroughHitTestImpl: ((CGPoint) -> UIView?)?
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if self.bounds.contains(point) {
|
||||
if !self.contentBackgroundNode.bounds.contains(self.convert(point, to: self.contentBackgroundNode)) {
|
||||
return self.dimNode.view
|
||||
}
|
||||
}
|
||||
return super.hitTest(point, with: event)
|
||||
}
|
||||
|
||||
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
||||
let contentOffset = scrollView.contentOffset
|
||||
let additionalTopHeight = max(0.0, -contentOffset.y)
|
||||
|
||||
if additionalTopHeight >= 30.0 {
|
||||
self.cancelButtonPressed()
|
||||
}
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.containerLayout = (layout, navigationBarHeight)
|
||||
|
||||
var insets = layout.insets(options: [.statusBar, .input])
|
||||
let cleanInsets = layout.insets(options: [.statusBar])
|
||||
insets.top = max(10.0, insets.top)
|
||||
|
||||
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
|
||||
let titleHeight: CGFloat = 54.0
|
||||
let contentHeight = titleHeight + bottomInset + 188.0
|
||||
|
||||
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
||||
|
||||
let sideInset = floor((layout.size.width - width) / 2.0)
|
||||
let contentContainerFrame = CGRect(origin: CGPoint(x: sideInset, y: layout.size.height - contentHeight), size: CGSize(width: width, height: contentHeight))
|
||||
let contentFrame = contentContainerFrame
|
||||
|
||||
var backgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX, y: contentFrame.minY), size: CGSize(width: contentFrame.width, height: contentFrame.height + 2000.0))
|
||||
if backgroundFrame.minY < contentFrame.minY {
|
||||
backgroundFrame.origin.y = contentFrame.minY
|
||||
}
|
||||
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
||||
transition.updateFrame(node: self.contentBackgroundNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||
transition.updateFrame(node: self.wrappingScrollNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: width - 90.0, height: titleHeight))
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((contentFrame.width - titleSize.width) / 2.0), y: 120.0), size: titleSize)
|
||||
transition.updateFrame(node: self.titleNode, frame: titleFrame)
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - 90.0, height: titleHeight))
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((contentFrame.width - textSize.width) / 2.0), y: titleFrame.maxY), size: textSize)
|
||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
||||
|
||||
let cancelSize = CGSize(width: 44.0, height: 44.0)
|
||||
let cancelFrame = CGRect(origin: CGPoint(x: contentFrame.width - cancelSize.width - 3.0, y: 6.0), size: cancelSize)
|
||||
transition.updateFrame(node: self.cancelButton, frame: cancelFrame)
|
||||
|
||||
let buttonInset: CGFloat = 16.0
|
||||
let doneButtonHeight = self.terminateButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
||||
transition.updateFrame(node: self.terminateButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 6.0, width: contentFrame.width, height: doneButtonHeight))
|
||||
|
||||
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
|
||||
transition.updateFrame(node: self.topContentContainerNode, frame: contentContainerFrame)
|
||||
|
||||
var listInsets = UIEdgeInsets()
|
||||
listInsets.top += layout.safeInsets.left + 12.0
|
||||
listInsets.bottom += layout.safeInsets.right + 12.0
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1012,7 +1012,9 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
|
||||
colorItemNode?.prepareCrossfadeTransition()
|
||||
}
|
||||
|
||||
let crossfadeController = ThemeSettingsCrossfadeController(view: view, topOffset: topOffset, bottomOffset: bottomOffset, leftOffset: leftOffset)
|
||||
let sectionInset = max(16.0, floor((controller.displayNode.frame.width - 674.0) / 2.0))
|
||||
|
||||
let crossfadeController = ThemeSettingsCrossfadeController(view: view, topOffset: topOffset, bottomOffset: bottomOffset, leftOffset: leftOffset, sideInset: sectionInset)
|
||||
crossfadeController.didAppear = { [weak themeItemNode, weak colorItemNode] in
|
||||
if view != nil {
|
||||
themeItemNode?.animateCrossfadeTransition()
|
||||
|
@ -1067,7 +1067,9 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
themeItemNode?.prepareCrossfadeTransition()
|
||||
}
|
||||
|
||||
let crossfadeController = ThemeSettingsCrossfadeController(view: view, topOffset: topOffset, bottomOffset: bottomOffset, leftOffset: leftOffset)
|
||||
let sectionInset = max(16.0, floor((controller.displayNode.frame.width - 674.0) / 2.0))
|
||||
|
||||
let crossfadeController = ThemeSettingsCrossfadeController(view: view, topOffset: topOffset, bottomOffset: bottomOffset, leftOffset: leftOffset, sideInset: sectionInset)
|
||||
crossfadeController.didAppear = { [weak themeItemNode] in
|
||||
if view != nil {
|
||||
themeItemNode?.animateCrossfadeTransition()
|
||||
@ -1248,9 +1250,12 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
private var bottomSnapshotView: UIView?
|
||||
private var sideSnapshotView: UIView?
|
||||
|
||||
private var leftSnapshotView: UIView?
|
||||
private var rightSnapshotView: UIView?
|
||||
|
||||
var didAppear: (() -> Void)?
|
||||
|
||||
public init(view: UIView? = nil, topOffset: CGFloat? = nil, bottomOffset: CGFloat? = nil, leftOffset: CGFloat? = nil) {
|
||||
public init(view: UIView? = nil, topOffset: CGFloat? = nil, bottomOffset: CGFloat? = nil, leftOffset: CGFloat? = nil, sideInset: CGFloat = 0.0) {
|
||||
if let view = view {
|
||||
if var leftOffset = leftOffset {
|
||||
leftOffset += UIScreenPixel
|
||||
@ -1281,6 +1286,58 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
if sideInset > 0.0 {
|
||||
if let view = view.snapshotView(afterScreenUpdates: false) {
|
||||
let clipView = UIView()
|
||||
clipView.clipsToBounds = true
|
||||
clipView.addSubview(view)
|
||||
|
||||
view.clipsToBounds = true
|
||||
view.contentMode = .topLeft
|
||||
|
||||
if let topOffset = topOffset, let bottomOffset = bottomOffset {
|
||||
var frame = view.frame
|
||||
frame.origin.y = topOffset
|
||||
frame.size.width = sideInset
|
||||
frame.size.height = bottomOffset - topOffset
|
||||
clipView.frame = frame
|
||||
|
||||
frame = view.frame
|
||||
frame.origin.y = -topOffset
|
||||
frame.size.width = sideInset
|
||||
frame.size.height = bottomOffset
|
||||
view.frame = frame
|
||||
}
|
||||
|
||||
self.leftSnapshotView = clipView
|
||||
}
|
||||
if let view = view.snapshotView(afterScreenUpdates: false) {
|
||||
let clipView = UIView()
|
||||
clipView.clipsToBounds = true
|
||||
clipView.addSubview(view)
|
||||
|
||||
view.clipsToBounds = true
|
||||
view.contentMode = .topRight
|
||||
|
||||
if let topOffset = topOffset, let bottomOffset = bottomOffset {
|
||||
var frame = view.frame
|
||||
frame.origin.x = frame.width - sideInset
|
||||
frame.origin.y = topOffset
|
||||
frame.size.width = sideInset
|
||||
frame.size.height = bottomOffset - topOffset
|
||||
clipView.frame = frame
|
||||
|
||||
frame = view.frame
|
||||
frame.origin.y = -topOffset
|
||||
frame.size.width = sideInset
|
||||
frame.size.height = bottomOffset
|
||||
view.frame = frame
|
||||
}
|
||||
|
||||
self.rightSnapshotView = clipView
|
||||
}
|
||||
}
|
||||
|
||||
if let view = view.snapshotView(afterScreenUpdates: false) {
|
||||
view.clipsToBounds = true
|
||||
view.contentMode = .top
|
||||
@ -1332,7 +1389,13 @@ public final class ThemeSettingsCrossfadeController: ViewController {
|
||||
}
|
||||
if let sideSnapshotView = self.sideSnapshotView {
|
||||
self.displayNode.view.addSubview(sideSnapshotView)
|
||||
}
|
||||
}
|
||||
if let leftSnapshotView = self.leftSnapshotView {
|
||||
self.displayNode.view.addSubview(leftSnapshotView)
|
||||
}
|
||||
if let rightSnapshotView = self.rightSnapshotView {
|
||||
self.displayNode.view.addSubview(rightSnapshotView)
|
||||
}
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
|
@ -63,6 +63,7 @@ public enum PresentationResourceKey: Int32 {
|
||||
case itemListBlockAccentIcon
|
||||
case itemListBlockDestructiveIcon
|
||||
case itemListAddDeviceIcon
|
||||
case itemListResetIcon
|
||||
|
||||
case itemListVoiceCallIcon
|
||||
case itemListVideoCallIcon
|
||||
|
@ -216,6 +216,12 @@ public struct PresentationResourcesItemList {
|
||||
})
|
||||
}
|
||||
|
||||
public static func resetIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.itemListEditThemeIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Settings/Reset"), color: theme.list.itemAccentColor)
|
||||
})
|
||||
}
|
||||
|
||||
public static func cornersImage(_ theme: PresentationTheme, top: Bool, bottom: Bool) -> UIImage? {
|
||||
if !top && !bottom {
|
||||
return nil
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Settings/Reset.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Settings/Reset.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon-36.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
88
submodules/TelegramUI/Images.xcassets/Settings/Reset.imageset/Icon-36.pdf
vendored
Normal file
88
submodules/TelegramUI/Images.xcassets/Settings/Reset.imageset/Icon-36.pdf
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 5.334961 5.270020 cm
|
||||
0.000000 0.478431 1.000000 scn
|
||||
6.194835 19.200245 m
|
||||
5.935136 18.940548 5.935136 18.519493 6.194835 18.259792 c
|
||||
9.694835 14.759793 l
|
||||
9.954534 14.500095 10.375588 14.500095 10.635287 14.759793 c
|
||||
10.894985 15.019492 10.894985 15.440547 10.635287 15.700245 c
|
||||
8.370360 17.965172 l
|
||||
8.791913 18.030869 9.224258 18.065020 9.665000 18.065020 c
|
||||
14.268293 18.065020 18.000000 14.333313 18.000000 9.730020 c
|
||||
18.000000 5.126726 14.268293 1.395020 9.665000 1.395020 c
|
||||
5.061707 1.395020 1.330000 5.126726 1.330000 9.730020 c
|
||||
1.330000 11.844328 2.116372 13.773348 3.413577 15.243072 c
|
||||
3.656611 15.518428 3.630409 15.938666 3.355053 16.181702 c
|
||||
3.079696 16.424736 2.659458 16.398533 2.416424 16.123177 c
|
||||
0.912993 14.419802 0.000000 12.180721 0.000000 9.730020 c
|
||||
0.000000 4.392187 4.327168 0.065018 9.665000 0.065018 c
|
||||
15.002832 0.065018 19.330002 4.392187 19.330002 9.730020 c
|
||||
19.330002 15.067852 15.002832 19.395020 9.665000 19.395020 c
|
||||
9.150949 19.395020 8.645859 19.354828 8.152806 19.277313 c
|
||||
10.635287 21.759794 l
|
||||
10.894985 22.019493 10.894985 22.440548 10.635287 22.700245 c
|
||||
10.375588 22.959944 9.954534 22.959944 9.694835 22.700245 c
|
||||
6.194835 19.200245 l
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
1242
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000001332 00000 n
|
||||
0000001355 00000 n
|
||||
0000001528 00000 n
|
||||
0000001602 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
1661
|
||||
%%EOF
|
@ -1044,6 +1044,7 @@ struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||
}
|
||||
|
||||
final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
private var presentationData: PresentationData?
|
||||
private(set) var buttonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:]
|
||||
|
||||
private var currentButtons: [PeerInfoHeaderNavigationButtonSpec] = []
|
||||
@ -1060,14 +1061,10 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
|
||||
var performAction: ((PeerInfoHeaderNavigationButtonKey, ContextReferenceContentNode?) -> Void)?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func update(size: CGSize, presentationData: PresentationData, buttons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let maximumExpandOffset: CGFloat = 14.0
|
||||
let expandOffset: CGFloat = -expandFraction * maximumExpandOffset
|
||||
if self.currentButtons != buttons {
|
||||
if self.currentButtons != buttons || presentationData.strings !== self.presentationData?.strings {
|
||||
self.currentButtons = buttons
|
||||
|
||||
var nextRegularButtonOrigin = size.width - 16.0
|
||||
@ -1145,6 +1142,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.presentationData = presentationData
|
||||
}
|
||||
}
|
||||
|
||||
@ -2210,7 +2208,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
} else {
|
||||
titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize)
|
||||
if self.isSettings {
|
||||
titleFrame = titleFrame.offsetBy(dx: 0.0, dy: 6.0)
|
||||
titleFrame = titleFrame.offsetBy(dx: 0.0, dy: 13.0)
|
||||
}
|
||||
let totalSubtitleWidth = subtitleSize.width + usernameSpacing + usernameSize.width
|
||||
twoLineInfo = false
|
||||
|
@ -6616,7 +6616,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
fileprivate func updateNavigation(transition: ContainedViewLayoutTransition, additive: Bool) {
|
||||
let offsetY = self.scrollNode.view.contentOffset.y
|
||||
|
||||
if self.isSettings {
|
||||
if self.isSettings, !(self.controller?.movingInHierarchy == true) {
|
||||
let bottomOffsetY = self.scrollNode.view.contentSize.height + self.scrollNode.view.contentInset.bottom - offsetY - self.scrollNode.frame.height
|
||||
let backgroundAlpha: CGFloat = min(30.0, bottomOffsetY) / 30.0
|
||||
|
||||
@ -7262,10 +7262,12 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
||||
super.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
fileprivate var movingInHierarchy = false
|
||||
public override func willMove(toParent viewController: UIViewController?) {
|
||||
super.willMove(toParent: parent)
|
||||
|
||||
if self.isSettings, viewController == nil, let tabBarController = self.parent as? TabBarController {
|
||||
self.movingInHierarchy = true
|
||||
tabBarController.updateBackgroundAlpha(1.0, transition: .immediate)
|
||||
}
|
||||
}
|
||||
@ -7275,6 +7277,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
||||
|
||||
if self.isSettings {
|
||||
if viewController == nil {
|
||||
self.movingInHierarchy = false
|
||||
Queue.mainQueue().after(0.1) {
|
||||
self.controllerNode.resetHeaderExpansion()
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ static const void *userInfoKey = &userInfoKey;
|
||||
|
||||
- (void)_ac91f40f_setBackBarButtonItem:(UIBarButtonItem *)backBarButtonItem
|
||||
{
|
||||
UIBarButtonItem *previousItem = self.rightBarButtonItem;
|
||||
UIBarButtonItem *previousItem = self.backBarButtonItem;
|
||||
|
||||
[self _ac91f40f_setBackBarButtonItem:backBarButtonItem];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user