Group boosts

This commit is contained in:
Ilya Laktyushin 2024-02-05 16:18:02 +04:00
parent 1b2b7dc403
commit b4b90b090c
65 changed files with 3569 additions and 1969 deletions

View file

@ -10987,6 +10987,7 @@ Sorry for the inconvenience.";
"ContactList.Context.Delete" = "Delete Contact";
"ContactList.Context.Select" = "Select";
"ContactList.DeleteConfirmationSingle" = "Delete Contact";
"ContactList.DeleteConfirmation_1" = "Delete %@ Contact";
"ContactList.DeleteConfirmation_any" = "Delete %@ Contacts";
@ -11082,3 +11083,12 @@ Sorry for the inconvenience.";
"GroupInfo.Permissions.DontRestrictBoosters" = "Do Not Restrict Boosters";
"GroupInfo.Permissions.DontRestrictBoostersInfo" = "Choose how many boosts a user must give to the group to bypass restrictions on sending messages.";
"GroupInfo.Permissions.DontRestrictBoostersEnableInfo" = "Turn this on to always allow users who boosted your group to send messages and media.";
"Notification.Boost.Times_1" = "%@ time";
"Notification.Boost.Times_any" = "%@ times";
"Notification.Boost.Single" = "%1$@ boosted the group";
"Notification.Boost.Multiple" = "%1$@ boosted the group %2$@";
"Notification.Boost.SingleYou" = "You boosted the group";
"Notification.Boost.MultipleYou" = "You boosted the group %1$@";

View file

@ -739,7 +739,6 @@ public enum InstalledStickerPacksControllerMode {
case modal
case masks
case emoji
case groupEmoji(selectedPack: StickerPackCollectionInfo?, completion: (StickerPackCollectionInfo?) -> Void)
}
public let defaultContactLabel: String = "_$!<Mobile>!$_"

View file

