Bot preview improvements

This commit is contained in:
Isaac 2024-07-26 00:03:54 +08:00
parent df31800dcd
commit b67485c260
7 changed files with 68 additions and 19 deletions

View File

@ -552,7 +552,8 @@ public final class SparseItemGrid: ASDisplayNode {
} }
var contentBottomOffset: CGFloat { var contentBottomOffset: CGFloat {
return -self.scrollView.contentOffset.y + self.scrollView.contentSize.height let bottomInset = self.layout?.containerLayout.insets.bottom ?? 0.0
return -self.scrollView.contentOffset.y + self.scrollView.contentSize.height - bottomInset
} }
let coveringOffsetUpdated: (Viewport, ContainedViewLayoutTransition) -> Void let coveringOffsetUpdated: (Viewport, ContainedViewLayoutTransition) -> Void

View File

@ -1363,6 +1363,15 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
return return
} }
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 == user.id && mainController.source == .generic {
navigationController.maximizeViewController(controller, animated: true)
return
}
}
}
context.sharedContext.openWebApp( context.sharedContext.openWebApp(
context: context, context: context,
parentController: parentController, parentController: parentController,

View File

@ -1629,6 +1629,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
public private(set) var isSelectionModeActive: Bool public private(set) var isSelectionModeActive: Bool
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, navigationHeight: CGFloat, presentationData: PresentationData)? private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, navigationHeight: CGFloat, presentationData: PresentationData)?
private var listBottomInset: CGFloat?
private let ready = Promise<Bool>() private let ready = Promise<Bool>()
private var didSetReady: Bool = false private var didSetReady: Bool = false
@ -2053,10 +2054,17 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
return SparseItemGrid.ShimmerColors(background: 0xffffff, foreground: 0xffffff) return SparseItemGrid.ShimmerColors(background: 0xffffff, foreground: 0xffffff)
} }
let backgroundColor = presentationData.theme.list.mediaPlaceholderColor if case .botPreview = scope {
let foregroundColor = presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.6) let backgroundColor = presentationData.theme.list.plainBackgroundColor
let foregroundColor = presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.6)
return SparseItemGrid.ShimmerColors(background: backgroundColor.argb, foreground: foregroundColor.argb)
return SparseItemGrid.ShimmerColors(background: backgroundColor.argb, foreground: foregroundColor.argb)
} else {
let backgroundColor = presentationData.theme.list.mediaPlaceholderColor
let foregroundColor = presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.6)
return SparseItemGrid.ShimmerColors(background: backgroundColor.argb, foreground: foregroundColor.argb)
}
} }
self.itemGridBinding.updateShimmerLayersImpl = { [weak self] layer in self.itemGridBinding.updateShimmerLayersImpl = { [weak self] layer in
@ -3396,7 +3404,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
} }
if case .botPreview = self.scope, self.canManageStories { if case .botPreview = self.scope, self.canManageStories {
self.updateBotPreviewLanguageTab(size: currentParams.size, topInset: currentParams.topInset, transition: transition) self.updateBotPreviewLanguageTab(size: currentParams.size, topInset: currentParams.topInset, transition: transition)
self.updateBotPreviewFooter(size: currentParams.size, bottomInset: currentParams.bottomInset, transition: transition) self.updateBotPreviewFooter(size: currentParams.size, bottomInset: 0.0, transition: transition)
} }
} }
} }
@ -3664,7 +3672,11 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
guard let self else { guard let self else {
return return
} }
self.emptyAction?() if self.canAddMoreBotPreviews() {
self.emptyAction?()
} else {
self.presentUnableToAddMorePreviewsAlert()
}
}, },
additionalActionTitle: isMainLanguage ? "Create a Translation" : nil, additionalActionTitle: isMainLanguage ? "Create a Translation" : nil,
additionalAction: { [weak self] in additionalAction: { [weak self] in
@ -3680,7 +3692,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
environment: {}, environment: {},
containerSize: CGSize(width: size.width, height: 1000.0) containerSize: CGSize(width: size.width, height: 1000.0)
) )
let botPreviewFooterFrame = CGRect(origin: CGPoint(x: floor((size.width - botPreviewFooterSize.width) * 0.5), y: self.itemGrid.contentBottomOffset - botPreviewFooterSize.height - bottomInset), size: botPreviewFooterSize) let botPreviewFooterFrame = CGRect(origin: CGPoint(x: floor((size.width - botPreviewFooterSize.width) * 0.5), y: self.itemGrid.contentBottomOffset + 16.0), size: botPreviewFooterSize)
if let botPreviewFooterView = botPreviewFooter.view { if let botPreviewFooterView = botPreviewFooter.view {
if botPreviewFooterView.superview == nil { if botPreviewFooterView.superview == nil {
self.view.addSubview(botPreviewFooterView) self.view.addSubview(botPreviewFooterView)
@ -3746,16 +3758,16 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
transition.updateFrame(layer: barBackgroundLayer, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: gridTopInset))) transition.updateFrame(layer: barBackgroundLayer, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: gridTopInset)))
} }
let defaultBottomInset = bottomInset var listBottomInset = bottomInset
var bottomInset = bottomInset var bottomInset = bottomInset
if case .botPreview = self.scope, self.canManageStories { if case .botPreview = self.scope, self.canManageStories {
updateBotPreviewLanguageTab(size: size, topInset: topInset, transition: transition) updateBotPreviewLanguageTab(size: size, topInset: topInset, transition: transition)
gridTopInset += 50.0 gridTopInset += 50.0
updateBotPreviewFooter(size: size, bottomInset: defaultBottomInset, transition: transition) updateBotPreviewFooter(size: size, bottomInset: 0.0, transition: transition)
if let botPreviewFooterView = self.botPreviewFooter?.view { if let botPreviewFooterView = self.botPreviewFooter?.view {
bottomInset += 18.0 + botPreviewFooterView.bounds.height listBottomInset += 18.0 + botPreviewFooterView.bounds.height
} }
} }
@ -3886,6 +3898,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
selectionPanelTransition.setFrame(view: selectionPanelView, frame: selectionPanelFrame) selectionPanelTransition.setFrame(view: selectionPanelView, frame: selectionPanelFrame)
} }
bottomInset = selectionPanelSize.height bottomInset = selectionPanelSize.height
listBottomInset += selectionPanelSize.height
} else if self.isProfileEmbedded, let selectedIds = self.itemInteraction.selectedIds, self.canManageStories, case .botPreview = self.scope { } else if self.isProfileEmbedded, let selectedIds = self.itemInteraction.selectedIds, self.canManageStories, case .botPreview = self.scope {
let selectionPanel: ComponentView<Empty> let selectionPanel: ComponentView<Empty>
var selectionPanelTransition = ComponentTransition(transition) var selectionPanelTransition = ComponentTransition(transition)
@ -3932,6 +3945,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
selectionPanelTransition.setFrame(view: selectionPanelView, frame: selectionPanelFrame) selectionPanelTransition.setFrame(view: selectionPanelView, frame: selectionPanelFrame)
} }
bottomInset = selectionPanelSize.height bottomInset = selectionPanelSize.height
listBottomInset += selectionPanelSize.height
} else if let selectionPanel = self.selectionPanel { } else if let selectionPanel = self.selectionPanel {
self.selectionPanel = nil self.selectionPanel = nil
if let selectionPanelView = selectionPanel.view { if let selectionPanelView = selectionPanel.view {
@ -4039,7 +4053,11 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
guard let self else { guard let self else {
return return
} }
self.emptyAction?() if self.canAddMoreBotPreviews() {
self.emptyAction?()
} else {
self.presentUnableToAddMorePreviewsAlert()
}
}, },
additionalActionTitle: self.canManageStories ? (isMainLanguage ? "Create a Translation" : "Delete this Translation") : nil, additionalActionTitle: self.canManageStories ? (isMainLanguage ? "Create a Translation" : "Delete this Translation") : nil,
additionalAction: { additionalAction: {
@ -4133,11 +4151,12 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
} }
self.itemGrid.pinchEnabled = items.count > 2 && !self.isReordering 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, adjustForSmallCount: adjustForSmallCount, 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: listBottomInset, 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)
} }
self.listBottomInset = listBottomInset
if case .botPreview = self.scope, self.canManageStories { if case .botPreview = self.scope, self.canManageStories {
updateBotPreviewFooter(size: size, bottomInset: defaultBottomInset, transition: transition) updateBotPreviewFooter(size: size, bottomInset: 0.0, transition: transition)
} }
} }
@ -4238,7 +4257,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
} }
private func presentAddBotPreviewLanguage() { private func presentAddBotPreviewLanguage() {
self.parentController?.push(LanguageSelectionScreen(context: self.context, selectLocalization: { [weak self] info in let excludeIds: [String] = self.currentBotPreviewLanguages.map(\.id)
self.parentController?.push(LanguageSelectionScreen(context: self.context, excludeIds: excludeIds, selectLocalization: { [weak self] info in
guard let self else { guard let self else {
return return
} }
@ -4246,6 +4266,14 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
})) }))
} }
public func presentUnableToAddMorePreviewsAlert() {
//TODO:localize
self.parentController?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: nil, text: "You can add at most \(self.maxBotPreviewCount) previews.", actions: [
TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {
})
], parseMarkdown: true), in: .window(.root))
}
public func presentDeleteBotPreviewLanguage() { public func presentDeleteBotPreviewLanguage() {
//TODO:localize //TODO:localize
self.parentController?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: "Delete Translation", text: "Are you sure you want to delete this translation?", actions: [ self.parentController?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: "Delete Translation", text: "Are you sure you want to delete this translation?", actions: [

View File

@ -11,6 +11,7 @@ import SearchUI
public class LanguageSelectionScreen: ViewController { public class LanguageSelectionScreen: ViewController {
private let context: AccountContext private let context: AccountContext
private let excludeIds: [String]
private let selectLocalization: (LocalizationInfo) -> Void private let selectLocalization: (LocalizationInfo) -> Void
private var controllerNode: LanguageSelectionScreenNode { private var controllerNode: LanguageSelectionScreenNode {
@ -29,8 +30,9 @@ public class LanguageSelectionScreen: ViewController {
private var previousContentOffset: ListViewVisibleContentOffset? private var previousContentOffset: ListViewVisibleContentOffset?
public init(context: AccountContext, selectLocalization: @escaping (LocalizationInfo) -> Void) { public init(context: AccountContext, excludeIds: [String] = [], selectLocalization: @escaping (LocalizationInfo) -> Void) {
self.context = context self.context = context
self.excludeIds = excludeIds
self.selectLocalization = selectLocalization self.selectLocalization = selectLocalization
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -92,7 +94,7 @@ public class LanguageSelectionScreen: ViewController {
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = LanguageSelectionScreenNode(context: self.context, presentationData: self.presentationData, navigationBar: self.navigationBar!, requestActivateSearch: { [weak self] in self.displayNode = LanguageSelectionScreenNode(context: self.context, presentationData: self.presentationData, navigationBar: self.navigationBar!, excludeIds: self.excludeIds, requestActivateSearch: { [weak self] in
self?.activateSearch() self?.activateSearch()
}, requestDeactivateSearch: { [weak self] in }, requestDeactivateSearch: { [weak self] in
self?.deactivateSearch() self?.deactivateSearch()

View File

@ -294,6 +294,7 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
private let context: AccountContext private let context: AccountContext
private var presentationData: PresentationData private var presentationData: PresentationData
private weak var navigationBar: NavigationBar? private weak var navigationBar: NavigationBar?
private let excludeIds: [String]
private let requestActivateSearch: () -> Void private let requestActivateSearch: () -> Void
private let requestDeactivateSearch: () -> Void private let requestDeactivateSearch: () -> Void
private let present: (ViewController, Any?) -> Void private let present: (ViewController, Any?) -> Void
@ -316,11 +317,12 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
private var currentListState: LocalizationListState? private var currentListState: LocalizationListState?
init(context: AccountContext, presentationData: PresentationData, navigationBar: NavigationBar, requestActivateSearch: @escaping () -> Void, requestDeactivateSearch: @escaping () -> Void, present: @escaping (ViewController, Any?) -> Void, push: @escaping (ViewController) -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void) { init(context: AccountContext, presentationData: PresentationData, navigationBar: NavigationBar, excludeIds: [String], requestActivateSearch: @escaping () -> Void, requestDeactivateSearch: @escaping () -> Void, present: @escaping (ViewController, Any?) -> Void, push: @escaping (ViewController) -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void) {
self.context = context self.context = context
self.presentationData = presentationData self.presentationData = presentationData
self.presentationDataValue.set(.single(presentationData)) self.presentationDataValue.set(.single(presentationData))
self.navigationBar = navigationBar self.navigationBar = navigationBar
self.excludeIds = excludeIds
self.requestActivateSearch = requestActivateSearch self.requestActivateSearch = requestActivateSearch
self.requestDeactivateSearch = requestDeactivateSearch self.requestDeactivateSearch = requestDeactivateSearch
self.present = present self.present = present
@ -362,6 +364,12 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
var entries: [LanguageListEntry] = [] var entries: [LanguageListEntry] = []
var existingIds = Set<String>() var existingIds = Set<String>()
var localizationListState = localizationListState
localizationListState.availableOfficialLocalizations = localizationListState.availableOfficialLocalizations.filter {
!strongSelf.excludeIds.contains($0.languageCode)
}
localizationListState.availableSavedLocalizations = []
if !localizationListState.availableOfficialLocalizations.isEmpty { if !localizationListState.availableOfficialLocalizations.isEmpty {
strongSelf.currentListState = localizationListState strongSelf.currentListState = localizationListState

View File

@ -976,6 +976,7 @@ open class SpaceWarpView4: UIView, SpaceWarpView {
meshView.frame = CGRect(origin: CGPoint(), size: size) meshView.frame = CGRect(origin: CGPoint(), size: size)
let pixelStep = CGPoint() let pixelStep = CGPoint()
//let pixelStep = CGPoint(x: CGFloat(resolution.x) * 0.33, y: CGFloat(resolution.y) * 0.33)
let itemSize = CGSize(width: size.width / CGFloat(resolution.x), height: size.height / CGFloat(resolution.y)) let itemSize = CGSize(width: size.width / CGFloat(resolution.x), height: size.height / CGFloat(resolution.y))
let params = RippleParams(amplitude: 26.0, frequency: 15.0, decay: 8.0, speed: 1400.0) let params = RippleParams(amplitude: 26.0, frequency: 15.0, decay: 8.0, speed: 1400.0)

View File

@ -6617,7 +6617,7 @@ public final class StoryItemSetContainerComponent: Component {
component.reorder() component.reorder()
}))) })))
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/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, a in }, action: { [weak self] _, a in
a(.default) a(.default)