mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Open bots from peer info screen
This commit is contained in:
parent
0ae86bd218
commit
ed592cc64c
@ -143,9 +143,11 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/TextLoadingEffect",
|
"//submodules/TelegramUI/Components/TextLoadingEffect",
|
||||||
"//submodules/TelegramUI/Components/Settings/BirthdayPickerScreen",
|
"//submodules/TelegramUI/Components/Settings/BirthdayPickerScreen",
|
||||||
"//submodules/TelegramUI/Components/Settings/PeerSelectionScreen",
|
"//submodules/TelegramUI/Components/Settings/PeerSelectionScreen",
|
||||||
|
"//submodules/TelegramUI/Components/ButtonComponent",
|
||||||
"//submodules/ConfettiEffect",
|
"//submodules/ConfettiEffect",
|
||||||
"//submodules/ContactsPeerItem",
|
"//submodules/ContactsPeerItem",
|
||||||
"//submodules/TelegramUI/Components/PeerManagement/OldChannelsController",
|
"//submodules/TelegramUI/Components/PeerManagement/OldChannelsController",
|
||||||
|
"//submodules/UrlHandling",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -11,6 +11,9 @@ import ContextUI
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TextLoadingEffect
|
import TextLoadingEffect
|
||||||
import EmojiTextAttachmentView
|
import EmojiTextAttachmentView
|
||||||
|
import ComponentFlow
|
||||||
|
import ButtonComponent
|
||||||
|
import ComponentDisplayAdapters
|
||||||
|
|
||||||
enum PeerInfoScreenLabeledValueTextColor {
|
enum PeerInfoScreenLabeledValueTextColor {
|
||||||
case primary
|
case primary
|
||||||
@ -49,6 +52,16 @@ private struct TextLinkItemSource: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
||||||
|
final class Button {
|
||||||
|
let title: String
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
init(title: String, action: @escaping () -> Void) {
|
||||||
|
self.title = title
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let id: AnyHashable
|
let id: AnyHashable
|
||||||
let context: AccountContext?
|
let context: AccountContext?
|
||||||
let label: String
|
let label: String
|
||||||
@ -62,6 +75,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
|||||||
let longTapAction: ((ASDisplayNode) -> Void)?
|
let longTapAction: ((ASDisplayNode) -> Void)?
|
||||||
let linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise<Bool>?) -> Void)?
|
let linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise<Bool>?) -> Void)?
|
||||||
let iconAction: (() -> Void)?
|
let iconAction: (() -> Void)?
|
||||||
|
let button: Button?
|
||||||
let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
|
let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
|
||||||
let requestLayout: () -> Void
|
let requestLayout: () -> Void
|
||||||
|
|
||||||
@ -79,6 +93,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
|||||||
longTapAction: ((ASDisplayNode) -> Void)? = nil,
|
longTapAction: ((ASDisplayNode) -> Void)? = nil,
|
||||||
linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise<Bool>?) -> Void)? = nil,
|
linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise<Bool>?) -> Void)? = nil,
|
||||||
iconAction: (() -> Void)? = nil,
|
iconAction: (() -> Void)? = nil,
|
||||||
|
button: Button? = nil,
|
||||||
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil,
|
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil,
|
||||||
requestLayout: @escaping () -> Void
|
requestLayout: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
@ -95,6 +110,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
|||||||
self.longTapAction = longTapAction
|
self.longTapAction = longTapAction
|
||||||
self.linkItemAction = linkItemAction
|
self.linkItemAction = linkItemAction
|
||||||
self.iconAction = iconAction
|
self.iconAction = iconAction
|
||||||
|
self.button = button
|
||||||
self.contextAction = contextAction
|
self.contextAction = contextAction
|
||||||
self.requestLayout = requestLayout
|
self.requestLayout = requestLayout
|
||||||
}
|
}
|
||||||
@ -148,6 +164,8 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
|||||||
|
|
||||||
private var linkHighlightingNode: LinkHighlightingNode?
|
private var linkHighlightingNode: LinkHighlightingNode?
|
||||||
|
|
||||||
|
private var actionButton: ComponentView<Empty>?
|
||||||
|
|
||||||
private let activateArea: AccessibilityAreaNode
|
private let activateArea: AccessibilityAreaNode
|
||||||
|
|
||||||
private var validLayout: (width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool)?
|
private var validLayout: (width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool)?
|
||||||
@ -651,6 +669,52 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
|||||||
height += additionalTextSize.height + 3.0
|
height += additionalTextSize.height + 3.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let button = item.button {
|
||||||
|
height += 3.0
|
||||||
|
|
||||||
|
let actionButton: ComponentView<Empty>
|
||||||
|
if let current = self.actionButton {
|
||||||
|
actionButton = current
|
||||||
|
} else {
|
||||||
|
actionButton = ComponentView()
|
||||||
|
self.actionButton = actionButton
|
||||||
|
}
|
||||||
|
|
||||||
|
let actionButtonSize = actionButton.update(
|
||||||
|
transition: ComponentTransition(transition),
|
||||||
|
component: AnyComponent(ButtonComponent(
|
||||||
|
background: ButtonComponent.Background(
|
||||||
|
color: presentationData.theme.list.itemCheckColors.fillColor,
|
||||||
|
foreground: presentationData.theme.list.itemCheckColors.foregroundColor,
|
||||||
|
pressedColor: presentationData.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
|
||||||
|
),
|
||||||
|
content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(Text(text: button.title, font: Font.semibold(17.0), color: presentationData.theme.list.itemCheckColors.foregroundColor))),
|
||||||
|
isEnabled: true,
|
||||||
|
allowActionWhenDisabled: false,
|
||||||
|
displaysProgress: false,
|
||||||
|
action: {
|
||||||
|
button.action()
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: width - sideInset * 2.0, height: 50.0)
|
||||||
|
)
|
||||||
|
let actionButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: height), size: actionButtonSize)
|
||||||
|
if let actionButtonView = actionButton.view {
|
||||||
|
if actionButtonView.superview == nil {
|
||||||
|
self.contextSourceNode.contentNode.view.addSubview(actionButtonView)
|
||||||
|
}
|
||||||
|
transition.updateFrame(view: actionButtonView, frame: actionButtonFrame)
|
||||||
|
}
|
||||||
|
height += actionButtonSize.height
|
||||||
|
height += 16.0
|
||||||
|
} else {
|
||||||
|
if let actionButton = self.actionButton {
|
||||||
|
self.actionButton = nil
|
||||||
|
actionButton.view?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
|
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
|
||||||
self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition)
|
self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition)
|
||||||
transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset)))
|
transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset)))
|
||||||
|
|||||||
@ -109,6 +109,7 @@ import PeerNameColorItem
|
|||||||
import PeerSelectionScreen
|
import PeerSelectionScreen
|
||||||
import UIKitRuntimeUtils
|
import UIKitRuntimeUtils
|
||||||
import OldChannelsController
|
import OldChannelsController
|
||||||
|
import UrlHandling
|
||||||
|
|
||||||
public enum PeerInfoAvatarEditingMode {
|
public enum PeerInfoAvatarEditingMode {
|
||||||
case generic
|
case generic
|
||||||
@ -1203,6 +1204,7 @@ private enum InfoSection: Int, CaseIterable {
|
|||||||
case calls
|
case calls
|
||||||
case personalChannel
|
case personalChannel
|
||||||
case peerInfo
|
case peerInfo
|
||||||
|
case peerInfoTrailing
|
||||||
case peerMembers
|
case peerMembers
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,6 +1212,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
guard let data = data else {
|
guard let data = data else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var currentPeerInfoSection: InfoSection = .peerInfo
|
||||||
|
|
||||||
var items: [InfoSection: [PeerInfoScreenItem]] = [:]
|
var items: [InfoSection: [PeerInfoScreenItem]] = [:]
|
||||||
for section in InfoSection.allCases {
|
for section in InfoSection.allCases {
|
||||||
@ -1265,7 +1269,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
} else {
|
} else {
|
||||||
label = presentationData.strings.ContactInfo_PhoneLabelMobile
|
label = presentationData.strings.ContactInfo_PhoneLabelMobile
|
||||||
}
|
}
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 2, label: label, text: formattedPhone, textColor: .accent, action: { node, progress in
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 2, label: label, text: formattedPhone, textColor: .accent, action: { node, progress in
|
||||||
interaction.openPhone(phone, node, nil, progress)
|
interaction.openPhone(phone, node, nil, progress)
|
||||||
}, longTapAction: nil, contextAction: { node, gesture, _ in
|
}, longTapAction: nil, contextAction: { node, gesture, _ in
|
||||||
interaction.openPhone(phone, node, gesture, nil)
|
interaction.openPhone(phone, node, gesture, nil)
|
||||||
@ -1280,7 +1284,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string
|
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string
|
||||||
}
|
}
|
||||||
|
|
||||||
items[.peerInfo]!.append(
|
items[currentPeerInfoSection]!.append(
|
||||||
PeerInfoScreenLabeledValueItem(
|
PeerInfoScreenLabeledValueItem(
|
||||||
id: 1,
|
id: 1,
|
||||||
label: presentationData.strings.Profile_Username,
|
label: presentationData.strings.Profile_Username,
|
||||||
@ -1326,30 +1330,70 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 400, context: context, label: hasBirthdayToday ? presentationData.strings.UserInfo_BirthdayToday : presentationData.strings.UserInfo_Birthday, text: stringForCompactBirthday(birthday, strings: presentationData.strings, showAge: true), textColor: .primary, leftIcon: hasBirthdayToday ? .birthday : nil, icon: hasBirthdayToday ? .premiumGift : nil, action: birthdayAction, longTapAction: nil, iconAction: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 400, context: context, label: hasBirthdayToday ? presentationData.strings.UserInfo_BirthdayToday : presentationData.strings.UserInfo_Birthday, text: stringForCompactBirthday(birthday, strings: presentationData.strings, showAge: true), textColor: .primary, leftIcon: hasBirthdayToday ? .birthday : nil, icon: hasBirthdayToday ? .premiumGift : nil, action: birthdayAction, longTapAction: nil, iconAction: {
|
||||||
interaction.openPremiumGift()
|
interaction.openPremiumGift()
|
||||||
}, contextAction: birthdayContextAction, requestLayout: {
|
}, contextAction: birthdayContextAction, requestLayout: {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.isFake {
|
if user.isFake {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: "", text: user.botInfo != nil ? presentationData.strings.UserInfo_FakeBotWarning : presentationData.strings.UserInfo_FakeUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: "", text: user.botInfo != nil ? presentationData.strings.UserInfo_FakeBotWarning : presentationData.strings.UserInfo_FakeUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: {
|
||||||
interaction.requestLayout(false)
|
interaction.requestLayout(false)
|
||||||
}))
|
}))
|
||||||
} else if user.isScam {
|
} else if user.isScam {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: {
|
||||||
interaction.requestLayout(false)
|
interaction.requestLayout(false)
|
||||||
}))
|
}))
|
||||||
} else if let about = cachedData.about, !about.isEmpty {
|
} else if let about = cachedData.about, !about.isEmpty {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.isPremium ? enabledPublicBioEntities : enabledPrivateBioEntities), action: isMyProfile ? { node, _ in
|
var actionButton: PeerInfoScreenLabeledValueItem.Button?
|
||||||
|
if let menuButton = cachedData.botInfo?.menuButton, case let .webView(text, url) = menuButton {
|
||||||
|
//TODO:localize
|
||||||
|
actionButton = PeerInfoScreenLabeledValueItem.Button(title: "Open App", action: {
|
||||||
|
guard let parentController = interaction.getController() else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
openWebApp(
|
||||||
|
parentController: parentController,
|
||||||
|
context: context,
|
||||||
|
peer: .user(user),
|
||||||
|
buttonText: text,
|
||||||
|
url: url,
|
||||||
|
simple: false,
|
||||||
|
source: .menu
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.isPremium ? enabledPublicBioEntities : enabledPrivateBioEntities), action: isMyProfile ? { node, _ in
|
||||||
bioContextAction(node, nil, nil)
|
bioContextAction(node, nil, nil)
|
||||||
} : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: {
|
} : nil, linkItemAction: bioLinkAction, button: actionButton, contextAction: bioContextAction, requestLayout: {
|
||||||
interaction.requestLayout(false)
|
interaction.requestLayout(false)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) {
|
||||||
|
//TODO:localize
|
||||||
|
items[currentPeerInfoSection]!.append(PeerInfoScreenCommentItem(id: 800, text: "By publishing this mini app, you agree to the [Telegram Terms of Service for Developers](https://telegram.org/privacy).", linkAction: { action in
|
||||||
|
if case let .tap(url) = action {
|
||||||
|
context.sharedContext.applicationBindings.openUrl(url)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} else if actionButton != nil {
|
||||||
|
//TODO:localize
|
||||||
|
items[currentPeerInfoSection]!.append(PeerInfoScreenCommentItem(id: 800, text: "By launching this mini app, you agree to the [Terms of Service for Mini Apps](https://telegram.org/privacy).", linkAction: { action in
|
||||||
|
if case let .tap(url) = action {
|
||||||
|
context.sharedContext.applicationBindings.openUrl(url)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
if actionButton != nil {
|
||||||
|
currentPeerInfoSection = .peerInfoTrailing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let businessHours = cachedData.businessHours {
|
if let businessHours = cachedData.businessHours {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenBusinessHoursItem(id: 300, label: presentationData.strings.PeerInfo_BusinessHours_Label, businessHours: businessHours, requestLayout: { animated in
|
items[currentPeerInfoSection]!.append(PeerInfoScreenBusinessHoursItem(id: 300, label: presentationData.strings.PeerInfo_BusinessHours_Label, businessHours: businessHours, requestLayout: { animated in
|
||||||
interaction.requestLayout(animated)
|
interaction.requestLayout(animated)
|
||||||
}, longTapAction: nil, contextAction: workingHoursContextAction))
|
}, longTapAction: nil, contextAction: workingHoursContextAction))
|
||||||
}
|
}
|
||||||
@ -1357,7 +1401,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
if let businessLocation = cachedData.businessLocation {
|
if let businessLocation = cachedData.businessLocation {
|
||||||
if let coordinates = businessLocation.coordinates {
|
if let coordinates = businessLocation.coordinates {
|
||||||
let imageSignal = chatMapSnapshotImage(engine: context.engine, resource: MapSnapshotMediaResource(latitude: coordinates.latitude, longitude: coordinates.longitude, width: 90, height: 90))
|
let imageSignal = chatMapSnapshotImage(engine: context.engine, resource: MapSnapshotMediaResource(latitude: coordinates.latitude, longitude: coordinates.longitude, width: 90, height: 90))
|
||||||
items[.peerInfo]!.append(PeerInfoScreenAddressItem(
|
items[currentPeerInfoSection]!.append(PeerInfoScreenAddressItem(
|
||||||
id: 301,
|
id: 301,
|
||||||
label: presentationData.strings.PeerInfo_Location_Label,
|
label: presentationData.strings.PeerInfo_Location_Label,
|
||||||
text: businessLocation.address,
|
text: businessLocation.address,
|
||||||
@ -1368,7 +1412,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
contextAction: businessLocationContextAction
|
contextAction: businessLocationContextAction
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenAddressItem(
|
items[currentPeerInfoSection]!.append(PeerInfoScreenAddressItem(
|
||||||
id: 301,
|
id: 301,
|
||||||
label: presentationData.strings.PeerInfo_Location_Label,
|
label: presentationData.strings.PeerInfo_Location_Label,
|
||||||
text: businessLocation.address,
|
text: businessLocation.address,
|
||||||
@ -1382,25 +1426,25 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
|
|
||||||
if !isMyProfile {
|
if !isMyProfile {
|
||||||
if let reactionSourceMessageId = reactionSourceMessageId, !data.isContact {
|
if let reactionSourceMessageId = reactionSourceMessageId, !data.isContact {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.UserInfo_SendMessage, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.UserInfo_SendMessage, action: {
|
||||||
interaction.openChat(nil)
|
interaction.openChat(nil)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.ReportPeer_BanAndReport, color: .destructive, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.ReportPeer_BanAndReport, color: .destructive, action: {
|
||||||
interaction.openReport(.reaction(reactionSourceMessageId))
|
interaction.openReport(.reaction(reactionSourceMessageId))
|
||||||
}))
|
}))
|
||||||
} else if let _ = nearbyPeerDistance {
|
} else if let _ = nearbyPeerDistance {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.UserInfo_SendMessage, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.UserInfo_SendMessage, action: {
|
||||||
interaction.openChat(nil)
|
interaction.openChat(nil)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.ReportPeer_Report, color: .destructive, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.ReportPeer_Report, color: .destructive, action: {
|
||||||
interaction.openReport(.user)
|
interaction.openReport(.user)
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
if !data.isContact {
|
if !data.isContact {
|
||||||
if user.botInfo == nil {
|
if user.botInfo == nil {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.PeerInfo_AddToContacts, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 3, text: presentationData.strings.PeerInfo_AddToContacts, action: {
|
||||||
interaction.openAddContact()
|
interaction.openAddContact()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1412,14 +1456,14 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isBlocked {
|
if isBlocked {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Unblock : presentationData.strings.Conversation_Unblock, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Unblock : presentationData.strings.Conversation_Unblock, action: {
|
||||||
interaction.updateBlocked(false)
|
interaction.updateBlocked(false)
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
if user.flags.contains(.isSupport) || data.isContact {
|
if user.flags.contains(.isSupport) || data.isContact {
|
||||||
} else {
|
} else {
|
||||||
if user.botInfo == nil {
|
if user.botInfo == nil {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.Conversation_BlockUser, color: .destructive, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 4, text: presentationData.strings.Conversation_BlockUser, color: .destructive, action: {
|
||||||
interaction.updateBlocked(true)
|
interaction.updateBlocked(true)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1427,22 +1471,22 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let encryptionKeyFingerprint = data.encryptionKeyFingerprint {
|
if let encryptionKeyFingerprint = data.encryptionKeyFingerprint {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenDisclosureEncryptionKeyItem(id: 5, text: presentationData.strings.Profile_EncryptionKey, fingerprint: encryptionKeyFingerprint, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenDisclosureEncryptionKeyItem(id: 5, text: presentationData.strings.Profile_EncryptionKey, fingerprint: encryptionKeyFingerprint, action: {
|
||||||
interaction.openEncryptionKey()
|
interaction.openEncryptionKey()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.botInfo != nil {
|
if user.botInfo != nil {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.ReportPeer_Report, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.ReportPeer_Report, action: {
|
||||||
interaction.openReport(.default)
|
interaction.openReport(.default)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let botInfo = user.botInfo, botInfo.flags.contains(.worksWithGroups) {
|
if let botInfo = user.botInfo, botInfo.flags.contains(.worksWithGroups) {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 7, text: presentationData.strings.Bot_AddToChat, color: .accent, action: {
|
items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: 7, text: presentationData.strings.Bot_AddToChat, color: .accent, action: {
|
||||||
interaction.openAddBotToGroup()
|
interaction.openAddBotToGroup()
|
||||||
}))
|
}))
|
||||||
items[.peerInfo]!.append(PeerInfoScreenCommentItem(id: 8, text: presentationData.strings.Bot_AddToChatInfo))
|
items[currentPeerInfoSection]!.append(PeerInfoScreenCommentItem(id: 8, text: presentationData.strings.Bot_AddToChatInfo))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1472,7 +1516,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
|
|
||||||
let linkText = "https://t.me/\(mainUsername)/\(threadId)"
|
let linkText = "https://t.me/\(mainUsername)/\(threadId)"
|
||||||
|
|
||||||
items[.peerInfo]!.append(
|
items[currentPeerInfoSection]!.append(
|
||||||
PeerInfoScreenLabeledValueItem(
|
PeerInfoScreenLabeledValueItem(
|
||||||
id: ItemUsername,
|
id: ItemUsername,
|
||||||
label: presentationData.strings.Channel_LinkItem,
|
label: presentationData.strings.Channel_LinkItem,
|
||||||
@ -1499,7 +1543,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
if let _ = channel.addressName {
|
if let _ = channel.addressName {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenCommentItem(id: ItemUsernameInfo, text: presentationData.strings.PeerInfo_PrivateShareLinkInfo))
|
items[currentPeerInfoSection]!.append(PeerInfoScreenCommentItem(id: ItemUsernameInfo, text: presentationData.strings.PeerInfo_PrivateShareLinkInfo))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let location = (data.cachedData as? CachedChannelData)?.peerGeoLocation {
|
if let location = (data.cachedData as? CachedChannelData)?.peerGeoLocation {
|
||||||
@ -1524,7 +1568,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string
|
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string
|
||||||
}
|
}
|
||||||
|
|
||||||
items[.peerInfo]!.append(
|
items[currentPeerInfoSection]!.append(
|
||||||
PeerInfoScreenLabeledValueItem(
|
PeerInfoScreenLabeledValueItem(
|
||||||
id: ItemUsername,
|
id: ItemUsername,
|
||||||
label: presentationData.strings.Channel_LinkItem,
|
label: presentationData.strings.Channel_LinkItem,
|
||||||
@ -1579,7 +1623,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
if case .group = channel.info {
|
if case .group = channel.info {
|
||||||
enabledEntities = enabledPrivateBioEntities
|
enabledEntities = enabledPrivateBioEntities
|
||||||
}
|
}
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledEntities), action: isMyProfile ? { node, _ in
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledEntities), action: isMyProfile ? { node, _ in
|
||||||
bioContextAction(node, nil, nil)
|
bioContextAction(node, nil, nil)
|
||||||
} : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: {
|
} : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: {
|
||||||
interaction.requestLayout(true)
|
interaction.requestLayout(true)
|
||||||
@ -1631,7 +1675,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let aboutText = aboutText {
|
if let aboutText = aboutText {
|
||||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledPrivateBioEntities), action: isMyProfile ? { node, _ in
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledPrivateBioEntities), action: isMyProfile ? { node, _ in
|
||||||
bioContextAction(node, nil, nil)
|
bioContextAction(node, nil, nil)
|
||||||
} : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: {
|
} : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: {
|
||||||
interaction.requestLayout(true)
|
interaction.requestLayout(true)
|
||||||
@ -13685,3 +13729,192 @@ private final class HeaderContextReferenceContentSource: ContextReferenceContent
|
|||||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds)
|
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func openWebApp(parentController: ViewController, context: AccountContext, peer: EnginePeer, buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource) {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
||||||
|
|
||||||
|
let botName: String
|
||||||
|
let botAddress: String
|
||||||
|
let botVerified: Bool
|
||||||
|
if case let .inline(bot) = source {
|
||||||
|
botName = bot.compactDisplayTitle
|
||||||
|
botAddress = bot.addressName ?? ""
|
||||||
|
botVerified = bot.isVerified
|
||||||
|
} else {
|
||||||
|
botName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||||
|
botAddress = peer.addressName ?? ""
|
||||||
|
botVerified = peer.isVerified
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = botAddress
|
||||||
|
|
||||||
|
let openWebView = { [weak parentController] in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if source == .menu {
|
||||||
|
if let navigationController = parentController.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
|
||||||
|
for controller in minimizedContainer.controllers {
|
||||||
|
if let controller = controller as? AttachmentController, let mainController = controller.mainController as? WebAppController, mainController.botId == peer.id && mainController.source == .menu {
|
||||||
|
navigationController.maximizeViewController(controller, animated: true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullSize = false
|
||||||
|
if isTelegramMeLink(url), let internalUrl = parseFullInternalUrl(sharedContext: context.sharedContext, url: url), case .peer(_, .appStart) = internalUrl {
|
||||||
|
fullSize = !url.contains("?mode=compact")
|
||||||
|
}
|
||||||
|
|
||||||
|
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||||
|
let params = WebAppParameters(source: .menu, peerId: peer.id, botId: peer.id, botName: botName, botVerified: botVerified, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: fullSize)
|
||||||
|
//TODO:localize
|
||||||
|
//updatedPresentationData
|
||||||
|
let controller = standaloneWebAppController(context: context, updatedPresentationData: nil, params: params, threadId: nil, openUrl: { [weak parentController] url, concealed, commit in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = parentController
|
||||||
|
/*ChatControllerImpl.botOpenUrl(context: context, peerId: peerId, controller: self, url: url, concealed: concealed, present: { c, a in
|
||||||
|
presentImpl?(c, a)
|
||||||
|
}, commit: commit)*/
|
||||||
|
}, requestSwitchInline: { [weak parentController] query, chatTypes, completion in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = parentController
|
||||||
|
//ChatControllerImpl.botRequestSwitchInline(context: context, controller: self, peerId: peerId, botAddress: botAddress, query: query, chatTypes: chatTypes, completion: completion)
|
||||||
|
}, getInputContainerNode: {
|
||||||
|
return nil
|
||||||
|
}, completion: {
|
||||||
|
}, willDismiss: {
|
||||||
|
}, didDismiss: {
|
||||||
|
}, getNavigationController: { [weak parentController] () -> NavigationController? in
|
||||||
|
guard let parentController else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parentController.navigationController as? NavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||||
|
})
|
||||||
|
controller.navigationPresentation = .flatModal
|
||||||
|
parentController.push(controller)
|
||||||
|
|
||||||
|
presentImpl = { [weak controller] c, a in
|
||||||
|
controller?.present(c, in: .window(.root), with: a)
|
||||||
|
}
|
||||||
|
let _ = presentImpl
|
||||||
|
} else if simple {
|
||||||
|
var isInline = false
|
||||||
|
var botId = peer.id
|
||||||
|
var botName = botName
|
||||||
|
var botAddress = ""
|
||||||
|
var botVerified = false
|
||||||
|
if case let .inline(bot) = source {
|
||||||
|
isInline = true
|
||||||
|
botId = bot.id
|
||||||
|
botName = bot.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||||
|
botAddress = bot.addressName ?? ""
|
||||||
|
botVerified = bot.isVerified
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = botAddress
|
||||||
|
|
||||||
|
let _ = ((context.engine.messages.requestSimpleWebView(botId: botId, url: url, source: isInline ? .inline : .generic, themeParams: generateWebAppThemeParams(presentationData.theme)))
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak parentController] result in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||||
|
let params = WebAppParameters(source: isInline ? .inline : .simple, peerId: peer.id, botId: botId, botName: botName, botVerified: botVerified, url: result.url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: result.flags.contains(.fullSize))
|
||||||
|
let controller = standaloneWebAppController(context: context, updatedPresentationData: nil, params: params, threadId: nil, openUrl: { [weak parentController] url, concealed, commit in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = parentController
|
||||||
|
/*ChatControllerImpl.botOpenUrl(context: context, peerId: peerId, controller: self, url: url, concealed: concealed, present: { c, a in
|
||||||
|
presentImpl?(c, a)
|
||||||
|
}, commit: commit)*/
|
||||||
|
}, requestSwitchInline: { query, chatTypes, completion in
|
||||||
|
//ChatControllerImpl.botRequestSwitchInline(context: context, controller: self, peerId: peerId, botAddress: botAddress, query: query, chatTypes: chatTypes, completion: completion)
|
||||||
|
}, getNavigationController: { [weak parentController] in
|
||||||
|
guard let parentController else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parentController.navigationController as? NavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||||
|
})
|
||||||
|
controller.navigationPresentation = .flatModal
|
||||||
|
parentController.push(controller)
|
||||||
|
|
||||||
|
presentImpl = { [weak controller] c, a in
|
||||||
|
controller?.present(c, in: .window(.root), with: a)
|
||||||
|
}
|
||||||
|
let _ = presentImpl
|
||||||
|
}, error: { [weak parentController] error in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parentController.present(textAlertController(context: context, updatedPresentationData: nil, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||||
|
})]), in: .window(.root))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let _ = ((context.engine.messages.requestWebView(peerId: peer.id, botId: peer.id, url: !url.isEmpty ? url : nil, payload: nil, themeParams: generateWebAppThemeParams(presentationData.theme), fromMenu: false, replyToMessageId: nil, threadId: nil))
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak parentController] result in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||||
|
let context = context
|
||||||
|
let params = WebAppParameters(source: .button, peerId: peer.id, botId: peer.id, botName: botName, botVerified: botVerified, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false, fullSize: result.flags.contains(.fullSize))
|
||||||
|
let controller = standaloneWebAppController(context: context, updatedPresentationData: nil, params: params, threadId: nil, openUrl: { [weak parentController] url, concealed, commit in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = parentController
|
||||||
|
/*ChatControllerImpl.botOpenUrl(context: context, peerId: peerId, controller: self, url: url, concealed: concealed, present: { c, a in
|
||||||
|
presentImpl?(c, a)
|
||||||
|
}, commit: commit)*/
|
||||||
|
}, completion: {
|
||||||
|
}, getNavigationController: { [weak parentController] in
|
||||||
|
guard let parentController else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parentController.navigationController as? NavigationController ?? context.sharedContext.mainWindow?.viewController as? NavigationController
|
||||||
|
})
|
||||||
|
controller.navigationPresentation = .flatModal
|
||||||
|
parentController.push(controller)
|
||||||
|
|
||||||
|
presentImpl = { [weak controller] c, a in
|
||||||
|
controller?.present(c, in: .window(.root), with: a)
|
||||||
|
}
|
||||||
|
let _ = presentImpl
|
||||||
|
}, error: { [weak parentController] error in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parentController.present(textAlertController(context: context, updatedPresentationData: nil, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||||
|
})]), in: .window(.root))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var botPeer = peer
|
||||||
|
if case let .inline(bot) = source {
|
||||||
|
botPeer = bot
|
||||||
|
}
|
||||||
|
let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id)
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak parentController] value in
|
||||||
|
guard let parentController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if value {
|
||||||
|
openWebView()
|
||||||
|
} else {
|
||||||
|
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: nil, peer: botPeer, completion: { _ in
|
||||||
|
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||||
|
openWebView()
|
||||||
|
}, showMore: nil)
|
||||||
|
parentController.present(controller, in: .window(.root))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user