@ -981,6 +981,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
}, hideTranslationPanel: {
}, openPremiumGift: {
}, openPremiumRequiredForMessaging: {
}, openBoostToUnrestrict: {
}, updateHistoryFilter: { _ in
}, requestLayout: { _ in
}, chatController: {

View file

@ -144,7 +144,7 @@ private final class CameraContext {
transform = CGAffineTransformTranslate(transform, 0.0, -size.height)
ciImage = ciImage.transformed(by: transform)
}
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: Camera.isDualCameraSupported ? 100.0 : 40.0).cropped(to: CGRect(origin: .zero, size: size))
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: Camera.isDualCameraSupported(forRoundVideo: true) ? 100.0 : 40.0).cropped(to: CGRect(origin: .zero, size: size))
if let cgImage = self.ciContext.createCGImage(ciImage, from: ciImage.extent) {
let uiImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: .right)
if front {
@ -1056,15 +1056,18 @@ public final class Camera {
}
}
public static var isDualCameraSupported: Bool {
public static func isDualCameraSupported(forRoundVideo: Bool = false) -> Bool {
if #available(iOS 13.0, *), AVCaptureMultiCamSession.isMultiCamSupported && !DeviceModel.current.isIpad {
if forRoundVideo && DeviceModel.current == .iPhoneXR {
return false
}
return true
} else {
return false
}
}
}
e
public final class CameraHolder {
public let camera: Camera
public let previewView: CameraPreviewView

View file

@ -173,6 +173,7 @@ public final class ChatPanelInterfaceInteraction {
public let openPremiumGift: () -> Void
public let openPremiumRequiredForMessaging: () -> Void
public let updateHistoryFilter: ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void
public let openBoostToUnrestrict: () -> Void
public let requestLayout: (ContainedViewLayoutTransition) -> Void
public let chatController: () -> ViewController?
public let statuses: ChatPanelInterfaceInteractionStatuses?
@ -281,6 +282,7 @@ public final class ChatPanelInterfaceInteraction {
hideTranslationPanel: @escaping () -> Void,
openPremiumGift: @escaping () -> Void,
openPremiumRequiredForMessaging: @escaping () -> Void,
openBoostToUnrestrict: @escaping () -> Void,
updateHistoryFilter: @escaping ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void,
requestLayout: @escaping (ContainedViewLayoutTransition) -> Void,
chatController: @escaping () -> ViewController?,
@ -389,6 +391,7 @@ public final class ChatPanelInterfaceInteraction {
self.hideTranslationPanel = hideTranslationPanel
self.openPremiumGift = openPremiumGift
self.openPremiumRequiredForMessaging = openPremiumRequiredForMessaging
self.openBoostToUnrestrict = openBoostToUnrestrict
self.updateHistoryFilter = updateHistoryFilter
self.requestLayout = requestLayout
@ -505,6 +508,7 @@ public final class ChatPanelInterfaceInteraction {
}, hideTranslationPanel: {
}, openPremiumGift: {
}, openPremiumRequiredForMessaging: {
}, openBoostToUnrestrict: {
}, updateHistoryFilter: { _ in
}, requestLayout: { _ in
}, chatController: {

View file

@ -183,9 +183,6 @@ public final class MultilineTextWithEntitiesComponent: Component {
}
}
let size = self.textNode.updateLayout(availableSize)
self.textNode.frame = CGRect(origin: .zero, size: size)
self.textNode.visibility = true
if let context = component.context, let animationCache = component.animationCache, let animationRenderer = component.animationRenderer, let placeholderColor = component.placeholderColor {
self.textNode.arguments = TextNodeWithEntities.Arguments(
@ -197,6 +194,9 @@ public final class MultilineTextWithEntitiesComponent: Component {
)
}
let size = self.textNode.updateLayout(availableSize)
self.textNode.frame = CGRect(origin: .zero, size: size)
return size
}
}

View file

@ -589,7 +589,15 @@ public class ContactsController: ViewController {
public func requestDeleteContacts(peerIds: [EnginePeer.Id]) {
let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ContactList_DeleteConfirmation(Int32(peerIds.count)), color: .destructive, action: { [weak self, weak actionSheet] in
let actionTitle: String
if peerIds.count > 1 {
actionTitle = self.presentationData.strings.ContactList_DeleteConfirmation(Int32(peerIds.count))
} else {
actionTitle = self.presentationData.strings.ContactList_DeleteConfirmationSingle
}
items.append(ActionSheetButtonItem(title: actionTitle, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let self else {

View file

@ -1115,6 +1115,7 @@ public class StickerPickerScreen: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1169,6 +1170,7 @@ public class StickerPickerScreen: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1199,6 +1201,7 @@ public class StickerPickerScreen: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1440,6 +1443,7 @@ public class StickerPickerScreen: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1470,6 +1474,7 @@ public class StickerPickerScreen: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -48,6 +48,7 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
let editing: ItemListStickerPackItemEditing
let enabled: Bool
let playAnimatedStickers: Bool
let style: ItemListStyle
public let sectionId: ItemListSectionId
let action: (() -> Void)?
let setPackIdWithRevealedOptions: (ItemCollectionId?, ItemCollectionId?) -> Void
@ -55,7 +56,7 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
let removePack: () -> Void
let toggleSelected: () -> Void
public init(presentationData: ItemListPresentationData, context: AccountContext, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void, toggleSelected: @escaping () -> Void) {
public init(presentationData: ItemListPresentationData, context: AccountContext, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, style: ItemListStyle = .blocks, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void, toggleSelected: @escaping () -> Void) {
self.presentationData = presentationData
self.context = context
self.packInfo = packInfo
@ -66,6 +67,7 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
self.editing = editing
self.enabled = enabled
self.playAnimatedStickers = playAnimatedStickers
self.style = style
self.sectionId = sectionId
self.action = action
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
@ -410,8 +412,20 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
let verticalInset: CGFloat = 11.0
let titleSpacing: CGFloat = 2.0
let insets = itemListNeighborsGroupedInsets(neighbors, params)
let separatorHeight = UIScreenPixel
let insets: UIEdgeInsets
let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor
switch item.style {
case .plain:
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
insets = itemListNeighborsPlainInsets(neighbors)
case .blocks:
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
insets = itemListNeighborsGroupedInsets(neighbors, params)
}
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool, ContainedViewLayoutTransition) -> ItemListEditableReorderControlNode)?
@ -543,9 +557,9 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
}
if let _ = updatedTheme {
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
}

View file

@ -652,7 +652,7 @@ private func channelPermissionsControllerEntries(context: AccountContext, presen
let slowModeTimeout = state.modifiedSlowmodeTimeout ?? (cachedData.slowModeTimeout ?? 0)
if !canSendText || !canSendMedia || slowModeTimeout > 0 {
let unrestrictBoosters = state.modifiedUnrestrictBoosters ?? (cachedData.boostsUnrestrict ?? 0)
let unrestrictBoosters = state.modifiedUnrestrictBoosters ?? (cachedData.boostsToUnrestrict ?? 0)
let unrestrictEnabled = unrestrictBoosters > 0
entries.append(.unrestrictBoostersSwitch(presentationData.theme, presentationData.strings.GroupInfo_Permissions_DontRestrictBoosters, unrestrictEnabled))
@ -780,6 +780,9 @@ public func channelPermissionsController(context: AccountContext, updatedPresent
let updateDefaultRightsDisposable = MetaDisposable()
actionsDisposable.add(updateDefaultRightsDisposable)
let updateUnrestrictBoostersDisposable = MetaDisposable()
actionsDisposable.add(updateUnrestrictBoostersDisposable)
let peerView = Promise<PeerView>()
peerView.set(sourcePeerId.get()
|> mapToSignal(context.account.viewTracker.peerView))
@ -1144,6 +1147,12 @@ public func channelPermissionsController(context: AccountContext, updatedPresent
return state
}
let _ = (peerView.get()
|> take(1)
|> deliverOnMainQueue).start(next: { view in
updateUnrestrictBoostersDisposable.set((context.engine.peers.updateChannelBoostsToUnlockRestrictions(peerId: view.peerId, boosts: value)
|> deliverOnMainQueue).start())
})
}, toggleIsOptionExpanded: { flags in
updateState { state in
var state = state

View file

@ -231,21 +231,7 @@ private final class PageIndicatorView: UIView {
private func updateDotPosition(currentPage: Int, animated: Bool) {
let duration = animated ? self.animationDuration : 0
if !animated {
if currentPage == 0 {
let x = -self.scrollView.contentInset.left
self.moveScrollView(x: x)
} else {
for _ in 0 ..< currentPage {
let x = self.scrollView.contentOffset.x + self.itemSize
self.moveScrollView(x: x, duration: duration)
}
if currentPage == self.pageCount - 1 {
let x = self.scrollView.contentSize.width - self.scrollView.bounds.width + self.scrollView.contentInset.right
self.moveScrollView(x: x, duration: duration)
}
}
} else {
let action: (Int, Double) -> Void = { currentPage, duration in
if currentPage == 0 {
let x = -self.scrollView.contentInset.left
self.moveScrollView(x: x, duration: duration)
@ -260,6 +246,18 @@ private final class PageIndicatorView: UIView {
self.moveScrollView(x: x, duration: duration)
}
}
if !animated {
if currentPage == 0 {
action(currentPage, 0)
} else {
for i in 0 ..< currentPage {
action(i, 0)
}
}
} else {
action(currentPage, duration)
}
}
private func updateDotSize(currentPage: Int, animated: Bool) {

View file

@ -466,6 +466,8 @@ private final class SheetContent: CombinedComponent {
final class State: ComponentState {
var cachedChevronImage: (UIImage, PresentationTheme)?
var cachedIconImage: UIImage?
private(set) var peer: EnginePeer?
private(set) var memberPeer: EnginePeer?
@ -511,6 +513,10 @@ private final class SheetContent: CombinedComponent {
}
static var body: Body {
let iconBackground = Child(Image.self)
let icon = Child(BundleIconComponent.self)
//let icon = Child(LottieComponent.self)
let peerShortcut = Child(Button.self)
let text = Child(BalancedTextComponent.self)
let alternateText = Child(List<Empty>.self)
@ -658,7 +664,7 @@ private final class SheetContent: CombinedComponent {
}
isCurrent = true
case let .unrestrict(unrestrictCount):
textString = "Boost the group \(unrestrictCount) times to remove messaging restrictions. Your boosts will help \(peerName) to unlock new features."
textString = "Boost the group **\(unrestrictCount)** times to remove messaging restrictions. Your boosts will help **\(peerName)** to unlock new features."
isCurrent = true
default:
if let remaining {
@ -674,7 +680,7 @@ private final class SheetContent: CombinedComponent {
isCurrent = mode == .current
}
case .features:
textString = ""
textString = "By gaining **boosts**, your group reaches higher levels and unlocks more features."
}
let defaultTitle = strings.ChannelBoost_Level("\(level)").string
@ -733,7 +739,48 @@ private final class SheetContent: CombinedComponent {
}
if case .features = component.mode {
contentSize.height += 17.0
contentSize.height -= 14.0
let iconSize = CGSize(width: 90.0, height: 90.0)
let gradientImage: UIImage
if let current = state.cachedIconImage {
gradientImage = current
} else {
gradientImage = generateFilledCircleImage(diameter: iconSize.width, color: theme.actionSheet.controlAccentColor)!
context.state.cachedIconImage = gradientImage
}
let iconBackground = iconBackground.update(
component: Image(image: gradientImage),
availableSize: iconSize,
transition: .immediate
)
context.add(iconBackground
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + iconBackground.size.height / 2.0))
)
let icon = icon.update(
component: BundleIconComponent(
name: "Premium/BoostLarge",
tintColor: .white
),
availableSize: CGSize(width: 90.0, height: 90.0),
transition: .immediate
)
// let icon = icon.update(
// component: LottieComponent(
// content: LottieComponent.AppBundleContent(name: iconName),
// playOnce: state.playOnce
// ),
// availableSize: CGSize(width: 70, height: 70),
// transition: .immediate
// )
context.add(icon
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + iconBackground.size.height / 2.0))
)
contentSize.height += iconSize.height
contentSize.height += 52.0
} else {
let limit = limit.update(
component: PremiumLimitDisplayComponent(
@ -760,83 +807,83 @@ private final class SheetContent: CombinedComponent {
)
contentSize.height += limit.size.height + 23.0
}
if myBoostCount > 0 {
let alternateTitle = isCurrent ? strings.ChannelBoost_YouBoostedChannelText(peerName).string : strings.ChannelBoost_YouBoostedOtherChannelText
if myBoostCount > 0 {
let alternateTitle = isCurrent ? strings.ChannelBoost_YouBoostedChannelText(peerName).string : strings.ChannelBoost_YouBoostedOtherChannelText
var alternateBadge: String?
if myBoostCount > 1 {
alternateBadge = "X\(myBoostCount)"
}
let alternateText = alternateText.update(
component: List(
[
AnyComponentWithIdentity(
id: "title",
component: AnyComponent(
BoostedTitleContent(text: NSAttributedString(string: alternateTitle, font: Font.semibold(15.0), textColor: textColor), badge: alternateBadge)
)
),
AnyComponentWithIdentity(
id: "text",
component: AnyComponent(
BalancedTextComponent(
text: .markdown(text: textString, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.1
)
var alternateBadge: String?
if myBoostCount > 1 {
alternateBadge = "X\(myBoostCount)"
}
let alternateText = alternateText.update(
component: List(
[
AnyComponentWithIdentity(
id: "title",
component: AnyComponent(
BoostedTitleContent(text: NSAttributedString(string: alternateTitle, font: Font.semibold(15.0), textColor: textColor), badge: alternateBadge)
)
),
AnyComponentWithIdentity(
id: "text",
component: AnyComponent(
BalancedTextComponent(
text: .markdown(text: textString, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.1
)
)
],
centerAlignment: true
),
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
transition: .immediate
)
context.add(alternateText
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + alternateText.size.height / 2.0))
.appear(Transition.Appear({ _, view, transition in
transition.animatePosition(view: view, from: CGPoint(x: 0.0, y: 64.0), to: .zero, additive: true)
transition.animateAlpha(view: view, from: 0.0, to: 1.0)
)
],
centerAlignment: true
),
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
transition: .immediate
)
context.add(alternateText
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + alternateText.size.height / 2.0))
.appear(Transition.Appear({ _, view, transition in
transition.animatePosition(view: view, from: CGPoint(x: 0.0, y: 64.0), to: .zero, additive: true)
transition.animateAlpha(view: view, from: 0.0, to: 1.0)
}))
.disappear(Transition.Disappear({ view, transition, completion in
view.superview?.sendSubviewToBack(view)
transition.animatePosition(view: view, from: .zero, to: CGPoint(x: 0.0, y: -64.0), additive: true)
transition.setAlpha(view: view, alpha: 0.0, completion: { _ in
completion()
})
}))
.disappear(Transition.Disappear({ view, transition, completion in
view.superview?.sendSubviewToBack(view)
transition.animatePosition(view: view, from: .zero, to: CGPoint(x: 0.0, y: -64.0), additive: true)
transition.setAlpha(view: view, alpha: 0.0, completion: { _ in
completion()
})
}))
)
contentSize.height += alternateText.size.height + 13.0
} else {
let text = text.update(
component: BalancedTextComponent(
text: .markdown(text: textString, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.2
),
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
transition: .immediate
)
context.add(text
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + text.size.height / 2.0))
.appear(Transition.Appear({ _, view, transition in
transition.animatePosition(view: view, from: CGPoint(x: 0.0, y: 64.0), to: .zero, additive: true)
transition.animateAlpha(view: view, from: 0.0, to: 1.0)
)
contentSize.height += alternateText.size.height + 20.0
} else {
let text = text.update(
component: BalancedTextComponent(
text: .markdown(text: textString, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.2
),
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
transition: .immediate
)
context.add(text
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + text.size.height / 2.0))
.appear(Transition.Appear({ _, view, transition in
transition.animatePosition(view: view, from: CGPoint(x: 0.0, y: 64.0), to: .zero, additive: true)
transition.animateAlpha(view: view, from: 0.0, to: 1.0)
}))
.disappear(Transition.Disappear({ view, transition, completion in
view.superview?.sendSubviewToBack(view)
transition.animatePosition(view: view, from: .zero, to: CGPoint(x: 0.0, y: -64.0), additive: true)
transition.setAlpha(view: view, alpha: 0.0, completion: { _ in
completion()
})
}))
.disappear(Transition.Disappear({ view, transition, completion in
view.superview?.sendSubviewToBack(view)
transition.animatePosition(view: view, from: .zero, to: CGPoint(x: 0.0, y: -64.0), additive: true)
transition.setAlpha(view: view, alpha: 0.0, completion: { _ in
completion()
})
}))
)
contentSize.height += text.size.height + 13.0
}
)
contentSize.height += text.size.height + 20.0
}
if case .owner = component.mode, let status = component.status {
@ -886,7 +933,6 @@ private final class SheetContent: CombinedComponent {
iconPosition: .left,
action: {
component.boost()
component.dismiss()
}
),
availableSize: CGSize(width: (context.availableSize.width - 8.0 - sideInset * 2.0) / 2.0, height: 50.0),
@ -1296,6 +1342,8 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
)
let titleString: String
var titleFont = Font.semibold(17.0)
switch component.mode {
case let .owner(subject):
if let status = component.status, let _ = status.nextLevelBoosts {
@ -1352,12 +1400,13 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
}
case .features:
//TODO:localize
titleString = "Features"
titleString = "Additional Features"
titleFont = Font.semibold(20.0)
}
let title = title.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: titleString, font: Font.semibold(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)),
text: .plain(NSAttributedString(string: titleString, font: titleFont, textColor: theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center,
truncationType: .end,
maximumNumberOfLines: 1
@ -1366,7 +1415,29 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
transition: context.transition
)
let topPanelAlpha: CGFloat = min(30.0, state.topContentOffset) / 30.0
let topPanelAlpha: CGFloat
let titleOriginY: CGFloat
let titleScale: CGFloat
if case .features = component.mode {
if state.topContentOffset > 78.0 {
topPanelAlpha = min(30.0, state.topContentOffset - 78.0) / 30.0
} else {
topPanelAlpha = 0.0
}
let titleTopOriginY = topPanel.size.height / 2.0
let titleBottomOriginY: CGFloat = 146.0
let titleOriginDelta = titleTopOriginY - titleBottomOriginY
let fraction = min(1.0, state.topContentOffset / abs(titleOriginDelta))
titleOriginY = titleBottomOriginY + fraction * titleOriginDelta
titleScale = 1.0 - max(0.0, fraction * 0.2)
} else {
topPanelAlpha = min(30.0, state.topContentOffset) / 30.0
titleOriginY = topPanel.size.height / 2.0
titleScale = 1.0
}
context.add(topPanel
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0))
.opacity(topPanelAlpha)
@ -1376,7 +1447,8 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
.opacity(topPanelAlpha)
)
context.add(title
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0))
.position(CGPoint(x: context.availableSize.width / 2.0, y: titleOriginY))
.scale(titleScale)
)
if let openStats = component.openStats {
@ -1615,6 +1687,9 @@ public class PremiumBoostLevelsScreen: ViewController {
private var dismissOffset: CGFloat?
func containerLayoutUpdated(layout: ContainerViewLayout, transition: Transition) {
guard !self.isDismissing else {
return
}
self.currentLayout = layout
self.dim.frame = CGRect(origin: CGPoint(x: 0.0, y: -layout.size.height), size: CGSize(width: layout.size.width, height: layout.size.height * 3.0))
@ -1725,15 +1800,17 @@ public class PremiumBoostLevelsScreen: ViewController {
controller.dismiss(animated: true)
let boostController = PremiumBoostLevelsScreen(
context: controller.context,
peerId: controller.peerId,
mode: .user(mode: .current),
status: controller.status,
myBoostStatus: nil,
forceDark: controller.forceDark
)
navigationController.pushViewController(boostController, animated: true)
Queue.mainQueue().justDispatch {
let boostController = PremiumBoostLevelsScreen(
context: controller.context,
peerId: controller.peerId,
mode: .user(mode: .current),
status: controller.status,
myBoostStatus: nil,
forceDark: controller.forceDark
)
navigationController.pushViewController(boostController, animated: true)
}
},
copyLink: { [weak self, weak controller] link in
guard let self else {

View file

@ -317,12 +317,6 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
if !component.isCompleted {
if let products = component.products {
let gradientColors: [UIColor] = [
UIColor(rgb: 0x8e77ff),
UIColor(rgb: 0x9a6fff),
UIColor(rgb: 0xb36eee)
]
let shortestOptionPrice: (Int64, NSDecimalNumber)
if let product = products.last {
shortestOptionPrice = (Int64(Float(product.storeProduct.priceCurrencyAndAmount.amount) / Float(product.months)), product.storeProduct.priceValue.dividing(by: NSDecimalNumber(value: product.months)))
@ -352,14 +346,20 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
var accessibilitySubtitle = ""
var pricePerMonth = environment.strings.Premium_PricePerMonth(product.storeProduct.pricePerMonth(Int(product.months))).string
var labelPrice = pricePerMonth
if component.peers.count > 1 {
subtitle = "\(product.storeProduct.price) x \(component.peers.count)"
pricePerMonth = product.storeProduct.multipliedPrice(count: component.peers.count)
subtitle = ""
labelPrice = "\(product.storeProduct.price) x \(component.peers.count)"
} else {
if discountValue > 0 {
subtitle = "**\(defaultPrice)** \(product.price)"
accessibilitySubtitle = product.price
}
subtitle = ""
labelPrice = product.price
}
items.append(SectionGroupComponent.Item(
@ -369,13 +369,13 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
PremiumOptionComponent(
title: giftTitle,
subtitle: subtitle,
labelPrice: pricePerMonth,
labelPrice: labelPrice,
discount: discount,
multiple: component.peers.count > 1,
selected: product.id == component.selectedProductId,
primaryTextColor: textColor,
secondaryTextColor: subtitleColor,
accentColor: gradientColors[i],
accentColor: environment.theme.list.itemAccentColor,
checkForegroundColor: environment.theme.list.itemCheckColors.foregroundColor,
checkBorderColor: environment.theme.list.itemCheckColors.strokeColor
)

View file

@ -643,9 +643,9 @@ public enum PremiumPerk: CaseIterable {
case .messageTags:
return "Premium/Perk/MessageTags"
case .lastSeen:
return "Premium/Perk/Wallpapers"
return "Premium/Perk/LastSeen"
case .messagePrivacy:
return "Premium/Perk/MessageTags"
return "Premium/Perk/MessagePrivacy"
}
}
}
@ -864,7 +864,6 @@ final class PremiumOptionComponent: CombinedComponent {
transition: context.transition
)
var discountOffset: CGFloat = 0.0
let discountSize: CGSize
if !component.discount.isEmpty {
let discount = discount.update(
@ -872,7 +871,7 @@ final class PremiumOptionComponent: CombinedComponent {
text: .plain(
NSAttributedString(
string: component.discount,
font: Font.with(size: component.multiple ? 13.0 : 14.0, design: .round, weight: .semibold, traits: []),
font: Font.with(size: 14.0, design: .round, weight: .semibold, traits: []),
textColor: .white
)
),
@ -893,13 +892,7 @@ final class PremiumOptionComponent: CombinedComponent {
transition: context.transition
)
let discountPosition: CGPoint
if component.multiple {
discountOffset = discountSize.width + 6.0
discountPosition = CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + discountSize.height / 2.0)
} else {
discountPosition = CGPoint(x: insets.left + title.size.width + 6.0 + discountSize.width / 2.0, y: insets.top + title.size.height / 2.0)
}
let discountPosition = CGPoint(x: insets.left + title.size.width + 6.0 + discountSize.width / 2.0, y: insets.top + title.size.height / 2.0)
context.add(discountBackground
.position(discountPosition)
@ -938,7 +931,7 @@ final class PremiumOptionComponent: CombinedComponent {
transition: context.transition
)
context.add(subtitle
.position(CGPoint(x: insets.left + subtitle.size.width / 2.0 + discountOffset, y: insets.top + title.size.height + spacing + subtitle.size.height / 2.0))
.position(CGPoint(x: insets.left + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + subtitle.size.height / 2.0))
)
subtitleSize = subtitle.size
@ -1894,11 +1887,6 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let layoutOptions = {
if let products = state.products, products.count > 1, state.isPremium == false || (!context.component.justBought && state.canUpgrade) {
var optionsItems: [SectionGroupComponent.Item] = []
let gradientColors: [UIColor] = [
UIColor(rgb: 0x8e77ff),
UIColor(rgb: 0x9a6fff),
UIColor(rgb: 0xb36eee)
]
let shortestOptionPrice: (Int64, NSDecimalNumber)
if let product = products.first(where: { $0.id.hasSuffix(".monthly") }) {
@ -1967,7 +1955,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
selected: !product.isCurrent && product.id == state.selectedProductId,
primaryTextColor: textColor,
secondaryTextColor: subtitleColor,
accentColor: gradientColors[i],
accentColor: environment.theme.list.itemAccentColor,
checkForegroundColor: environment.theme.list.itemCheckColors.foregroundColor,
checkBorderColor: environment.theme.list.itemCheckColors.strokeColor
)

View file

@ -771,7 +771,7 @@ public class PremiumLimitsListScreen: ViewController {
position: .top,
model: .island,
videoFile: configuration.videos["last_seen"],
decoration: .tag
decoration: .badgeStars
)),
title: strings.Premium_LastSeen,
text: strings.Premium_LastSeenInfo,
@ -790,7 +790,7 @@ public class PremiumLimitsListScreen: ViewController {
position: .top,
model: .island,
videoFile: configuration.videos["message_privacy"],
decoration: .tag
decoration: .swirlStars
)),
title: strings.Premium_MessagePrivacy,
text: strings.Premium_MessagePrivacyInfo,

View file

@ -582,7 +582,6 @@ final class StoriesPageComponent: CombinedComponent {
let topPanel = Child(BlurredBackgroundComponent.self)
let topSeparator = Child(Rectangle.self)
let title = Child(MultilineTextComponent.self)
let secondaryTitle = Child(MultilineTextComponent.self)
let resetScroll = ActionSlot<Void>()
@ -664,17 +663,6 @@ final class StoriesPageComponent: CombinedComponent {
availableSize: context.availableSize,
transition: context.transition
)
let secondaryTitle = secondaryTitle.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: strings.Premium_Stories_AdditionalTitle, font: Font.semibold(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)),
horizontalAlignment: .center,
truncationType: .end,
maximumNumberOfLines: 1
),
availableSize: context.availableSize,
transition: context.transition
)
let topPanelAlpha: CGFloat
if state.topContentOffset > 78.0 {
@ -699,23 +687,9 @@ final class StoriesPageComponent: CombinedComponent {
let titleOriginY: CGFloat = titleBottomOriginY + fraction * titleOriginDelta
let titleScale = 1.0 - max(0.0, fraction * 0.2)
let titleAlpha: CGFloat
if fraction > 0.78 {
titleAlpha = max(0.0, 1.0 - (fraction - 0.78) / 0.16)
} else {
titleAlpha = 1.0
}
let secondaryTitleAlpha: CGFloat = 1.0 - titleAlpha
context.add(title
.position(CGPoint(x: context.availableSize.width / 2.0, y: titleOriginY))
.scale(titleScale)
.opacity(titleAlpha)
)
context.add(secondaryTitle
.position(CGPoint(x: context.availableSize.width / 2.0, y: titleOriginY))
.opacity(secondaryTitleAlpha)
)
return scroll.size

View file

@ -1656,6 +1656,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1704,6 +1705,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
groupId: AnyHashable(info.id),
title: info.title,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1762,6 +1764,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1793,6 +1796,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -510,7 +510,7 @@ private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> It
return Namespaces.ItemCollection.CloudStickerPacks
case .masks:
return Namespaces.ItemCollection.CloudMaskPacks
case .emoji, .groupEmoji:
case .emoji:
return Namespaces.ItemCollection.CloudEmojiPacks
}
}
@ -574,11 +574,6 @@ private func installedStickerPacksControllerEntries(context: AccountContext, pre
entries.append(.suggestAnimatedEmoji(presentationData.strings.StickerPacksSettings_SuggestAnimatedEmoji, stickerSettings.suggestAnimatedEmoji))
entries.append(.suggestAnimatedEmojiInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_SuggestAnimatedEmojiInfo))
case .groupEmoji:
entries.append(.info(presentationData.theme, "All members will be able to use these emoji in the group, even if they don't have Telegram Premium.\n"))
//TODO:localize
entries.append(.packsTitle(presentationData.theme, "CHOOSE EMOJI PACK".uppercased()))
}
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView {
@ -624,27 +619,21 @@ private func installedStickerPacksControllerEntries(context: AccountContext, pre
}
}
if case .groupEmoji = mode {
} else {
var markdownString: String
switch mode {
case .general, .modal:
markdownString = presentationData.strings.StickerPacksSettings_ManagingHelp
case .masks:
markdownString = presentationData.strings.MaskStickerSettings_Info
case .emoji:
markdownString = presentationData.strings.EmojiStickerSettings_Info
case .groupEmoji:
markdownString = ""
}
let entities = generateTextEntities(markdownString, enabledTypes: [.mention])
if let entity = entities.first {
markdownString.insert(contentsOf: "]()", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.upperBound))
markdownString.insert(contentsOf: "[", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.lowerBound))
}
entries.append(.packsInfo(presentationData.theme, markdownString))
var markdownString: String
switch mode {
case .general, .modal:
markdownString = presentationData.strings.StickerPacksSettings_ManagingHelp
case .masks:
markdownString = presentationData.strings.MaskStickerSettings_Info
case .emoji:
markdownString = presentationData.strings.EmojiStickerSettings_Info
}
let entities = generateTextEntities(markdownString, enabledTypes: [.mention])
if let entity = entities.first {
markdownString.insert(contentsOf: "]()", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.upperBound))
markdownString.insert(contentsOf: "[", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.lowerBound))
}
entries.append(.packsInfo(presentationData.theme, markdownString))
return entries
}
@ -917,7 +906,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .masks) |> map(Optional.init)))
quickReaction = .single(nil)
emojiCount.set(.single(0))
case .emoji, .groupEmoji:
case .emoji:
featured.set(.single([]))
archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .emoji) |> map(Optional.init)))
quickReaction = .single(nil)
@ -1070,8 +1059,6 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
} else {
if case .modal = mode {
rightNavigationButton = nil
} else if case .groupEmoji = mode {
rightNavigationButton = nil
} else {
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: {
updateState {
@ -1093,9 +1080,6 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
title = presentationData.strings.MaskStickerSettings_Title
case .emoji:
title = presentationData.strings.EmojiPacksSettings_Title
case .groupEmoji:
//TODO:localize
title = "Group Emoji Pack"
}
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
@ -1250,48 +1234,43 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
packs.insert(packReference, at: 0)
}
if let mainStickerPack = mainStickerPack {
//TODO:localize
presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], mainActionTitle: "Set as Group Emoji Pack", parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { actions in
if case .groupEmoji = mode {
} else {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var animateInAsReplacement = false
if let navigationController = navigationControllerImpl?() {
for controller in navigationController.overlayControllers {
if let controller = controller as? UndoOverlayController {
controller.dismissWithCommitActionAndReplacementAnimation()
animateInAsReplacement = true
}
presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { actions in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var animateInAsReplacement = false
if let navigationController = navigationControllerImpl?() {
for controller in navigationController.overlayControllers {
if let controller = controller as? UndoOverlayController {
controller.dismissWithCommitActionAndReplacementAnimation()
animateInAsReplacement = true
}
}
if let (info, items, action) = actions.first {
switch action {
case .add:
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
return true
}))
case let .remove(positionInList):
let removedTitle: String
let removedText: String
if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle
removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string
} else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle
removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string
} else {
removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle
removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string
}
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
if case .undo = action {
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
}
return true
}))
}
if let (info, items, action) = actions.first {
switch action {
case .add:
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
return true
}))
case let .remove(positionInList):
let removedTitle: String
let removedText: String
if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle
removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string
} else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle
removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string
} else {
removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle
removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string
}
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
if case .undo = action {
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
}
return true
}))
}
}
}), nil)

View file

@ -476,6 +476,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[508332649] = { return Api.Message.parse_message($0) }
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
dict[721967202] = { return Api.Message.parse_messageService($0) }
dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) }
dict[-988359047] = { return Api.MessageAction.parse_messageActionBotAllowed($0) }
dict[-1781355374] = { return Api.MessageAction.parse_messageActionChannelCreate($0) }
dict[-365344535] = { return Api.MessageAction.parse_messageActionChannelMigrateFrom($0) }

View file

@ -664,6 +664,7 @@ public extension Api {
}
public extension Api {
enum MessageAction: TypeConstructorDescription {
case messageActionBoostApply(boosts: Int32)
case messageActionBotAllowed(flags: Int32, domain: String?, app: Api.BotApp?)
case messageActionChannelCreate(title: String)
case messageActionChannelMigrateFrom(title: String, chatId: Int64)
@ -708,6 +709,12 @@ public extension Api {
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageActionBoostApply(let boosts):
if boxed {
buffer.appendInt32(-872240531)
}
serializeInt32(boosts, buffer: buffer, boxed: false)
break
case .messageActionBotAllowed(let flags, let domain, let app):
if boxed {
buffer.appendInt32(-988359047)
@ -1032,6 +1039,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageActionBoostApply(let boosts):
return ("messageActionBoostApply", [("boosts", boosts as Any)])
case .messageActionBotAllowed(let flags, let domain, let app):
return ("messageActionBotAllowed", [("flags", flags as Any), ("domain", domain as Any), ("app", app as Any)])
case .messageActionChannelCreate(let title):
@ -1117,6 +1126,17 @@ public extension Api {
}
}
public static func parse_messageActionBoostApply(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.MessageAction.messageActionBoostApply(boosts: _1!)
}
else {
return nil
}
}
public static func parse_messageActionBotAllowed(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()

View file

@ -224,7 +224,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults:
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply:
break
case let .messageActionChannelMigrateFrom(_, chatId):
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))

View file

@ -135,6 +135,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .giveawayLaunched)
case let .messageActionGiveawayResults(winners, unclaimed):
return TelegramMediaAction(action: .giveawayResults(winners: winners, unclaimed: unclaimed))
case let .messageActionBoostApply(boosts):
return TelegramMediaAction(action: .boostsApplied(boosts: boosts))
}
}

