mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
e3eac999c4
6 changed files with 93 additions and 42 deletions
|
|
@ -1240,6 +1240,11 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
|||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
if !mergedBottom {
|
||||
strongSelf.separatorNode.isHidden = true
|
||||
} else {
|
||||
strongSelf.separatorNode.isHidden = false
|
||||
}
|
||||
case .blocks:
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.addSubnode(strongSelf.maskNode)
|
||||
|
|
|
|||
|
|
@ -462,7 +462,7 @@ func _internal_composeAIMessageStyles(account: Account) -> Signal<[TelegramCompo
|
|||
}
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
#if DEBUG && false
|
||||
for item in Array(result) {
|
||||
result.append(TelegramComposeAIMessageMode.Style(name: item.name + "_", emoji: item.emoji))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1698,6 +1698,14 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
guard let strongSelf = self, let itemView = item.view as? ItemView else {
|
||||
return
|
||||
}
|
||||
var isList = false
|
||||
switch strongSelf.contentType {
|
||||
case .files, .music, .voiceAndVideoMessages:
|
||||
isList = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
let listSideInset = isList ? (sideInset + 16.0) : sideInset
|
||||
if let item = itemView.item {
|
||||
itemView.bind(
|
||||
item: item,
|
||||
|
|
@ -1707,7 +1715,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
interaction: strongSelf.itemGridBinding.listItemInteraction,
|
||||
isSelected: strongSelf.chatControllerInteraction.selectionState?.selectedIds.contains(item.message.id),
|
||||
size: CGSize(width: size.width, height: itemView.bounds.height),
|
||||
insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset)
|
||||
insets: UIEdgeInsets(top: topInset, left: listSideInset, bottom: bottomInset, right: listSideInset)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2137,6 +2145,14 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
guard let itemView = item.view as? ItemView, let (size, topInset, sideInset, bottomInset, _, _, _, _, _, _) = self.currentParams else {
|
||||
return
|
||||
}
|
||||
var isList = false
|
||||
switch self.contentType {
|
||||
case .files, .music, .voiceAndVideoMessages:
|
||||
isList = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
let listSideInset = isList ? (sideInset + 16.0) : sideInset
|
||||
if let item = itemView.item {
|
||||
itemView.bind(
|
||||
item: item,
|
||||
|
|
@ -2146,7 +2162,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
interaction: self.itemGridBinding.listItemInteraction,
|
||||
isSelected: self.chatControllerInteraction.selectionState?.selectedIds.contains(item.message.id),
|
||||
size: CGSize(width: size.width, height: itemView.bounds.height),
|
||||
insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset)
|
||||
insets: UIEdgeInsets(top: topInset, left: listSideInset, bottom: bottomInset, right: listSideInset)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,31 +137,13 @@ final class TextProcessingStyleSelectionComponent: Component {
|
|||
styleData.append((item.id, item.emoji, localizedStyleName(strings: component.strings, styleId: item.id)))
|
||||
}
|
||||
|
||||
let maxItemWidth: CGFloat = 80.0
|
||||
let itemPadding: CGFloat = 0.0
|
||||
let minSlotWidth: CGFloat = 50.0
|
||||
let slotWidth: CGFloat
|
||||
if CGFloat(styleData.count) * minSlotWidth <= availableSize.width {
|
||||
slotWidth = floor(availableSize.width / CGFloat(styleData.count))
|
||||
} else {
|
||||
var resolved: CGFloat = minSlotWidth
|
||||
var targetVisible: CGFloat = min(7.5, floor((availableSize.width + 16.0) / 60.0) + 0.5)
|
||||
while targetVisible >= 1.5 {
|
||||
let candidateWidth = floor((availableSize.width + 16.0) / targetVisible)
|
||||
if candidateWidth >= minSlotWidth {
|
||||
resolved = candidateWidth
|
||||
break
|
||||
}
|
||||
targetVisible -= 1.0
|
||||
}
|
||||
slotWidth = resolved
|
||||
}
|
||||
let contentWidth = slotWidth * CGFloat(styleData.count)
|
||||
let itemSize = CGSize(width: slotWidth, height: availableSize.height)
|
||||
let maxSlotWidth: CGFloat = 80.0
|
||||
|
||||
self.scrollView.frame = CGRect(origin: CGPoint(), size: availableSize)
|
||||
self.scrollView.contentSize = CGSize(width: contentWidth, height: availableSize.height)
|
||||
self.scrollView.alwaysBounceHorizontal = contentWidth > availableSize.width
|
||||
|
||||
var selectedItemFrame: CGRect?
|
||||
// First pass: measure all items to find intrinsic sizes
|
||||
var itemSizes: [TelegramComposeAIMessageMode.StyleId: CGSize] = [:]
|
||||
for i in 0 ..< styleData.count {
|
||||
let style = styleData[i]
|
||||
let itemView: ComponentView<Empty>
|
||||
|
|
@ -173,8 +155,7 @@ final class TextProcessingStyleSelectionComponent: Component {
|
|||
itemView = ComponentView()
|
||||
self.itemViews[style.id] = itemView
|
||||
}
|
||||
let itemFrame = CGRect(origin: CGPoint(x: CGFloat(i) * slotWidth, y: 0.0), size: itemSize)
|
||||
let _ = itemView.update(
|
||||
let measuredSize = itemView.update(
|
||||
transition: itemTransition,
|
||||
component: AnyComponent(ItemComponent(
|
||||
theme: component.theme,
|
||||
|
|
@ -182,16 +163,58 @@ final class TextProcessingStyleSelectionComponent: Component {
|
|||
title: style.title
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: itemSize
|
||||
containerSize: CGSize(width: maxItemWidth, height: availableSize.height)
|
||||
)
|
||||
itemSizes[style.id] = measuredSize
|
||||
}
|
||||
|
||||
// Compute uniform slot width from largest item
|
||||
var largestItemWidth: CGFloat = 0.0
|
||||
for (_, size) in itemSizes {
|
||||
largestItemWidth = max(largestItemWidth, size.width)
|
||||
}
|
||||
let contentBasedWidth = min(maxSlotWidth, max(minSlotWidth, largestItemWidth + itemPadding))
|
||||
let slotWidth: CGFloat
|
||||
if CGFloat(styleData.count) * contentBasedWidth <= availableSize.width {
|
||||
slotWidth = floor(availableSize.width / CGFloat(styleData.count))
|
||||
} else {
|
||||
var resolved: CGFloat = contentBasedWidth
|
||||
var targetVisible: CGFloat = min(7.5, floor((availableSize.width + 16.0) / (contentBasedWidth + 10.0)) + 0.5)
|
||||
while targetVisible >= 1.5 {
|
||||
let candidateWidth = floor((availableSize.width + 16.0) / targetVisible)
|
||||
if candidateWidth >= contentBasedWidth {
|
||||
resolved = candidateWidth
|
||||
break
|
||||
}
|
||||
targetVisible -= 1.0
|
||||
}
|
||||
slotWidth = resolved
|
||||
}
|
||||
let contentWidth = slotWidth * CGFloat(styleData.count)
|
||||
|
||||
self.scrollView.frame = CGRect(origin: CGPoint(), size: availableSize)
|
||||
self.scrollView.contentSize = CGSize(width: contentWidth, height: availableSize.height)
|
||||
self.scrollView.alwaysBounceHorizontal = contentWidth > availableSize.width
|
||||
|
||||
// Second pass: position items centered in their slots
|
||||
var selectedItemFrame: CGRect?
|
||||
for i in 0 ..< styleData.count {
|
||||
let style = styleData[i]
|
||||
guard let itemView = self.itemViews[style.id],
|
||||
let naturalSize = itemSizes[style.id] else {
|
||||
continue
|
||||
}
|
||||
let slotOriginX = CGFloat(i) * slotWidth
|
||||
let itemX = slotOriginX + floor((slotWidth - naturalSize.width) * 0.5)
|
||||
let itemFrame = CGRect(origin: CGPoint(x: itemX, y: 0.0), size: naturalSize)
|
||||
if let itemComponentView = itemView.view {
|
||||
if itemComponentView.superview == nil {
|
||||
self.scrollView.addSubview(itemComponentView)
|
||||
}
|
||||
itemTransition.setFrame(view: itemComponentView, frame: itemFrame)
|
||||
transition.setFrame(view: itemComponentView, frame: itemFrame)
|
||||
}
|
||||
if style.id == component.selectedStyle {
|
||||
selectedItemFrame = CGRect(origin: CGPoint(x: itemFrame.minX, y: itemFrame.minY - 5.0), size: CGSize(width: itemFrame.width, height: itemFrame.height + 5.0 + 3.0))
|
||||
selectedItemFrame = CGRect(origin: CGPoint(x: slotOriginX, y: -5.0), size: CGSize(width: slotWidth, height: availableSize.height + 5.0 + 3.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,14 +333,6 @@ private final class ItemComponent: Component {
|
|||
environment: {},
|
||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||
)
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: -1.0), size: iconSize)
|
||||
if let imageIconView = imageIcon.view {
|
||||
if imageIconView.superview == nil {
|
||||
self.addSubview(imageIconView)
|
||||
}
|
||||
iconTransition.setFrame(view: imageIconView, frame: iconFrame)
|
||||
}
|
||||
|
||||
let titleSize = self.title.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
|
|
@ -326,7 +341,18 @@ private final class ItemComponent: Component {
|
|||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||
)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: availableSize.height - 5.0 - titleSize.height), size: titleSize)
|
||||
|
||||
let contentWidth = max(iconSize.width, titleSize.width)
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((contentWidth - iconSize.width) * 0.5), y: -1.0), size: iconSize)
|
||||
if let imageIconView = imageIcon.view {
|
||||
if imageIconView.superview == nil {
|
||||
self.addSubview(imageIconView)
|
||||
}
|
||||
iconTransition.setFrame(view: imageIconView, frame: iconFrame)
|
||||
}
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((contentWidth - titleSize.width) * 0.5), y: availableSize.height - 5.0 - titleSize.height), size: titleSize)
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
self.addSubview(titleView)
|
||||
|
|
@ -334,7 +360,7 @@ private final class ItemComponent: Component {
|
|||
titleView.frame = titleFrame
|
||||
}
|
||||
|
||||
return availableSize
|
||||
return CGSize(width: contentWidth, height: availableSize.height)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ final class TextProcessingTranslateContentComponent: Component {
|
|||
|
||||
fileprivate(set) var nonPremiumFloodTriggered: Bool = false {
|
||||
didSet {
|
||||
if self.isProcessing != oldValue {
|
||||
if self.nonPremiumFloodTriggered != oldValue {
|
||||
self.nonPremiumFloodTriggeredUpdated?(self.nonPremiumFloodTriggered)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2354,6 +2354,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
navigationController.pushViewController(createBotScreen)
|
||||
}
|
||||
}
|
||||
case let .channel(channel):
|
||||
if channel.isCreator {
|
||||
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue