Bot preview improvements

This commit is contained in:
Isaac 2024-07-25 14:52:20 +08:00
parent d14e45f681
commit df31800dcd
9 changed files with 108 additions and 66 deletions

View File

@ -149,10 +149,13 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
}) })
}))) })))
items.append(.separator) items.append(.separator)
case .popularApps:
break
} }
} }
if case .search(.recentApps) = source { if case .search(.recentApps) = source {
} else if case .search(.popularApps) = source {
} else { } else {
let isSavedMessages = peerId == context.account.peerId let isSavedMessages = peerId == context.account.peerId

View File

@ -330,6 +330,10 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
} }
} }
self.paneContainerNode.requesDismissInput = {
parentController()?.view.endEditing(true)
}
self.filterContainerNode.filterPressed = { [weak self] filter in self.filterContainerNode.filterPressed = { [weak self] filter in
guard let strongSelf = self else { guard let strongSelf = self else {
return return

View File

@ -298,13 +298,17 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
} }
}, },
deletePeer: deletePeer, deletePeer: deletePeer,
contextAction: (key == .channels) ? nil : peerContextAction.flatMap { peerContextAction in contextAction: (key == .channels || section == .popularApps) ? nil : peerContextAction.flatMap { peerContextAction in
return { node, gesture, location in return { node, gesture, location in
if let chatPeer = peer.peer.peers[peer.peer.peerId] { if let chatPeer = peer.peer.peers[peer.peer.peerId] {
let source: ChatListSearchContextActionSource let source: ChatListSearchContextActionSource
if key == .apps { if key == .apps {
source = .recentApps if case .popularApps = section {
source = .popularApps
} else {
source = .recentApps
}
} else { } else {
source = .recentSearch source = .recentSearch
} }
@ -1081,6 +1085,7 @@ public enum ChatListSearchContextActionSource {
case recentPeers case recentPeers
case recentSearch case recentSearch
case recentApps case recentApps
case popularApps
case search(EngineMessage.Id?) case search(EngineMessage.Id?)
} }

View File

@ -192,6 +192,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
var currentPaneUpdated: ((ChatListSearchPaneKey?, CGFloat, ContainedViewLayoutTransition) -> Void)? var currentPaneUpdated: ((ChatListSearchPaneKey?, CGFloat, ContainedViewLayoutTransition) -> Void)?
var requestExpandTabs: (() -> Bool)? var requestExpandTabs: (() -> Bool)?
var requesDismissInput: (() -> Void)?
private var currentAvailablePanes: [ChatListSearchPaneKey]? private var currentAvailablePanes: [ChatListSearchPaneKey]?
@ -227,12 +228,20 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams { if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams {
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring)) self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring))
} }
if case .apps = key {
self.requesDismissInput?()
}
} else if self.pendingSwitchToPaneKey != key { } else if self.pendingSwitchToPaneKey != key {
self.pendingSwitchToPaneKey = key self.pendingSwitchToPaneKey = key
if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams { if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams {
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring)) self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring))
} }
if case .apps = key {
self.requesDismissInput?()
}
} }
} }
@ -322,6 +331,10 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
let switchToKey = availablePanes[updatedIndex] let switchToKey = availablePanes[updatedIndex]
if switchToKey != self.currentPaneKey && self.currentPanes[switchToKey] != nil{ if switchToKey != self.currentPaneKey && self.currentPanes[switchToKey] != nil{
self.currentPaneKey = switchToKey self.currentPaneKey = switchToKey
if case .apps = switchToKey {
self.requesDismissInput?()
}
} }
} }
self.transitionFraction = 0.0 self.transitionFraction = 0.0

View File