View file

@ -260,7 +260,8 @@ public final class CachedChannelData: CachedPeerData {
public let membersHidden: EnginePeerCachedInfoItem<PeerMembersHidden>
public let viewForumAsMessages: EnginePeerCachedInfoItem<Bool>
public let wallpaper: TelegramWallpaper?
public let boostsUnrestrict: Int32?
public let boostsToUnrestrict: Int32?
public let appliedBoosts: Int32?
public let emojiPack: StickerPackCollectionInfo?
public let peerIds: Set<PeerId>
@ -303,7 +304,8 @@ public final class CachedChannelData: CachedPeerData {
self.membersHidden = .unknown
self.viewForumAsMessages = .unknown
self.wallpaper = nil
self.boostsUnrestrict = nil
self.boostsToUnrestrict = nil
self.appliedBoosts = nil
self.emojiPack = nil
}
@ -339,7 +341,8 @@ public final class CachedChannelData: CachedPeerData {
membersHidden: EnginePeerCachedInfoItem<PeerMembersHidden>,
viewForumAsMessages: EnginePeerCachedInfoItem<Bool>,
wallpaper: TelegramWallpaper?,
boostsUnrestrict: Int32?,
boostsToUnrestrict: Int32?,
appliedBoosts: Int32?,
emojiPack: StickerPackCollectionInfo?
) {
self.isNotAccessible = isNotAccessible
@ -373,7 +376,8 @@ public final class CachedChannelData: CachedPeerData {
self.membersHidden = membersHidden
self.viewForumAsMessages = viewForumAsMessages
self.wallpaper = wallpaper
self.boostsUnrestrict = boostsUnrestrict
self.boostsToUnrestrict = boostsToUnrestrict
self.appliedBoosts = appliedBoosts
self.emojiPack = emojiPack
var peerIds = Set<PeerId>()
@ -402,137 +406,141 @@ public final class CachedChannelData: CachedPeerData {
}
public func withUpdatedIsNotAccessible(_ isNotAccessible: Bool) -> CachedChannelData {
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedAbout(_ about: String?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedMigrationReference(_ migrationReference: ChannelMigrationReference?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedLinkedDiscussionPeerId(_ linkedDiscussionPeerId: LinkedDiscussionPeerId) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedSlowModeTimeout(_ slowModeTimeout: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedSlowModeValidUntilTimestamp(_ slowModeValidUntilTimestamp: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedStatsDatacenterId(_ statsDatacenterId: Int32) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedInvitedOn(_ invitedOn: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedActiveCall(_ activeCall: ActiveCall?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedPendingSuggestions(_ pendingSuggestions: [String]) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedInviteRequestsPending(_ inviteRequestsPending: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedSendAsPeerId(_ sendAsPeerId: PeerId?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedAllowedReactions(_ allowedReactions: EnginePeerCachedInfoItem<PeerAllowedReactions>) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedMembersHidden(_ membersHidden: EnginePeerCachedInfoItem<PeerMembersHidden>) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedViewForumAsMessages(_ viewForumAsMessages: EnginePeerCachedInfoItem<Bool>) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedWallpaper(_ wallpaper: TelegramWallpaper?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: self.emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedBoostsUnrestrict(_ boostsUnrestrict: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: boostsUnrestrict, emojiPack: self.emojiPack)
public func withUpdatedBoostsToUnrestrict(_ boostsToUnrestrict: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdateAppliedBoosts(_ appliedBoosts: Int32?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: appliedBoosts, emojiPack: self.emojiPack)
}
public func withUpdatedEmojiPack(_ emojiPack: StickerPackCollectionInfo?) -> CachedChannelData {
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsUnrestrict: self.boostsUnrestrict, emojiPack: emojiPack)
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: emojiPack)
}
public init(decoder: PostboxDecoder) {
self.isNotAccessible = decoder.decodeInt32ForKey("isNotAccessible", orElse: 0) != 0
self.flags = CachedChannelFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
@ -648,7 +656,9 @@ public final class CachedChannelData: CachedPeerData {
}
}
self.boostsUnrestrict = decoder.decodeOptionalInt32ForKey("bu")
self.boostsToUnrestrict = decoder.decodeOptionalInt32ForKey("bu")
self.appliedBoosts = decoder.decodeOptionalInt32ForKey("ab")
if let emojiPack = decoder.decodeObjectForKey("ep", decoder: { StickerPackCollectionInfo(decoder: $0) }) as? StickerPackCollectionInfo {
self.emojiPack = emojiPack
@ -821,12 +831,18 @@ public final class CachedChannelData: CachedPeerData {
encoder.encodeNil(forKey: "wp")
}
if let boostsUnrestrict = self.boostsUnrestrict {
encoder.encodeInt32(boostsUnrestrict, forKey: "bu")
if let boostsToUnrestrict = self.boostsToUnrestrict {
encoder.encodeInt32(boostsToUnrestrict, forKey: "bu")
} else {
encoder.encodeNil(forKey: "bu")
}
if let appliedBoosts = self.appliedBoosts {
encoder.encodeInt32(appliedBoosts, forKey: "ab")
} else {
encoder.encodeNil(forKey: "ab")
}
if let emojiPack = self.emojiPack {
encoder.encodeObject(emojiPack, forKey: "ep")
} else {
@ -958,12 +974,19 @@ public final class CachedChannelData: CachedPeerData {
if other.viewForumAsMessages != self.viewForumAsMessages {
return false
}
if other.wallpaper != self.wallpaper {
return false
}
if other.boostsUnrestrict != self.boostsUnrestrict {
if other.boostsToUnrestrict != self.boostsToUnrestrict {
return false
}
if other.appliedBoosts != self.appliedBoosts {
return false
}
if other.emojiPack != self.emojiPack {
return false
}

View file

@ -126,6 +126,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case giveawayLaunched
case joinedChannel
case giveawayResults(winners: Int32, unclaimed: Int32)
case boostsApplied(boosts: Int32)
public init(decoder: PostboxDecoder) {
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
@ -232,6 +233,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
self = .joinedChannel
case 39:
self = .giveawayResults(winners: decoder.decodeInt32ForKey("winners", orElse: 0), unclaimed: decoder.decodeInt32ForKey("unclaimed", orElse: 0))
case 40:
self = .boostsApplied(boosts: decoder.decodeInt32ForKey("boosts", orElse: 0))
default:
self = .unknown
}
@ -451,6 +454,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeInt32(39, forKey: "_rawValue")
encoder.encodeInt32(winners, forKey: "winners")
encoder.encodeInt32(unclaimed, forKey: "unclaimed")
case let .boostsApplied(boosts):
encoder.encodeInt32(40, forKey: "_rawValue")
encoder.encodeInt32(boosts, forKey: "boosts")
}
}

View file

@ -183,3 +183,33 @@ func _internal_updateDefaultChannelMemberBannedRights(account: Account, peerId:
|> switchToLatest
}
func _internal_updateChannelBoostsToUnlockRestrictions(account: Account, peerId: PeerId, boosts: Int32) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Never, NoError> in
guard let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) else {
return .complete()
}
return account.network.request(Api.functions.channels.setBoostsToUnblockRestrictions(channel: inputChannel, boosts: boosts))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<Never, NoError> in
guard let result = result else {
return .complete()
}
account.stateManager.addUpdates(result)
return account.postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedBoostsToUnrestrict(boosts)
}
return cachedData
})
}
|> ignoreValues
}
}
|> switchToLatest
}

View file

@ -352,6 +352,10 @@ public extension TelegramEngine {
public func updateDefaultChannelMemberBannedRights(peerId: PeerId, rights: TelegramChatBannedRights) -> Signal<Never, NoError> {
return _internal_updateDefaultChannelMemberBannedRights(account: self.account, peerId: peerId, rights: rights)
}
public func updateChannelBoostsToUnlockRestrictions(peerId: PeerId, boosts: Int32) -> Signal<Never, NoError> {
return _internal_updateChannelBoostsToUnlockRestrictions(account: self.account, peerId: peerId, boosts: boosts)
}
public func createChannel(title: String, description: String?, username: String? = nil) -> Signal<PeerId, CreateChannelError> {
return _internal_createChannel(account: self.account, title: title, description: description, username: username)

View file

@ -459,7 +459,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
}
switch fullChat {
case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, _, wallpaper, _, boostsUnrestrict, emojiSet):
case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, _, wallpaper, appliedBoosts, boostsUnrestrict, emojiSet):
var channelFlags = CachedChannelFlags()
if (flags & (1 << 3)) != 0 {
channelFlags.insert(.canDisplayParticipants)
@ -674,7 +674,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
.withUpdatedMembersHidden(.known(PeerMembersHidden(value: membersHidden)))
.withUpdatedViewForumAsMessages(.known(forumViewAsMessages))
.withUpdatedWallpaper(wallpaper)
.withUpdatedBoostsUnrestrict(boostsUnrestrict)
.withUpdatedBoostsToUnrestrict(boostsUnrestrict)
.withUpdateAppliedBoosts(appliedBoosts)
.withUpdatedEmojiPack(emojiPack)
})

View file

@ -122,6 +122,7 @@ public enum PresentationResourceKey: Int32 {
case chatTitleLockIcon
case chatTitleMuteIcon
case chatPanelLockIcon
case chatPanelBoostIcon
case chatBubbleVerticalLineIncomingImage
case chatBubbleVerticalLineOutgoingImage

View file

@ -84,6 +84,12 @@ public struct PresentationResourcesChat {
})
}
public static func chatPanelBoostIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatPanelBoostIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Premium/BoostChannel"), color: theme.chat.inputPanel.panelControlAccentColor)
})
}
public static func chatTitleMuteIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatTitleMuteIcon.rawValue, { theme in
return generateImage(CGSize(width: 9.0, height: 9.0), rotatedContext: { size, context in

View file

@ -959,6 +959,25 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} else {
attributedString = parseMarkdownIntoAttributedString(strings.Notification_GiveawayResults(winners), attributes: MarkdownAttributes(body: bodyAttributes, bold: boldAttributes, link: bodyAttributes, linkAttribute: { _ in return nil }))
}
case let .boostsApplied(boosts):
if message.author?.id == accountPeerId {
if boosts == 1 {
attributedString = NSAttributedString(string: strings.Notification_Boost_SingleYou, font: titleFont, textColor: primaryTextColor)
} else {
let boostsString = strings.Notification_Boost_Times(boosts)
attributedString = NSAttributedString(string: strings.Notification_Boost_MultipleYou(boostsString).string, font: titleFont, textColor: primaryTextColor)
}
} else {
let peerName = message.author?.compactDisplayTitle ?? ""
if boosts == 1 {
let resultTitleString = strings.Notification_Boost_Single(peerName)
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
} else {
let boostsString = strings.Notification_Boost_Times(boosts)
let resultTitleString = strings.Notification_Boost_Multiple(peerName, boostsString)
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
}
}
case .unknown:
attributedString = nil
}

View file

@ -428,6 +428,7 @@ final class AvatarEditorScreenComponent: Component {
groupId: "emoji",
title: "Emoji",
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -448,6 +449,7 @@ final class AvatarEditorScreenComponent: Component {
groupId: "stickers",
title: "Stickers",
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -505,6 +507,7 @@ final class AvatarEditorScreenComponent: Component {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -538,6 +541,7 @@ final class AvatarEditorScreenComponent: Component {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -1061,7 +1061,7 @@ private final class CameraScreenComponent: CombinedComponent {
.disappear(.default(scale: true))
)
if !isTablet && Camera.isDualCameraSupported {
if !isTablet && Camera.isDualCameraSupported(forRoundVideo: false) {
let dualButton = dualButton.update(
component: CameraButton(
content: AnyComponentWithIdentity(
@ -1513,7 +1513,7 @@ public class CameraScreen: ViewController {
self.previewBlurView = BlurView()
self.previewBlurView.isUserInteractionEnabled = false
var isDualCameraEnabled = Camera.isDualCameraSupported
var isDualCameraEnabled = Camera.isDualCameraSupported(forRoundVideo: false)
if isDualCameraEnabled {
if let isDualCameraEnabledValue = UserDefaults.standard.object(forKey: "TelegramStoryCameraIsDualEnabled") as? NSNumber {
isDualCameraEnabled = isDualCameraEnabledValue.boolValue

View file

@ -564,7 +564,12 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
false
)
actionButtonMinWidthAndFinalizeLayout = (buttonWidth, continueLayout)
actualWidth = max(actualWidth, buttonWidth)
var buttonInset: CGFloat = 0.0
if let buttonIconImage {
buttonInset += buttonIconImage.size.width + 2.0
}
actualWidth = max(actualWidth, buttonWidth + buttonInset * 2.0)
} else {
actionButtonMinWidthAndFinalizeLayout = nil
}

View file

@ -321,6 +321,11 @@ public class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
}
let (addButtonWidth, addContinueLayout) = makeAddButtonLayout(constrainedSize.width, 10.0, nil, false, addTitle.uppercased(), mainColor, false, false)
let showAddButton = !(!canAdd && canMessage)
let showMessageButton = canMessage
let buttonCount = (showAddButton ? 1 : 0) + (showMessageButton ? 1 : 0)
let maxButtonWidth = max(messageButtonWidth, addButtonWidth)
var maxContentWidth: CGFloat = avatarSize.width + 7.0
if let statusSuggestedWidthAndContinue = statusSuggestedWidthAndContinue {
@ -328,7 +333,7 @@ public class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
}
maxContentWidth = max(maxContentWidth, 7.0 + avatarSize.width + 7.0 + titleLayout.size.width + 7.0)
maxContentWidth = max(maxContentWidth, 7.0 + avatarSize.width + 7.0 + textLayout.size.width + 7.0)
maxContentWidth = max(maxContentWidth, maxButtonWidth * 2.0)
maxContentWidth = max(maxContentWidth, maxButtonWidth * CGFloat(buttonCount))
maxContentWidth = max(maxContentWidth, 220.0)
let contentWidth = maxContentWidth + layoutConstants.text.bubbleInsets.right * 2.0

View file

@ -167,6 +167,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
}, hideTranslationPanel: {
}, openPremiumGift: {
}, openPremiumRequiredForMessaging: {
}, openBoostToUnrestrict: {
}, updateHistoryFilter: { _ in
}, requestLayout: { _ in
}, chatController: {

View file

@ -231,7 +231,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
public let displayGiveawayParticipationStatus: (EngineMessage.Id) -> Void
public let openPremiumStatusInfo: (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void
public let openRecommendedChannelContextMenu: (EnginePeer, UIView, ContextGesture?) -> Void
public let openGroupBoostInfo: (EnginePeer.Id, Int) -> Void
public let openGroupBoostInfo: (EnginePeer.Id?, Int) -> Void
public let requestMessageUpdate: (MessageId, Bool) -> Void
public let cancelInteractiveKeyboardGestures: () -> Void
@ -354,7 +354,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
displayGiveawayParticipationStatus: @escaping (EngineMessage.Id) -> Void,
openPremiumStatusInfo: @escaping (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void,
openRecommendedChannelContextMenu: @escaping (EnginePeer, UIView, ContextGesture?) -> Void,
openGroupBoostInfo: @escaping (EnginePeer.Id, Int) -> Void,
openGroupBoostInfo: @escaping (EnginePeer.Id?, Int) -> Void,
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
cancelInteractiveKeyboardGestures: @escaping () -> Void,
dismissTextInput: @escaping () -> Void,

View file

@ -639,7 +639,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
}
}
if file.isPremiumEmoji && !hasPremium {
if file.isPremiumEmoji && !hasPremium && groupId != AnyHashable("peerSpecific") {
var animateInAsReplacement = false
if let currentUndoOverlayController = strongSelf.currentUndoOverlayController {
currentUndoOverlayController.dismissWithCommitActionAndReplacementAnimation()
@ -959,6 +959,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1007,6 +1008,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: AnyHashable(info.id),
title: info.title,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1065,6 +1067,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1095,6 +1098,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1365,6 +1369,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -1395,6 +1400,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -578,6 +578,7 @@ public final class EmojiStatusSelectionController: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -632,6 +633,7 @@ public final class EmojiStatusSelectionController: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -663,6 +665,7 @@ public final class EmojiStatusSelectionController: ViewController {
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -771,6 +771,8 @@ private final class GroupHeaderLayer: UIView {
private var tintSubtitleLayer: SimpleLayer?
private var lockIconLayer: SimpleLayer?
private var tintLockIconLayer: SimpleLayer?
private var badgeLayer: SimpleLayer?
private var tintBadgeLayer: SimpleLayer?
private(set) var clearIconLayer: SimpleLayer?
private var tintClearIconLayer: SimpleLayer?
private var separatorLayer: SimpleLayer?
@ -816,6 +818,7 @@ private final class GroupHeaderLayer: UIView {
actionButtonTitle: String?,
title: String,
subtitle: String?,
badge: String?,
isPremiumLocked: Bool,
hasClear: Bool,
embeddedItems: [EmojiPagerContentComponent.Item]?,
@ -831,7 +834,7 @@ private final class GroupHeaderLayer: UIView {
self.theme = theme
themeUpdated = true
}
let needsVibrancy = !theme.overallDarkAppearance || forceNeedsVibrancy
let textOffsetY: CGFloat
@ -978,10 +981,72 @@ private final class GroupHeaderLayer: UIView {
self.tintTextLayer.isHidden = !needsVibrancy
self.currentTextLayout = (title, color, textConstrainedWidth, textSize)
}
var badgeSize: CGSize = .zero
if let badge {
func generateBadgeImage(color: UIColor) -> UIImage? {
let string = NSAttributedString(string: badge, font: Font.semibold(11.0), textColor: .white)
let stringBounds = string.boundingRect(with: CGSize(width: 120, height: 18.0), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
let badgeSize = CGSize(width: stringBounds.width + 8.0, height: 16.0)
return generateImage(badgeSize, opaque: false, scale: 0.0, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(color.cgColor)
context.addPath(UIBezierPath(roundedRect: CGRect(origin: .zero, size: badgeSize), cornerRadius: badgeSize.height / 2.0).cgPath)
context.fillPath()
context.setBlendMode(.clear)
UIGraphicsPushContext(context)
string.draw(with: CGRect(origin: CGPoint(x: floorToScreenPixels((badgeSize.width - stringBounds.size.width) / 2.0), y: floorToScreenPixels((badgeSize.height - stringBounds.size.height) / 2.0)), size: stringBounds.size), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
UIGraphicsPopContext()
})
}
let badgeLayer: SimpleLayer
if let current = self.badgeLayer {
badgeLayer = current
} else {
badgeLayer = SimpleLayer()
self.badgeLayer = badgeLayer
self.layer.addSublayer(badgeLayer)
if let image = generateBadgeImage(color: color.withMultipliedAlpha(0.66)) {
badgeLayer.contents = image.cgImage
badgeLayer.bounds = CGRect(origin: .zero, size: image.size)
}
}
badgeSize = badgeLayer.bounds.size
let tintBadgeLayer: SimpleLayer
if let current = self.tintBadgeLayer {
tintBadgeLayer = current
} else {
tintBadgeLayer = SimpleLayer()
self.tintBadgeLayer = tintBadgeLayer
self.tintContentLayer.addSublayer(tintBadgeLayer)
if let image = generateBadgeImage(color: .white) {
tintBadgeLayer.contents = image.cgImage
}
}
} else {
if let badgeLayer = self.badgeLayer {
self.badgeLayer = nil
badgeLayer.removeFromSuperlayer()
}
if let tintBadgeLayer = self.tintBadgeLayer {
self.tintBadgeLayer = nil
tintBadgeLayer.removeFromSuperlayer()
}
}
let textFrame: CGRect
if subtitle == nil {
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), y: textOffsetY), size: textSize)
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - (textSize.width + badgeSize.width)) / 2.0), y: textOffsetY), size: textSize)
} else {
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize)
}
@ -989,6 +1054,11 @@ private final class GroupHeaderLayer: UIView {
self.tintTextLayer.frame = textFrame
self.tintTextLayer.isHidden = !needsTintText
if let badgeLayer = self.badgeLayer, let tintBadgeLayer = self.tintBadgeLayer {
badgeLayer.frame = CGRect(origin: CGPoint(x: textFrame.maxX + 4.0, y: 0.0), size: badgeLayer.frame.size)
tintBadgeLayer.frame = badgeLayer.frame
}
if isPremiumLocked {
let lockIconLayer: SimpleLayer
if let current = self.lockIconLayer {
@ -2536,6 +2606,7 @@ public final class EmojiPagerContentComponent: Component {
public let groupId: AnyHashable
public let title: String?
public let subtitle: String?
public let badge: String?
public let actionButtonTitle: String?
public let isFeatured: Bool
public let isPremiumLocked: Bool
@ -2553,6 +2624,7 @@ public final class EmojiPagerContentComponent: Component {
groupId: AnyHashable,
title: String?,
subtitle: String?,
badge: String?,
actionButtonTitle: String?,
isFeatured: Bool,
isPremiumLocked: Bool,
@ -2569,6 +2641,7 @@ public final class EmojiPagerContentComponent: Component {
self.groupId = groupId
self.title = title
self.subtitle = subtitle
self.badge = badge
self.actionButtonTitle = actionButtonTitle
self.isFeatured = isFeatured
self.isPremiumLocked = isPremiumLocked
@ -2598,6 +2671,9 @@ public final class EmojiPagerContentComponent: Component {
if lhs.subtitle != rhs.subtitle {
return false
}
if lhs.badge != rhs.badge {
return false
}
if lhs.actionButtonTitle != rhs.actionButtonTitle {
return false
}
@ -5540,6 +5616,7 @@ public final class EmojiPagerContentComponent: Component {
actionButtonTitle: actionButtonTitle,
title: title,
subtitle: itemGroup.subtitle,
badge: itemGroup.badge,
isPremiumLocked: itemGroup.isPremiumLocked,
hasClear: itemGroup.hasClear,
embeddedItems: itemGroup.isEmbedded ? itemGroup.items : nil,

View file

@ -208,6 +208,7 @@ public extension EmojiPagerContentComponent {
var id: AnyHashable
var title: String?
var subtitle: String?
var badge: String?
var isPremiumLocked: Bool
var isFeatured: Bool
var collapsedLineCount: Int?
@ -241,7 +242,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@ -317,7 +318,7 @@ public extension EmojiPagerContentComponent {
itemGroupIndexById[groupId] = itemGroups.count
let title = context.sharedContext.currentPresentationData.with({ $0 }).strings.EmojiInput_TrendingEmoji
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 0, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 0, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@ -373,7 +374,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@ -432,7 +433,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@ -592,7 +593,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@ -738,7 +739,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@ -816,7 +817,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
@ -874,7 +875,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
}
} else {
let groupId = "recent"
@ -886,7 +887,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@ -958,7 +959,7 @@ public extension EmojiPagerContentComponent {
popularInsertIndex += 1
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
}
}
}
@ -1023,7 +1024,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
} else if [.profilePhoto, .groupPhoto].contains(subject) {
@ -1031,7 +1032,7 @@ public extension EmojiPagerContentComponent {
let groupId = "recent"
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: []))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: []))
if let featuredAvatarEmoji = featuredAvatarEmoji {
for item in featuredAvatarEmoji.items {
@ -1100,7 +1101,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
if let featuredBackgroundIconEmoji {
@ -1208,15 +1209,11 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: true, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: true, headerItem: nil, items: [resultItem]))
}
}
}
if !hasPremium {
maybeAppendUnicodeEmoji()
}
var itemCollectionMapping: [ItemCollectionId: StickerPackCollectionInfo] = [:]
for (id, info, _) in view.collectionInfos {
if let info = info as? StickerPackCollectionInfo {
@ -1260,13 +1257,18 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.peer.compactDisplayTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
//TODO:localize
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.info.title, subtitle: nil, badge: "GROUP EMOJI", isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
let supergroupId: AnyHashable = peerSpecificPack.info.id
skippedCollectionIds.insert(supergroupId)
}
if !hasPremium {
maybeAppendUnicodeEmoji()
}
if areCustomEmojiEnabled {
for entry in view.entries {
@ -1364,7 +1366,7 @@ public extension EmojiPagerContentComponent {
break inner
}
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, badge: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
@ -1453,7 +1455,7 @@ public extension EmojiPagerContentComponent {
isFeatured = false
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: isFeatured, collapsedLineCount: 3, isClearable: false, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, badge: nil, isPremiumLocked: isPremiumLocked, isFeatured: isFeatured, collapsedLineCount: 3, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
}
@ -1508,6 +1510,7 @@ public extension EmojiPagerContentComponent {
groupId: group.id,
title: group.title,
subtitle: group.subtitle,
badge: group.badge,
actionButtonTitle: nil,
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,
@ -1994,6 +1997,7 @@ public extension EmojiPagerContentComponent {
groupId: group.id,
title: group.title,
subtitle: group.subtitle,
badge: nil,
actionButtonTitle: group.actionButtonTitle,
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,

View file

@ -122,6 +122,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: AnyHashable(groupItem.info.id),
title: groupItem.info.title,
subtitle: nil,
badge: nil,
actionButtonTitle: self.presentationData.strings.EmojiInput_AddPack(groupItem.info.title).string,
isFeatured: true,
isPremiumLocked: !self.hasPremiumForInstallation,
@ -286,6 +287,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -340,6 +342,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@ -373,6 +376,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,

View file

@ -20,6 +20,9 @@ swift_library(
"//submodules/AccountContext:AccountContext",
"//submodules/StickerPackPreviewUI:StickerPackPreviewUI",
"//submodules/ItemListStickerPackItem:ItemListStickerPackItem",
"//submodules/SearchBarNode:SearchBarNode",
"//submodules/SearchUI:SearchUI",
"//submodules/MergeLists:MergeLists",
],
visibility = [
"//visibility:public",

View file

@ -259,6 +259,7 @@ private enum GroupStickerPackSearchState: Equatable {
private struct GroupStickerPackSetupControllerState: Equatable {
var isSaving: Bool
var searchingPacks: Bool
}
private func groupStickerPackSetupControllerEntries(context: AccountContext, presentationData: PresentationData, searchText: String, view: CombinedView, initialData: InitialStickerPackData?, searchState: GroupStickerPackSearchState, stickerSettings: StickerSettings, emoji: Bool) -> [GroupStickerPackEntry] {
@ -276,10 +277,10 @@ private func groupStickerPackSetupControllerEntries(context: AccountContext, pre
case .searching:
entries.append(.currentPack(0, presentationData.theme, presentationData.strings, .searching))
case let .found(data):
entries.append(.currentPack(0, presentationData.theme, presentationData.strings, .found(packInfo: data.info, topItem: data.item, subtitle: presentationData.strings.StickerPack_StickerCount(data.info.count))))
entries.append(.currentPack(0, presentationData.theme, presentationData.strings, .found(packInfo: data.info, topItem: data.item, subtitle: emoji ? presentationData.strings.StickerPack_EmojiCount(data.info.count) : presentationData.strings.StickerPack_StickerCount(data.info.count))))
}
entries.append(.searchInfo(presentationData.theme, emoji ? "All members will be able to use these emoji in the group, even if they don't have Telegram Premium." : presentationData.strings.Channel_Stickers_CreateYourOwn))
entries.append(.packsTitle(presentationData.theme, emoji ? "CHOOSE FROM YOUR EMOJI" : presentationData.strings.Channel_Stickers_YourStickers))
entries.append(.packsTitle(presentationData.theme, emoji ? "CHOOSE EMOJI PACK" : presentationData.strings.Channel_Stickers_YourStickers))
let namespace = emoji ? Namespaces.ItemCollection.CloudEmojiPacks : Namespaces.ItemCollection.CloudStickerPacks
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespace])] as? ItemCollectionInfosView {
@ -291,7 +292,15 @@ private func groupStickerPackSetupControllerEntries(context: AccountContext, pre
if case let .found(found) = searchState {
selected = found.info.id == info.id
}
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), context.sharedContext.energyUsageSettings.loopStickers, selected))
let count = info.count == 0 ? entry.count : info.count
let thumbnail: StickerPackItem?
if let thumbnailRep = info.thumbnail {
thumbnail = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: thumbnailRep.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: info.immediateThumbnailData, mimeType: "", size: nil, attributes: []), indexKeys: [])
} else {
thumbnail = entry.firstItem as? StickerPackItem
}
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, thumbnail, emoji ? presentationData.strings.StickerPack_EmojiCount(count) : presentationData.strings.StickerPack_StickerCount(count), context.sharedContext.energyUsageSettings.loopStickers, selected))
index += 1
}
}
@ -302,7 +311,7 @@ private func groupStickerPackSetupControllerEntries(context: AccountContext, pre
}
public func groupStickerPackSetupController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: PeerId, emoji: Bool = false, currentPackInfo: StickerPackCollectionInfo?, completion: ((StickerPackCollectionInfo?) -> Void)? = nil) -> ViewController {
let initialState = GroupStickerPackSetupControllerState(isSaving: false)
let initialState = GroupStickerPackSetupControllerState(isSaving: false, searchingPacks: false)
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState)
@ -433,10 +442,15 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
})
}
var rightNavigationButton: ItemListNavigationButton?
if let _ = completion {
rightNavigationButton = ItemListNavigationButton(content: .icon(.search), style: .regular, enabled: true, action: {})
rightNavigationButton = ItemListNavigationButton(content: .icon(.search), style: .regular, enabled: true, action: {
updateState { state in
var updatedState = state
updatedState.searchingPacks = true
return updatedState
}
})
} else {
if initialData != nil {
if state.isSaving {
@ -467,7 +481,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
return state
}
saveDisposable.set((context.engine.peers.updateGroupSpecificStickerset(peerId: peerId, info: info)
|> deliverOnMainQueue).start(error: { _ in
|> deliverOnMainQueue).start(error: { _ in
updateState { state in
var state = state
state.isSaving = false
@ -483,6 +497,21 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
}
}
var searchItem: ItemListControllerSearch?
if state.searchingPacks {
searchItem = GroupStickerSearchItem(context: context, cancel: {
updateState { state in
var updatedState = state
updatedState.searchingPacks = false
return updatedState
}
}, select: { pack in
arguments.selectStickerPack(pack)
}, dismissInput: {
dismissInputImpl?()
})
}
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(emoji ? "Group Emoji Pack" : presentationData.strings.Channel_Info_Stickers), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
let hasData = initialData != nil
@ -493,7 +522,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
}
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStickerPackSetupControllerEntries(context: context, presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings, emoji: emoji), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: hasData && hadData)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStickerPackSetupControllerEntries(context: context, presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings, emoji: emoji), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: hasData && hadData)
return (controllerState, (listState, arguments))
} |> afterDisposed {
actionsDisposable.dispose()

View file

@ -0,0 +1,328 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import SearchUI
import ItemListUI
import ItemListStickerPackItem
private final class GroupStickerSearchContainerInteraction {
let packSelected: (StickerPackCollectionInfo) -> Void
init(packSelected: @escaping (StickerPackCollectionInfo) -> Void) {
self.packSelected = packSelected
}
}
private final class GroupStickerSearchEntry: Comparable, Identifiable {
let index: Int
let pack: StickerPackCollectionInfo
let topItem: ItemCollectionItem?
init(index: Int, pack: StickerPackCollectionInfo, topItem: ItemCollectionItem?) {
self.index = index
self.pack = pack
self.topItem = topItem
}
var stableId: ItemCollectionId {
return self.pack.id
}
static func ==(lhs: GroupStickerSearchEntry, rhs: GroupStickerSearchEntry) -> Bool {
return lhs.index == rhs.index && lhs.pack == rhs.pack
}
static func <(lhs: GroupStickerSearchEntry, rhs: GroupStickerSearchEntry) -> Bool {
return lhs.index < rhs.index
}
func item(context: AccountContext, presentationData: PresentationData, interaction: GroupStickerSearchContainerInteraction) -> ListViewItem {
let pack = self.pack
let count = presentationData.strings.StickerPack_EmojiCount(pack.count)
return ItemListStickerPackItem(presentationData: ItemListPresentationData(presentationData), context: context, packInfo: pack, itemCount: count, topItem: self.topItem as? StickerPackItem, unread: false, control: .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: true, style: .plain, sectionId: 0, action: {
interaction.packSelected(pack)
}, setPackIdWithRevealedOptions: { _, _ in
}, addPack: {
}, removePack: {
}, toggleSelected: {
})
}
}
struct GroupStickerSearchContainerTransition {
let deletions: [ListViewDeleteItem]
let insertions: [ListViewInsertItem]
let updates: [ListViewUpdateItem]
let isSearching: Bool
let isEmpty: Bool
let query: String
}
private func groupStickerSearchContainerPreparedRecentTransition(from fromEntries: [GroupStickerSearchEntry], to toEntries: [GroupStickerSearchEntry], isSearching: Bool, isEmpty: Bool, query: String, context: AccountContext, presentationData: PresentationData, interaction: GroupStickerSearchContainerInteraction) -> GroupStickerSearchContainerTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) }
return GroupStickerSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching, isEmpty: isEmpty, query: query)
}
public final class GroupStickerSearchContainerNode: SearchDisplayControllerContentNode {
private let context: AccountContext
private let packSelected: (StickerPackCollectionInfo) -> Void
private let listNode: ListView
private let emptyResultsTitleNode: ImmediateTextNode
private let emptyResultsTextNode: ImmediateTextNode
private var enqueuedTransitions: [(GroupStickerSearchContainerTransition, Bool)] = []
private var validLayout: (ContainerViewLayout, CGFloat)?
private let searchQuery = Promise<String?>()
private let searchDisposable = MetaDisposable()
private let forceTheme: PresentationTheme?
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
private let removeMemberDisposable = MetaDisposable()
private let presentationDataPromise: Promise<PresentationData>
private var _hasDim: Bool = false
override public var hasDim: Bool {
return _hasDim
}
public init(context: AccountContext, forceTheme: PresentationTheme?, packSelected: @escaping (StickerPackCollectionInfo) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void) {
self.context = context
self.packSelected = packSelected
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.presentationData = presentationData
self.forceTheme = forceTheme
if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
}
self.presentationDataPromise = Promise(self.presentationData)
self.listNode = ListView()
self.listNode.accessibilityPageScrolledString = { row, count in
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
}
self.emptyResultsTitleNode = ImmediateTextNode()
self.emptyResultsTitleNode.displaysAsynchronously = false
self.emptyResultsTitleNode.attributedText = NSAttributedString(string: self.presentationData.strings.ChatList_Search_NoResults, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.freeTextColor)
self.emptyResultsTitleNode.textAlignment = .center
self.emptyResultsTitleNode.isHidden = true
self.emptyResultsTextNode = ImmediateTextNode()
self.emptyResultsTextNode.displaysAsynchronously = false
self.emptyResultsTextNode.maximumNumberOfLines = 0
self.emptyResultsTextNode.textAlignment = .center
self.emptyResultsTextNode.isHidden = true
super.init()
self.listNode.backgroundColor = self.presentationData.theme.chatList.backgroundColor
self.listNode.isHidden = true
self._hasDim = true
self.addSubnode(self.listNode)
self.addSubnode(self.emptyResultsTitleNode)
self.addSubnode(self.emptyResultsTextNode)
let interaction = GroupStickerSearchContainerInteraction(packSelected: { [weak self] pack in
packSelected(pack)
self?.listNode.clearHighlightAnimated(true)
})
let foundItems = self.searchQuery.get()
|> mapToSignal { query -> Signal<[GroupStickerSearchEntry]?, NoError> in
guard let query, !query.isEmpty else {
return .single(nil)
}
return context.engine.stickers.searchEmojiSets(query: query)
|> mapToSignal { localResult in
return context.engine.stickers.searchEmojiSetsRemotely(query: query)
|> map { remoteResult -> [GroupStickerSearchEntry]? in
let mergedResult = localResult.merge(with: remoteResult)
var entries: [GroupStickerSearchEntry] = []
var index = 0
for info in mergedResult.infos {
if let pack = info.1 as? StickerPackCollectionInfo {
entries.append(GroupStickerSearchEntry(index: index, pack: pack, topItem: info.2))
index += 1
}
}
return entries
}
}
}
let previousSearchItems = Atomic<[GroupStickerSearchEntry]?>(value: nil)
self.searchDisposable.set((combineLatest(self.searchQuery.get(), foundItems, self.presentationDataPromise.get())
|> deliverOnMainQueue).start(next: { [weak self] query, entries, presentationData in
if let strongSelf = self {
let previousEntries = previousSearchItems.swap(entries)
updateActivity(false)
let firstTime = previousEntries == nil
let transition = groupStickerSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, isEmpty: entries?.isEmpty ?? false, query: query ?? "", context: context, presentationData: presentationData, interaction: interaction)
strongSelf.enqueueTransition(transition, firstTime: firstTime)
}
}))
self.presentationDataDisposable = (context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self {
var presentationData = presentationData
let previousTheme = strongSelf.presentationData.theme
let previousStrings = strongSelf.presentationData.strings
if let forceTheme = strongSelf.forceTheme {
presentationData = presentationData.withUpdated(theme: forceTheme)
}
strongSelf.presentationData = presentationData
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
strongSelf.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings)
}
}
})
self.listNode.beganInteractiveDragging = { [weak self] _ in
self?.dismissInput?()
}
}
deinit {
self.searchDisposable.dispose()
self.presentationDataDisposable?.dispose()
}
private func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
self.listNode.backgroundColor = theme.chatList.backgroundColor
}
override public func searchTextUpdated(text: String) {
if text.isEmpty {
self.searchQuery.set(.single(nil))
} else {
self.searchQuery.set(.single(text))
}
}
private func enqueueTransition(_ transition: GroupStickerSearchContainerTransition, firstTime: Bool) {
enqueuedTransitions.append((transition, firstTime))
if let _ = self.validLayout {
while !self.enqueuedTransitions.isEmpty {
self.dequeueTransition()
}
}
}
private func dequeueTransition() {
if let (transition, firstTime) = self.enqueuedTransitions.first {
self.enqueuedTransitions.remove(at: 0)
var options = ListViewDeleteAndInsertOptions()
options.insert(.PreferSynchronousDrawing)
options.insert(.PreferSynchronousResourceLoading)
if firstTime {
} else {
//options.insert(.AnimateAlpha)
}
let isSearching = transition.isSearching
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in
guard let strongSelf = self else {
return
}
strongSelf.listNode.isHidden = !isSearching
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(transition.query).string, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
let emptyResults = transition.isSearching && transition.isEmpty
strongSelf.emptyResultsTitleNode.isHidden = !emptyResults
strongSelf.emptyResultsTextNode.isHidden = !emptyResults
if let (layout, navigationBarHeight) = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
}
})
}
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
let hadValidLayout = self.validLayout == nil
self.validLayout = (layout, navigationBarHeight)
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
var insets = layout.insets(options: [.input])
insets.top += navigationBarHeight
insets.left += layout.safeInsets.left
insets.right += layout.safeInsets.right
self.listNode.frame = CGRect(origin: CGPoint(), size: layout.size)
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
let padding: CGFloat = 16.0
let emptyTitleSize = self.emptyResultsTitleNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0, height: CGFloat.greatestFiniteMagnitude))
let emptyTextSize = self.emptyResultsTextNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0, height: CGFloat.greatestFiniteMagnitude))
let emptyTextSpacing: CGFloat = 8.0
let emptyTotalHeight = emptyTitleSize.height + emptyTextSize.height + emptyTextSpacing
let emptyTitleY = navigationBarHeight + floorToScreenPixels((layout.size.height - navigationBarHeight - max(insets.bottom, layout.intrinsicInsets.bottom) - emptyTotalHeight) / 2.0)
transition.updateFrame(node: self.emptyResultsTitleNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + padding + (layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0 - emptyTitleSize.width) / 2.0, y: emptyTitleY), size: emptyTitleSize))
transition.updateFrame(node: self.emptyResultsTextNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + padding + (layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0 - emptyTextSize.width) / 2.0, y: emptyTitleY + emptyTitleSize.height + emptyTextSpacing), size: emptyTextSize))
if !hadValidLayout {
while !self.enqueuedTransitions.isEmpty {
self.dequeueTransition()
}
}
}
override public func scrollToTop() {
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.cancel?()
}
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard let result = self.view.hitTest(point, with: event) else {
return nil
}
if result === self.view {
return nil
}
return result
}
}

