Swiftgram/submodules/TelegramUI/Sources/ChatInfoTitlePanelNode.swift
2020-08-28 17:32:21 +01:00

239 lines
8.5 KiB
Swift

import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import SyncCore
import TelegramPresentationData
private enum ChatInfoTitleButton {
case search
case info
case mute
case unmute
case call
case report
case unarchive
func title(_ strings: PresentationStrings) -> String {
switch self {
case .search:
return strings.Common_Search
case .info:
return strings.Conversation_Info
case .mute:
return strings.Conversation_TitleMute
case .unmute:
return strings.Conversation_TitleUnmute
case .call:
return strings.Conversation_Call
case .report:
return strings.ReportPeer_Report
case .unarchive:
return strings.ChatList_UnarchiveAction
}
}
func icon(_ theme: PresentationTheme) -> UIImage? {
switch self {
case .search:
return PresentationResourcesChat.chatTitlePanelSearchImage(theme)
case .info:
return PresentationResourcesChat.chatTitlePanelInfoImage(theme)
case .mute:
return PresentationResourcesChat.chatTitlePanelMuteImage(theme)
case .unmute:
return PresentationResourcesChat.chatTitlePanelUnmuteImage(theme)
case .call:
return PresentationResourcesChat.chatTitlePanelCallImage(theme)
case .report:
return PresentationResourcesChat.chatTitlePanelReportImage(theme)
case .unarchive:
return PresentationResourcesChat.chatTitlePanelUnarchiveImage(theme)
}
}
}
private func peerButtons(_ peer: Peer, interfaceState: ChatPresentationInterfaceState) -> [ChatInfoTitleButton] {
let muteAction: ChatInfoTitleButton
if interfaceState.peerIsMuted {
muteAction = .unmute
} else {
muteAction = .mute
}
let infoButton: ChatInfoTitleButton
if interfaceState.isArchived {
infoButton = .unarchive
} else {
infoButton = .info
}
if let peer = peer as? TelegramUser {
var buttons: [ChatInfoTitleButton] = [.search, muteAction]
if peer.botInfo == nil && interfaceState.callsAvailable {
buttons.append(.call)
}
buttons.append(infoButton)
return buttons
} else if let _ = peer as? TelegramSecretChat {
var buttons: [ChatInfoTitleButton] = [.search, muteAction]
buttons.append(.call)
buttons.append(.info)
return buttons
} else if let channel = peer as? TelegramChannel {
if channel.flags.contains(.isCreator) || channel.username == nil {
return [.search, muteAction, infoButton]
} else {
return [.search, .report, muteAction, infoButton]
}
} else if let group = peer as? TelegramGroup {
if case .creator = group.role {
return [.search, muteAction, infoButton]
} else {
return [.search, muteAction, infoButton]
}
} else {
return [.search, muteAction, infoButton]
}
}
private let buttonFont = Font.medium(10.0)
private final class ChatInfoTitlePanelButtonNode: HighlightableButtonNode {
init() {
super.init()
self.displaysAsynchronously = false
self.imageNode.displayWithoutProcessing = true
self.imageNode.displaysAsynchronously = false
self.titleNode.displaysAsynchronously = false
self.laysOutHorizontally = false
}
func setup(text: String, color: UIColor, icon: UIImage?) {
self.setTitle(text, with: buttonFont, with: color, for: [])
self.setImage(icon, for: [])
if let icon = icon {
self.contentSpacing = max(0.0, 32.0 - icon.size.height)
}
}
}
final class ChatInfoTitlePanelNode: ChatTitleAccessoryPanelNode {
private var theme: PresentationTheme?
private let backgroundNode: ASDisplayNode
private let separatorNode: ASDisplayNode
private var buttons: [(ChatInfoTitleButton, ChatInfoTitlePanelButtonNode)] = []
override init() {
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> CGFloat {
let themeUpdated = self.theme !== interfaceState.theme
self.theme = interfaceState.theme
let panelHeight: CGFloat = 55.0
if themeUpdated {
self.backgroundNode.backgroundColor = interfaceState.theme.chat.historyNavigation.fillColor
self.separatorNode.backgroundColor = interfaceState.theme.chat.historyNavigation.strokeColor
}
let updatedButtons: [ChatInfoTitleButton]
switch interfaceState.chatLocation {
case .peer:
if let peer = interfaceState.renderedPeer?.peer {
updatedButtons = peerButtons(peer, interfaceState: interfaceState)
} else {
updatedButtons = []
}
case .replyThread:
updatedButtons = []
}
var buttonsUpdated = false
if self.buttons.count != updatedButtons.count {
buttonsUpdated = true
} else {
for i in 0 ..< updatedButtons.count {
if self.buttons[i].0 != updatedButtons[i] {
buttonsUpdated = true
break
}
}
}
if buttonsUpdated || themeUpdated {
for (_, buttonNode) in self.buttons {
buttonNode.removeFromSupernode()
}
self.buttons.removeAll()
for button in updatedButtons {
let buttonNode = ChatInfoTitlePanelButtonNode()
buttonNode.laysOutHorizontally = false
buttonNode.setup(text: button.title(interfaceState.strings), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor, icon: button.icon(interfaceState.theme))
buttonNode.addTarget(self, action: #selector(self.buttonPressed(_:)), forControlEvents: [.touchUpInside])
self.addSubnode(buttonNode)
self.buttons.append((button, buttonNode))
}
}
if !self.buttons.isEmpty {
let buttonWidth = floor((width - leftInset - rightInset) / CGFloat(self.buttons.count))
var nextButtonOrigin: CGFloat = leftInset
for (_, buttonNode) in self.buttons {
buttonNode.frame = CGRect(origin: CGPoint(x: nextButtonOrigin, y: 0.0), size: CGSize(width: buttonWidth, height: panelHeight))
nextButtonOrigin += buttonWidth
}
}
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: panelHeight)))
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelHeight - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)))
return panelHeight
}
@objc func buttonPressed(_ node: HighlightableButtonNode) {
for (button, buttonNode) in self.buttons {
if buttonNode === node {
switch button {
case .info:
self.interfaceInteraction?.openPeerInfo()
case .mute:
self.interfaceInteraction?.togglePeerNotifications()
case .unmute:
self.interfaceInteraction?.togglePeerNotifications()
case .search:
self.interfaceInteraction?.beginMessageSearch(.everything, "")
case .call:
self.interfaceInteraction?.beginCall(false)
case .report:
self.interfaceInteraction?.reportPeer()
case .unarchive:
self.interfaceInteraction?.unarchiveChat()
}
break
}
}
}
}