@ -462,7 +462,7 @@ public final class SparseItemGrid: ASDisplayNode {
self.itemSpacing = 1.0 self.itemSpacing = 1.0
let itemsPerRow: CGFloat let itemsPerRow: CGFloat
if containerLayout.fixedItemAspect != nil && itemCount <= 2 { if containerLayout.fixedItemAspect != nil && itemCount <= 2 && containerLayout.adjustForSmallCount {
itemsPerRow = 2.0 itemsPerRow = 2.0
centerItems = itemCount == 1 centerItems = itemCount == 1
} else { } else {
@ -1607,6 +1607,7 @@ public final class SparseItemGrid: ASDisplayNode {
var lockScrollingAtTop: Bool var lockScrollingAtTop: Bool
var fixedItemHeight: CGFloat? var fixedItemHeight: CGFloat?
var fixedItemAspect: CGFloat? var fixedItemAspect: CGFloat?
var adjustForSmallCount: Bool
} }
private var tapRecognizer: UITapGestureRecognizer? private var tapRecognizer: UITapGestureRecognizer?
@ -1932,7 +1933,7 @@ public final class SparseItemGrid: ASDisplayNode {
} }
} }
public func update(size: CGSize, insets: UIEdgeInsets, useSideInsets: Bool, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, fixedItemAspect: CGFloat?, items: Items, theme: PresentationTheme, synchronous: SparseItemGrid.Synchronous, transition: ComponentTransition = .immediate) { public func update(size: CGSize, insets: UIEdgeInsets, useSideInsets: Bool, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, fixedItemAspect: CGFloat?, adjustForSmallCount: Bool = true, items: Items, theme: PresentationTheme, synchronous: SparseItemGrid.Synchronous, transition: ComponentTransition = .immediate) {
self.theme = theme self.theme = theme
var headerInset: CGFloat = 0.0 var headerInset: CGFloat = 0.0
@ -1973,7 +1974,7 @@ public final class SparseItemGrid: ASDisplayNode {
var insets = insets var insets = insets
insets.top += headerInset insets.top += headerInset
let containerLayout = ContainerLayout(size: size, insets: insets, useSideInsets: useSideInsets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect) let containerLayout = ContainerLayout(size: size, insets: insets, useSideInsets: useSideInsets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, adjustForSmallCount: adjustForSmallCount)
self.containerLayout = containerLayout self.containerLayout = containerLayout
self.items = items self.items = items
self.scrollingArea.isHidden = lockScrollingAtTop self.scrollingArea.isHidden = lockScrollingAtTop

View File

@ -77,7 +77,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
let iconAction: (() -> Void)? let iconAction: (() -> Void)?
let button: Button? let button: Button?
let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
let requestLayout: () -> Void let requestLayout: (Bool) -> Void
init( init(
id: AnyHashable, id: AnyHashable,
@ -95,7 +95,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
iconAction: (() -> Void)? = nil, iconAction: (() -> Void)? = nil,
button: Button? = nil, button: Button? = nil,
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil,
requestLayout: @escaping () -> Void requestLayout: @escaping (Bool) -> Void
) { ) {
self.id = id self.id = id
self.context = context self.context = context
@ -336,7 +336,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
@objc private func expandPressed() { @objc private func expandPressed() {
self.isExpanded = true self.isExpanded = true
self.item?.requestLayout() self.item?.requestLayout(true)
} }
@objc private func iconPressed() { @objc private func iconPressed() {

View File

@ -1273,8 +1273,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
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)
}, requestLayout: { }, requestLayout: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
})) }))
} }
if let mainUsername = user.addressName { if let mainUsername = user.addressName {
@ -1304,8 +1304,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
interaction.openQrCode() interaction.openQrCode()
}, contextAction: { node, gesture, _ in }, contextAction: { node, gesture, _ in
interaction.openUsernameContextMenu(node, gesture) interaction.openUsernameContextMenu(node, gesture)
}, requestLayout: { }, requestLayout: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
} }
) )
) )
@ -1332,7 +1332,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
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: { 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: { _ in
})) }))
} }
@ -1347,12 +1347,12 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
} }
if user.isFake { if user.isFake {
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: { 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: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
})) }))
} else if user.isScam { } else if user.isScam {
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: { 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: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
})) }))
} else if hasAbout || hasWebApp { } else if hasAbout || hasWebApp {
var actionButton: PeerInfoScreenLabeledValueItem.Button? var actionButton: PeerInfoScreenLabeledValueItem.Button?
@ -1385,8 +1385,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: label, text: cachedData.about ?? "", textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.isPremium ? enabledPublicBioEntities : enabledPrivateBioEntities), action: isMyProfile ? { node, _ in items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: label, text: cachedData.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, button: actionButton, contextAction: bioContextAction, requestLayout: { } : nil, linkItemAction: bioLinkAction, button: actionButton, contextAction: bioContextAction, requestLayout: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
})) }))
if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) { if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) {
@ -1579,8 +1579,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
} }
}, iconAction: { }, iconAction: {
interaction.openQrCode() interaction.openQrCode()
}, requestLayout: { }, requestLayout: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
} }
) )
) )
@ -1636,8 +1636,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
} }
}, iconAction: { }, iconAction: {
interaction.openQrCode() interaction.openQrCode()
}, requestLayout: { }, requestLayout: { animated in
interaction.requestLayout(false) interaction.requestLayout(animated)
} }
) )
) )
@ -1669,8 +1669,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
} }
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 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: { animated in
interaction.requestLayout(true) interaction.requestLayout(animated)
})) }))
} }
@ -1755,8 +1755,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
if let aboutText = aboutText { if let aboutText = aboutText {
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 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: { animated in
interaction.requestLayout(true) interaction.requestLayout(animated)
})) }))
} }
} }
@ -10916,19 +10916,21 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}))) })))
} }
items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in if pane.canReorder() {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in
}, action: { [weak pane] _, a in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor)
if ignoreNextActions { }, action: { [weak pane] _, a in
return if ignoreNextActions {
} return
ignoreNextActions = true }
a(.default) ignoreNextActions = true
a(.default)
if let pane {
pane.beginReordering() if let pane {
} pane.beginReordering()
}))) }
})))
}
items.append(.action(ContextMenuActionItem(text: "Select", icon: { theme in items.append(.action(ContextMenuActionItem(text: "Select", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor)

View File

@ -2495,7 +2495,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
} }
self.parentController?.present(UndoOverlayController(presentationData: presentationData, content: .universal(animation: isPinned ? "anim_toastunpin" : "anim_toastpin", scale: 0.06, colors: [:], title: toastTitle, text: toastText, customUndoText: nil, timeout: 5), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) self.parentController?.present(UndoOverlayController(presentationData: presentationData, content: .universal(animation: isPinned ? "anim_toastunpin" : "anim_toastpin", scale: 0.06, colors: [:], title: toastTitle, text: toastText, customUndoText: nil, timeout: 5), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
}))) })))
if isPinned { if isPinned && self.canReorder() {
//TODO:localize //TODO:localize
items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
@ -2560,7 +2560,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
}))) })))
} }
if canManage, case .botPreview = self.scope { if canManage, case .botPreview = self.scope, self.canReorder() {
//TODO:localize //TODO:localize
items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
@ -2571,17 +2571,6 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
self.beginReordering() self.beginReordering()
}) })
}))) })))
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Edit Preview", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in
c?.dismiss(completion: {
guard let self else {
return
}
let _ = self
})
})))
} }
if !item.isForwardingDisabled, case .everyone = item.privacy?.base { if !item.isForwardingDisabled, case .everyone = item.privacy?.base {
@ -2791,8 +2780,32 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
} }
} }
botPreviewLanguages.sort(by: { $0.name < $1.name }) botPreviewLanguages.sort(by: { $0.name < $1.name })
var hadLocalItems = false
if let currentListState = self.currentListState {
for item in currentListState.items {
if item.storyItem.isPending {
hadLocalItems = true
}
}
}
self.currentListState = state self.currentListState = state
var hasLocalItems = false
if let currentListState = self.currentListState {
for item in currentListState.items {
if item.storyItem.isPending {
hasLocalItems = true
}
}
}
var synchronous = synchronous
if hasLocalItems != hadLocalItems {
synchronous = true
}
self.updateItemsFromState(state: state, firstTime: firstTime, reloadAtTop: reloadAtTop, synchronous: synchronous, animated: false) self.updateItemsFromState(state: state, firstTime: firstTime, reloadAtTop: reloadAtTop, synchronous: synchronous, animated: false)
if self.currentBotPreviewLanguages != botPreviewLanguages || reloadAtTop { if self.currentBotPreviewLanguages != botPreviewLanguages || reloadAtTop {
@ -4113,9 +4126,14 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
fixedItemHeight = nil fixedItemHeight = nil
let fixedItemAspect: CGFloat? = 0.81 let fixedItemAspect: CGFloat? = 0.81
var adjustForSmallCount = true
if case .botPreview = self.scope {
adjustForSmallCount = false
}
self.itemGrid.pinchEnabled = items.count > 2 self.itemGrid.pinchEnabled = items.count > 2 && !self.isReordering
self.itemGrid.update(size: size, insets: UIEdgeInsets(top: gridTopInset, left: sideInset, bottom: bottomInset, right: sideInset), useSideInsets: !isList, scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none, transition: animateGridItems ? .spring(duration: 0.35) : .immediate) self.itemGrid.update(size: size, insets: UIEdgeInsets(top: gridTopInset, left: sideInset, bottom: bottomInset, right: sideInset), useSideInsets: !isList, scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, adjustForSmallCount: adjustForSmallCount, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none, transition: animateGridItems ? .spring(duration: 0.35) : .immediate)
} }
if case .botPreview = self.scope, self.canManageStories { if case .botPreview = self.scope, self.canManageStories {
@ -4212,6 +4230,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
return items.count < self.maxBotPreviewCount return items.count < self.maxBotPreviewCount
} }
public func canReorder() -> Bool {
guard let items = self.items else {
return false
}
return items.count > 1
}
private func presentAddBotPreviewLanguage() { private func presentAddBotPreviewLanguage() {
self.parentController?.push(LanguageSelectionScreen(context: self.context, selectLocalization: { [weak self] info in self.parentController?.push(LanguageSelectionScreen(context: self.context, selectLocalization: { [weak self] info in
guard let self else { guard let self else {

View File

@ -6616,17 +6616,6 @@ public final class StoryItemSetContainerComponent: Component {
component.reorder() component.reorder()
}))) })))
items.append(.action(ContextMenuActionItem(text: "Edit Preview", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let component = self.component else {
return
}
let _ = component
})))
items.append(.action(ContextMenuActionItem(text: "Delete", textColor: .destructive, icon: { theme in items.append(.action(ContextMenuActionItem(text: "Delete", textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.destructiveColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, a in }, action: { [weak self] _, a in