View file

@ -0,0 +1,119 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import TelegramCore
import SwiftSignalKit
import ItemListUI
import PresentationDataUtils
import AccountContext
final class GroupStickerSearchItem: ItemListControllerSearch {
let context: AccountContext
let cancel: () -> Void
let select: (StickerPackCollectionInfo) -> Void
let dismissInput: () -> Void
private var updateActivity: ((Bool) -> Void)?
private var activity: ValuePromise<Bool> = ValuePromise(ignoreRepeated: false)
private let activityDisposable = MetaDisposable()
init(
context: AccountContext,
cancel: @escaping () -> Void,
select: @escaping (StickerPackCollectionInfo) -> Void,
dismissInput: @escaping () -> Void
) {
self.context = context
self.cancel = cancel
self.select = select
self.dismissInput = dismissInput
self.activityDisposable.set((self.activity.get() |> mapToSignal { value -> Signal<Bool, NoError> in
if value {
return .single(value) |> delay(0.2, queue: Queue.mainQueue())
} else {
return .single(value)
}
}).start(next: { [weak self] value in
self?.updateActivity?(value)
}))
}
deinit {
self.activityDisposable.dispose()
}
func isEqual(to: ItemListControllerSearch) -> Bool {
if let to = to as? GroupStickerSearchItem {
if self.context !== to.context {
return false
}
return true
} else {
return false
}
}
func titleContentNode(current: (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)?) -> NavigationBarContentNode & ItemListControllerSearchNavigationContentNode {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
if let current = current as? GroupStickerSearchNavigationContentNode {
current.updateTheme(presentationData.theme)
return current
} else {
return GroupStickerSearchNavigationContentNode(theme: presentationData.theme, strings: presentationData.strings, cancel: self.cancel, updateActivity: { [weak self] value in
self?.updateActivity = value
})
}
}
func node(current: ItemListControllerSearchNode?, titleContentNode: (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)?) -> ItemListControllerSearchNode {
return GroupStickerSearchItemNode(context: self.context, packSelected: self.select, cancel: self.cancel, updateActivity: { [weak self] value in
self?.activity.set(value)
}, pushController: { c in
}, dismissInput: self.dismissInput)
}
}
private final class GroupStickerSearchItemNode: ItemListControllerSearchNode {
private let containerNode: GroupStickerSearchContainerNode
init(context: AccountContext, packSelected: @escaping (StickerPackCollectionInfo) -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, dismissInput: @escaping () -> Void) {
self.containerNode = GroupStickerSearchContainerNode(context: context, forceTheme: nil, packSelected: { pack in
packSelected(pack)
cancel()
}, updateActivity: updateActivity, pushController: pushController)
self.containerNode.cancel = {
cancel()
}
super.init()
self.addSubnode(self.containerNode)
self.containerNode.dismissInput = {
dismissInput()
}
}
override func queryUpdated(_ query: String) {
self.containerNode.searchTextUpdated(text: query)
}
override func scrollToTop() {
self.containerNode.scrollToTop()
}
override func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - navigationBarHeight)))
self.containerNode.containerLayoutUpdated(layout.withUpdatedSize(CGSize(width: layout.size.width, height: layout.size.height - navigationBarHeight)), navigationBarHeight: 0.0, transition: transition)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = self.containerNode.hitTest(self.view.convert(point, to: self.containerNode.view), with: event) {
return result
}
return super.hitTest(point, with: event)
}
}

View file

@ -0,0 +1,88 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import Postbox
import TelegramCore
import TelegramPresentationData
import ItemListUI
import PresentationDataUtils
import SearchBarNode
private let searchBarFont = Font.regular(17.0)
final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, ItemListControllerSearchNavigationContentNode {
private var theme: PresentationTheme
private let strings: PresentationStrings
private let cancel: () -> Void
private let searchBar: SearchBarNode
private var queryUpdated: ((String) -> Void)?
var activity: Bool = false {
didSet {
self.searchBar.activity = activity
}
}
init(theme: PresentationTheme, strings: PresentationStrings, cancel: @escaping () -> Void, updateActivity: @escaping(@escaping(Bool)->Void) -> Void) {
self.theme = theme
self.strings = strings
self.cancel = cancel
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, displayBackground: false)
super.init()
self.addSubnode(self.searchBar)
self.searchBar.cancel = { [weak self] in
self?.searchBar.deactivate(clear: false)
self?.cancel()
}
self.searchBar.textUpdated = { [weak self] query, _ in
self?.queryUpdated?(query)
}
updateActivity({ [weak self] value in
self?.activity = value
})
self.updatePlaceholder()
}
func setQueryUpdated(_ f: @escaping (String) -> Void) {
self.queryUpdated = f
}
func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), strings: self.strings)
self.updatePlaceholder()
}
func updatePlaceholder() {
self.searchBar.placeholderString = NSAttributedString(string: self.strings.Common_Search, font: searchBarFont, textColor: self.theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
}
override var nominalHeight: CGFloat {
return 54.0
}
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
let searchBarFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - self.nominalHeight), size: CGSize(width: size.width, height: 54.0))
self.searchBar.frame = searchBarFrame
self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: leftInset, rightInset: rightInset, transition: transition)
}
func activate() {
self.searchBar.activate()
}
func deactivate() {
self.searchBar.deactivate(clear: false)
}
}

View file

@ -14,6 +14,10 @@ private func fullEntityMediaPath(_ path: String) -> String {
}
public final class DrawingStickerEntity: DrawingEntity, Codable {
public enum DecodingError: Error {
case generic
}
public enum Content: Equatable {
public enum ImageType: Equatable {
case sticker
@ -262,7 +266,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable {
} else if let file = try container.decodeIfPresent(TelegramMediaFile.self, forKey: .videoFile) {
self.content = .video(file)
} else {
fatalError()
throw DrawingStickerEntity.DecodingError.generic
}
self.referenceDrawingSize = try container.decode(CGSize.self, forKey: .referenceDrawingSize)
self.position = try container.decode(CGPoint.self, forKey: .position)

View file

@ -414,6 +414,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
}, hideTranslationPanel: {
}, openPremiumGift: {
}, openPremiumRequiredForMessaging: {
}, openBoostToUnrestrict: {
}, updateHistoryFilter: { _ in
}, requestLayout: { _ in
}, chatController: {

View file

@ -728,6 +728,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}, hideTranslationPanel: {
}, openPremiumGift: {
}, openPremiumRequiredForMessaging: {
}, openBoostToUnrestrict: {
}, updateHistoryFilter: { _ in
}, requestLayout: { _ in
}, chatController: {

View file

@ -1461,11 +1461,24 @@ final class ShareWithPeersScreenComponent: Component {
}
if case .channels = component.stateContext.subject {
if case let .channel(channel) = peer, channel.addressName == nil, index == nil {
let title: String
let text: String
switch channel.info {
case .broadcast:
title = environment.strings.BoostGift_Channels_PrivateChannel_Title
text = environment.strings.BoostGift_Channels_PrivateChannel_Text
case .group:
//TODO:localize
title = "Group is Private"
text = "Are you sure you want to add a private group? Users won't be able to join it without an invite link."
}
let alertController = textAlertController(
context: component.context,
forceTheme: environment.theme,
title: environment.strings.BoostGift_Channels_PrivateChannel_Title,
text: environment.strings.BoostGift_Channels_PrivateChannel_Text,
title: title,
text: text,
actions: [
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: environment.strings.BoostGift_Channels_PrivateChannel_Add, action: {
@ -2382,9 +2395,10 @@ final class ShareWithPeersScreenComponent: Component {
subtitle = environment.strings.BoostGift_Subscribers_Subtitle("\(10)").string
actionButtonTitle = environment.strings.BoostGift_Subscribers_Save
case .channels:
title = environment.strings.BoostGift_Channels_Title
subtitle = environment.strings.BoostGift_Channels_Subtitle("\(component.context.userLimits.maxGiveawayChannelsCount)").string
actionButtonTitle = environment.strings.BoostGift_Channels_Save
//TODO:localize
title = "Add Groups or Channels"// environment.strings.BoostGift_Channels_Title
subtitle = "select up to \(component.context.userLimits.maxGiveawayChannelsCount) groups or channels" //environment.strings.BoostGift_Channels_Subtitle("\(component.context.userLimits.maxGiveawayChannelsCount)").string
actionButtonTitle = "Save Groups and Channels" // environment.strings.BoostGift_Channels_Save
}
let titleComponent: AnyComponent<Empty>

View file

@ -640,7 +640,7 @@ public extension ShareWithPeersScreen {
}
for item in searchResults {
if let peer = item.peer, case let .channel(channel) = peer, case .broadcast = channel.info {
if let peer = item.peer, case .channel = peer {
selectedPeers.append(peer)
existingIds.insert(peer.id)
}
@ -672,7 +672,7 @@ public extension ShareWithPeersScreen {
if self.initialPeerIds.contains(peer.id) {
return false
}
if case let .channel(channel) = peer, case .broadcast = channel.info {
if case .channel = peer {
return true
}
return false

View file

@ -292,6 +292,7 @@ public class ImmediateTextNodeWithEntities: TextNode {
public var displaySpoilers = false
public var displaySpoilerEffect = true
public var spoilerColor: UIColor = .black
public var balancedTextLayout: Bool = false
private var enableLooping: Bool = true

View file

@ -621,7 +621,7 @@ public class VideoMessageCameraScreen: ViewController {
self.previewContainerView = UIView()
self.previewContainerView.clipsToBounds = true
let isDualCameraEnabled = Camera.isDualCameraSupported
let isDualCameraEnabled = Camera.isDualCameraSupported(forRoundVideo: true)
let isFrontPosition = "".isEmpty
self.mainPreviewView = CameraSimplePreviewView(frame: .zero, main: true, roundVideo: true)

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "boosts.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,100 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 28.934570 23.770996 cm
0.000000 0.000000 0.000000 scn
19.893095 16.420483 m
19.893103 16.420439 19.893110 16.420393 19.893118 16.420349 c
24.322737 22.894407 l
25.011452 23.900990 24.290668 25.267513 23.071022 25.267513 c
16.783052 25.267513 l
16.020958 25.267513 15.406286 25.824291 15.287010 26.530622 c
15.286899 26.530460 l
15.260291 26.687939 15.258309 26.852856 15.284810 27.020691 c
17.311213 39.854584 l
17.563419 41.451893 15.474540 42.282173 14.561391 40.947567 c
0.267549 20.056564 l
-0.421166 19.049982 0.299617 17.683458 1.519263 17.683458 c
7.807235 17.683458 l
8.739199 17.683458 9.450692 16.850807 9.305341 15.930248 c
7.278937 3.096359 l
7.026731 1.499050 9.115610 0.668770 10.028760 2.003372 c
19.893095 16.420483 l
h
19.104115 28.767513 m
19.790094 33.112053 l
25.151236 40.947567 l
26.064384 42.282173 28.153263 41.451893 27.901056 39.854580 c
26.002724 27.831802 l
25.198483 28.413969 24.199286 28.767513 23.071022 28.767513 c
19.104115 28.767513 l
h
27.211313 20.918013 m
28.156090 22.298841 28.298967 23.884453 27.854807 25.267483 c
33.660732 25.267483 l
34.880375 25.267483 35.601158 23.900959 34.912445 22.894377 c
20.618603 2.003372 l
19.705454 0.668770 17.616575 1.499050 17.868782 3.096359 c
18.724150 8.513695 l
27.211313 20.918013 l
h
f*
n
Q
endstream
endobj
3 0 obj
1339
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 90.000000 90.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001429 00000 n
0000001452 00000 n
0000001625 00000 n
0000001699 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1758
%%EOF

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "lastseen_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,169 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.320312 4.036133 cm
0.000000 0.000000 0.000000 scn
15.718013 7.249816 m
15.405374 7.990487 12.549557 9.993635 11.723054 10.108183 c
11.210857 10.179170 10.094700 8.757028 9.820968 7.139155 c
9.652993 6.146357 9.900538 5.153749 10.575783 4.550840 c
12.351411 2.965429 16.030653 6.509145 15.718013 7.249816 c
h
20.036879 19.735321 m
18.253841 20.338758 14.037626 18.223207 12.869061 12.033148 c
12.869061 11.732358 15.300022 9.989953 16.974861 9.388252 c
17.829952 9.081054 20.971378 12.265821 21.642756 15.454392 c
22.042732 17.354000 20.948334 19.426855 20.036879 19.735321 c
h
5.331334 5.154034 m
4.841030 5.573311 1.180003 6.640569 0.478038 6.303137 c
-0.223926 5.965705 -0.489510 1.657463 2.111791 1.081186 c
4.713092 0.504911 5.821639 4.734756 5.331334 5.154034 c
h
1.053483 8.698494 m
1.543788 8.279216 5.287134 6.983948 5.989099 7.321380 c
6.691063 7.658812 11.170075 16.921753 6.587785 17.884901 c
5.138152 18.189598 2.305758 16.301899 1.450079 13.825531 c
0.615815 11.411140 0.811438 8.905476 1.053483 8.698494 c
h
f*
n
Q
endstream
endobj
2 0 obj
1098
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000001356 00000 n
0000001379 00000 n
0000002571 00000 n
0000002593 00000 n
0000002891 00000 n
0000002993 00000 n
0000003014 00000 n
0000003187 00000 n
0000003261 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
3321
%%EOF

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "messageprivacy_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,185 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.000000 4.484375 cm
0.000000 0.000000 0.000000 scn
10.000000 20.135742 m
15.522848 20.135742 20.000000 16.065603 20.000000 11.044833 c
20.000000 6.024063 15.522848 1.953924 10.000000 1.953924 c
9.153261 1.953924 8.331102 2.049595 7.545889 2.229696 c
7.397357 2.263765 7.228708 2.107983 6.947171 1.847927 c
6.606689 1.533424 6.101101 1.066412 5.266314 0.598253 c
4.199766 0.000120 2.722059 0.052011 2.471971 0.156912 c
2.232201 0.257484 2.416753 0.457399 2.741760 0.809465 c
2.966608 1.053034 3.258681 1.369423 3.523984 1.776117 c
4.172771 2.770672 3.904685 3.954702 3.613619 4.167799 c
1.337573 5.834144 0.000000 8.181331 0.000000 11.044833 c
0.000000 16.065603 4.477152 20.135742 10.000000 20.135742 c
h
6.335000 14.010747 m
6.335000 16.034870 7.975876 17.675747 10.000000 17.675747 c
12.024124 17.675747 13.665000 16.034870 13.665000 14.010747 c
13.665000 12.722709 l
14.121655 12.482201 14.492952 12.106080 14.727516 11.645723 c
15.000000 11.110944 15.000000 10.410878 15.000000 9.010747 c
15.000000 7.610616 15.000000 6.910550 14.727516 6.375771 c
14.487833 5.905365 14.105381 5.522914 13.634976 5.283231 c
13.100197 5.010747 12.400131 5.010747 11.000000 5.010747 c
9.000000 5.010747 l
7.599869 5.010747 6.899803 5.010747 6.365024 5.283231 c
5.894619 5.522914 5.512167 5.905365 5.272484 6.375771 c
5.000000 6.910550 5.000000 7.610616 5.000000 9.010747 c
5.000000 10.410878 5.000000 11.110944 5.272484 11.645723 c
5.507047 12.106080 5.878345 12.482201 6.335000 12.722709 c
6.335000 14.010747 l
h
12.335000 14.010747 m
12.335000 12.995256 l
11.973238 13.010747 11.538372 13.010747 11.000000 13.010747 c
9.000000 13.010747 l
8.461628 13.010747 8.026762 13.010747 7.665000 12.995256 c
7.665000 14.010747 l
7.665000 15.300332 8.710415 16.345747 10.000000 16.345747 c
11.289585 16.345747 12.335000 15.300332 12.335000 14.010747 c
h
f*
n
Q
endstream
endobj
2 0 obj
1905
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000002163 00000 n
0000002186 00000 n
0000003378 00000 n
0000003400 00000 n
0000003698 00000 n
0000003800 00000 n
0000003821 00000 n
0000003994 00000 n
0000004068 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
4128
%%EOF

File diff suppressed because it is too large Load diff

View file

@ -3381,6 +3381,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
let effectiveInputText = effectivePresentationInterfaceState.interfaceState.composeInputState.inputText
let peerSpecificEmojiPack = (self.controller?.peerView?.cachedData as? CachedChannelData)?.emojiPack
var inlineStickers: [MediaId: Media] = [:]
var firstLockedPremiumEmoji: TelegramMediaFile?
var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:]
@ -3391,7 +3393,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if let packId = value.interactivelySelectedFromPackId {
bubbleUpEmojiOrStickersetsById[file.fileId.id] = packId
}
if file.isPremiumEmoji && !self.chatPresentationInterfaceState.isPremium && self.chatPresentationInterfaceState.chatLocation.peerId != self.context.account.peerId {
var isPeerSpecific = false
for attribute in file.attributes {
if case let .CustomEmoji(_, _, _, packReference) = attribute, case let .id(id, _) = packReference {
isPeerSpecific = id == peerSpecificEmojiPack?.id.id
}
}
if file.isPremiumEmoji && !self.chatPresentationInterfaceState.isPremium && self.chatPresentationInterfaceState.chatLocation.peerId != self.context.account.peerId && !isPeerSpecific {
if firstLockedPremiumEmoji == nil {
firstLockedPremiumEmoji = file
}

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@ import TelegramPresentationData
import ChatInputPanelNode
final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
private let buttonNode: HighlightTrackingButtonNode
private let textNode: ImmediateTextNode
private var iconView: UIImageView?
@ -21,9 +22,34 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
self.textNode.maximumNumberOfLines = 2
self.textNode.textAlignment = .center
self.buttonNode = HighlightTrackingButtonNode()
self.buttonNode.isUserInteractionEnabled = false
super.init()
self.addSubnode(self.textNode)
self.addSubnode(self.buttonNode)
self.buttonNode.highligthedChanged = { [weak self] highlighted in
if let self {
if highlighted {
self.iconView?.layer.removeAnimation(forKey: "opacity")
self.iconView?.alpha = 0.4
self.textNode.layer.removeAnimation(forKey: "opacity")
self.textNode.alpha = 0.4
} else {
self.iconView?.alpha = 1.0
self.iconView?.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
self.textNode.alpha = 1.0
self.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
}
}
}
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
}
@objc private func buttonPressed() {
self.interfaceInteraction?.openBoostToUnrestrict()
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat {
@ -45,6 +71,8 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
}
var iconImage: UIImage?
var iconSpacing: CGFloat = 4.0
var isUserInteractionEnabled = false
if case let .replyThread(message) = interfaceState.chatLocation, message.peerId == self.context?.account.peerId {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelStatusAuthorHidden, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
@ -63,17 +91,25 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
} else if personal {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_RestrictedText, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
} else {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_DefaultRestrictedText, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
if "".isEmpty {
//TODO:localize
iconSpacing = 0.0
iconImage = PresentationResourcesChat.chatPanelBoostIcon(interfaceState.theme)
self.textNode.attributedText = NSAttributedString(string: "Boost this group to send messages", font: Font.regular(15.0), textColor: interfaceState.theme.chat.inputPanel.panelControlAccentColor)
isUserInteractionEnabled = true
} else {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_DefaultRestrictedText, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
}
}
}
self.buttonNode.isUserInteractionEnabled = isUserInteractionEnabled
let panelHeight = defaultHeight(metrics: metrics)
let textSize = self.textNode.updateLayout(CGSize(width: width - leftInset - rightInset - 8.0 * 2.0, height: panelHeight))
let textFrame = CGRect(origin: CGPoint(x: leftInset + floor((width - leftInset - rightInset - textSize.width) / 2.0), y: floor((panelHeight - textSize.height) / 2.0)), size: textSize)
self.textNode.frame = textFrame
var originX: CGFloat = leftInset + floor((width - leftInset - rightInset - textSize.width) / 2.0)
if let iconImage = iconImage {
if let iconImage {
let iconView: UIImageView
if let current = self.iconView {
iconView = current
@ -83,12 +119,21 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
self.view.addSubview(iconView)
}
iconView.image = iconImage
iconView.frame = CGRect(origin: CGPoint(x: textFrame.minX - 4.0 - iconImage.size.width, y: textFrame.minY + UIScreenPixel + floorToScreenPixels((textFrame.height - iconImage.size.height) / 2.0)), size: iconImage.size)
let totalWidth = textSize.width + iconImage.size.width + iconSpacing
iconView.frame = CGRect(origin: CGPoint(x: leftInset + floor((width - leftInset - rightInset - totalWidth) / 2.0), y: floor((panelHeight - textSize.height) / 2.0) + UIScreenPixel + floorToScreenPixels((textSize.height - iconImage.size.height) / 2.0)), size: iconImage.size)
originX += iconImage.size.width + iconSpacing
} else if let iconView = self.iconView {
self.iconView = nil
iconView.removeFromSuperview()
}
let textFrame = CGRect(origin: CGPoint(x: originX, y: floor((panelHeight - textSize.height) / 2.0)), size: textSize)
self.textNode.frame = textFrame
self.buttonNode.frame = textFrame.insetBy(dx: -8.0, dy: -12.0)
return panelHeight
}

View file

@ -25,6 +25,7 @@ swift_library(
"//submodules/Markdown",
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
"//submodules/Components/BalancedTextComponent",
"//submodules/Components/MultilineTextWithEntitiesComponent",
],
visibility = [
"//visibility:public",

View file

@ -17,6 +17,7 @@ import AvatarStoryIndicatorComponent
import AccountContext
import Markdown
import BalancedTextComponent
import MultilineTextWithEntitiesComponent
public enum TooltipActiveTextItem {
case url(String, Bool)
@ -108,6 +109,8 @@ private class DownArrowsIconNode: ASDisplayNode {
}
private final class TooltipScreenNode: ViewControllerTracingNode {
private let context: AccountContext?
private let text: TooltipScreen.Text
private let textAlignment: TooltipScreen.Alignment
private let balancedTextLayout: Bool
@ -171,6 +174,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
cornerRadius: CGFloat? = nil,
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?)
{
self.context = context
self.tooltipStyle = style
self.arrowStyle = arrowStyle
self.icon = icon
@ -534,6 +538,8 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
}
)
attributedText = parseMarkdownIntoAttributedString(text, attributes: markdownAttributes)
case let .attributedString(text):
attributedText = text
}
let highlightColor: UIColor? = UIColor.white.withAlphaComponent(0.5)
@ -594,21 +600,44 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
}
}
let textSize = self.textView.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
text: .plain(attributedText),
balanced: self.balancedTextLayout,
horizontalAlignment: self.textAlignment == .center ? .center : .left,
maximumNumberOfLines: 0,
highlightColor: highlightColor,
highlightAction: highlightAction,
tapAction: tapAction,
longTapAction: longTapAction
)),
environment: {},
containerSize: CGSize(width: containerWidth - contentInset * 2.0 - animationSize.width - animationSpacing - buttonInset, height: 1000000.0)
)
let textSize: CGSize
if case .attributedString = self.text, let context = self.context {
textSize = self.textView.update(
transition: .immediate,
component: AnyComponent(MultilineTextWithEntitiesComponent(
context: context,
animationCache: context.animationCache,
animationRenderer: context.animationRenderer,
placeholderColor: UIColor(rgb: 0xffffff, alpha: 0.4),
text: .plain(attributedText),
horizontalAlignment: self.textAlignment == .center ? .center : .left,
truncationType: .end,
maximumNumberOfLines: 3,
lineSpacing: 0.2,
highlightAction: nil,
tapAction: { _, _ in
}
)),
environment: {},
containerSize: CGSize(width: containerWidth - contentInset * 2.0 - animationSize.width - animationSpacing - buttonInset, height: 1000000.0)
)
} else {
textSize = self.textView.update(
transition: .immediate,
component: AnyComponent(BalancedTextComponent(
text: .plain(attributedText),
balanced: self.balancedTextLayout,
horizontalAlignment: self.textAlignment == .center ? .center : .left,
maximumNumberOfLines: 0,
highlightColor: highlightColor,
highlightAction: highlightAction,
tapAction: tapAction,
longTapAction: longTapAction
)),
environment: {},
containerSize: CGSize(width: containerWidth - contentInset * 2.0 - animationSize.width - animationSpacing - buttonInset, height: 1000000.0)
)
}
var backgroundFrame: CGRect
@ -941,6 +970,7 @@ public final class TooltipScreen: ViewController {
case plain(text: String)
case entities(text: String, entities: [MessageTextEntity])
case markdown(text: String)
case attributedString(text: NSAttributedString)
}
public class Action {