mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Group boosts
This commit is contained in:
parent
cd7c9ea73c
commit
971b4d6986
@ -24,8 +24,9 @@ private final class ChannelAdminsControllerArguments {
|
||||
let addAdmin: () -> Void
|
||||
let openAdmin: (ChannelParticipant) -> Void
|
||||
let updateAntiSpamEnabled: (Bool) -> Void
|
||||
let updateSignMessagesEnabled: (Bool) -> Void
|
||||
|
||||
init(context: AccountContext, openRecentActions: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removeAdmin: @escaping (EnginePeer.Id) -> Void, addAdmin: @escaping () -> Void, openAdmin: @escaping (ChannelParticipant) -> Void, updateAntiSpamEnabled: @escaping (Bool) -> Void) {
|
||||
init(context: AccountContext, openRecentActions: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removeAdmin: @escaping (EnginePeer.Id) -> Void, addAdmin: @escaping () -> Void, openAdmin: @escaping (ChannelParticipant) -> Void, updateAntiSpamEnabled: @escaping (Bool) -> Void, updateSignMessagesEnabled: @escaping (Bool) -> Void) {
|
||||
self.context = context
|
||||
self.openRecentActions = openRecentActions
|
||||
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
||||
@ -33,12 +34,14 @@ private final class ChannelAdminsControllerArguments {
|
||||
self.addAdmin = addAdmin
|
||||
self.openAdmin = openAdmin
|
||||
self.updateAntiSpamEnabled = updateAntiSpamEnabled
|
||||
self.updateSignMessagesEnabled = updateSignMessagesEnabled
|
||||
}
|
||||
}
|
||||
|
||||
private enum ChannelAdminsSection: Int32 {
|
||||
case administration
|
||||
case admins
|
||||
case signMessages
|
||||
}
|
||||
|
||||
private enum ChannelAdminsEntryStableId: Hashable {
|
||||
@ -56,31 +59,40 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
case addAdmin(PresentationTheme, String, Bool)
|
||||
case adminsInfo(PresentationTheme, String)
|
||||
|
||||
case signMessages(PresentationTheme, String, Bool)
|
||||
case signMessagesInfo(PresentationTheme, String)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
case .recentActions, .antiSpam, .antiSpamInfo:
|
||||
return ChannelAdminsSection.administration.rawValue
|
||||
case .adminsHeader, .adminPeerItem, .addAdmin, .adminsInfo:
|
||||
return ChannelAdminsSection.admins.rawValue
|
||||
case .recentActions, .antiSpam, .antiSpamInfo:
|
||||
return ChannelAdminsSection.administration.rawValue
|
||||
case .adminsHeader, .adminPeerItem, .addAdmin, .adminsInfo:
|
||||
return ChannelAdminsSection.admins.rawValue
|
||||
case .signMessages, .signMessagesInfo:
|
||||
return ChannelAdminsSection.signMessages.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
var stableId: ChannelAdminsEntryStableId {
|
||||
switch self {
|
||||
case .recentActions:
|
||||
return .index(0)
|
||||
case .antiSpam:
|
||||
return .index(1)
|
||||
case .antiSpamInfo:
|
||||
return .index(2)
|
||||
case .adminsHeader:
|
||||
return .index(3)
|
||||
case .addAdmin:
|
||||
return .index(4)
|
||||
case .adminsInfo:
|
||||
return .index(5)
|
||||
case let .adminPeerItem(_, _, _, _, _, _, participant, _, _, _):
|
||||
return .peer(participant.peer.id)
|
||||
case .recentActions:
|
||||
return .index(0)
|
||||
case .antiSpam:
|
||||
return .index(1)
|
||||
case .antiSpamInfo:
|
||||
return .index(2)
|
||||
case .adminsHeader:
|
||||
return .index(3)
|
||||
case .addAdmin:
|
||||
return .index(4)
|
||||
case .adminsInfo:
|
||||
return .index(5)
|
||||
case let .adminPeerItem(_, _, _, _, _, _, participant, _, _, _):
|
||||
return .peer(participant.peer.id)
|
||||
case .signMessages:
|
||||
return .index(6)
|
||||
case .signMessagesInfo:
|
||||
return .index(7)
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +170,18 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .signMessages(lhsTheme, lhsText, lhsValue):
|
||||
if case let .signMessages(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .signMessagesInfo(lhsTheme, lhsText):
|
||||
if case let .signMessagesInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +227,26 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
return true
|
||||
}
|
||||
case .adminsInfo:
|
||||
return false
|
||||
switch rhs {
|
||||
case .recentActions, .antiSpam, .antiSpamInfo, .adminsHeader, .addAdmin, .adminsInfo:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .signMessages:
|
||||
switch rhs {
|
||||
case .recentActions, .antiSpam, .antiSpamInfo, .adminsHeader, .addAdmin, .adminsInfo, .signMessages:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .signMessagesInfo:
|
||||
switch rhs {
|
||||
case .recentActions, .antiSpam, .antiSpamInfo, .adminsHeader, .addAdmin, .adminsInfo, .signMessages, .signMessagesInfo:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,6 +302,12 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
})
|
||||
case let .adminsInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .signMessages(_, text, value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.updateSignMessagesEnabled(value)
|
||||
})
|
||||
case let .signMessagesInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,7 +386,7 @@ private struct ChannelAdminsControllerState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func channelAdminsControllerEntries(presentationData: PresentationData, accountPeerId: EnginePeer.Id, peer: EnginePeer?, state: ChannelAdminsControllerState, participants: [RenderedChannelParticipant]?, antiSpamAvailable: Bool, antiSpamEnabled: Bool) -> [ChannelAdminsEntry] {
|
||||
private func channelAdminsControllerEntries(presentationData: PresentationData, accountPeerId: EnginePeer.Id, peer: EnginePeer?, state: ChannelAdminsControllerState, participants: [RenderedChannelParticipant]?, antiSpamAvailable: Bool, antiSpamEnabled: Bool, signMessagesEnabled: Bool) -> [ChannelAdminsEntry] {
|
||||
if participants == nil || participants?.count == nil {
|
||||
return []
|
||||
}
|
||||
@ -429,6 +478,11 @@ private func channelAdminsControllerEntries(presentationData: PresentationData,
|
||||
let info = isGroup ? presentationData.strings.Group_Management_AddModeratorHelp : presentationData.strings.Channel_Management_AddModeratorHelp
|
||||
entries.append(.adminsInfo(presentationData.theme, info))
|
||||
}
|
||||
|
||||
if !isGroup && peer.hasPermission(.sendSomething) {
|
||||
entries.append(.signMessages(presentationData.theme, presentationData.strings.Channel_SignMessages, signMessagesEnabled))
|
||||
entries.append(.signMessagesInfo(presentationData.theme, presentationData.strings.Channel_SignMessages_Help))
|
||||
}
|
||||
}
|
||||
} else if case let .legacyGroup(peer) = peer {
|
||||
let isGroup = true
|
||||
@ -536,6 +590,9 @@ public func channelAdminsController(context: AccountContext, updatedPresentation
|
||||
let updateAntiSpamDisposable = MetaDisposable()
|
||||
actionsDisposable.add(updateAntiSpamDisposable)
|
||||
|
||||
let updateSignMessagesDisposable = MetaDisposable()
|
||||
actionsDisposable.add(updateSignMessagesDisposable)
|
||||
|
||||
let adminsPromise = Promise<[RenderedChannelParticipant]?>(nil)
|
||||
|
||||
let antiSpamConfiguration = AntiSpamBotConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||
@ -732,6 +789,12 @@ public func channelAdminsController(context: AccountContext, updatedPresentation
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
updateAntiSpamDisposable.set(context.engine.peers.toggleAntiSpamProtection(peerId: peerId, enabled: value).start())
|
||||
})
|
||||
}, updateSignMessagesEnabled: { value in
|
||||
let _ = (currentPeerId.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
updateSignMessagesDisposable.set(context.engine.peers.toggleShouldChannelMessagesSignatures(peerId: peerId, enabled: value).start())
|
||||
})
|
||||
})
|
||||
|
||||
let membersAndLoadMoreControlValue = Atomic<(Disposable, PeerChannelMemberCategoryControl?)?>(value: nil)
|
||||
@ -852,6 +915,11 @@ public func channelAdminsController(context: AccountContext, updatedPresentation
|
||||
antiSpamAvailable = true
|
||||
}
|
||||
|
||||
var signMessagesEnabled = false
|
||||
if case let .channel(channel) = view.peer, case let .broadcast(info) = channel.info {
|
||||
signMessagesEnabled = info.flags.contains(.messagesShouldHaveSignatures)
|
||||
}
|
||||
|
||||
var rightNavigationButton: ItemListNavigationButton?
|
||||
var secondaryRightNavigationButton: ItemListNavigationButton?
|
||||
if let admins = admins, admins.count > 1 {
|
||||
@ -923,7 +991,7 @@ public func channelAdminsController(context: AccountContext, updatedPresentation
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(isGroup ? presentationData.strings.ChatAdmins_Title : presentationData.strings.Channel_Management_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminsControllerEntries(presentationData: presentationData, accountPeerId: context.account.peerId, peer: view.peer, state: state, participants: admins, antiSpamAvailable: antiSpamAvailable, antiSpamEnabled: antiSpamEnabled), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && admins != nil && previous!.count >= admins!.count)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminsControllerEntries(presentationData: presentationData, accountPeerId: context.account.peerId, peer: view.peer, state: state, participants: admins, antiSpamAvailable: antiSpamAvailable, antiSpamEnabled: antiSpamEnabled, signMessagesEnabled: signMessagesEnabled), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && admins != nil && previous!.count >= admins!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -59,6 +59,7 @@ public enum PresentationResourceKey: Int32 {
|
||||
case itemListVerifiedPeerIcon
|
||||
case itemListCloudFetchIcon
|
||||
case itemListCloseIconImage
|
||||
case itemListRemoveIconImage
|
||||
case itemListMakeVisibleIcon
|
||||
case itemListMakeInvisibleIcon
|
||||
case itemListEditThemeIcon
|
||||
|
@ -211,6 +211,24 @@ public struct PresentationResourcesItemList {
|
||||
})
|
||||
}
|
||||
|
||||
public static func itemListRemoveIconImage(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.itemListRemoveIconImage.rawValue, { theme in
|
||||
return generateImage(CGSize(width: 15.0, height: 15.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setBlendMode(.copy)
|
||||
context.setStrokeColor(theme.list.disclosureArrowColor.cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
context.setLineCap(.round)
|
||||
context.move(to: CGPoint(x: 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
context.move(to: CGPoint(x: size.width - 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public static func makeVisibleIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.itemListMakeVisibleIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Contact List/MakeVisibleIcon"), color: theme.list.itemAccentColor)
|
||||
|
@ -180,6 +180,7 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
||||
self.addSubnode(self.notFoundNode)
|
||||
self.addSubnode(self.activityIndicator)
|
||||
|
||||
self.addSubnode(self.removeButtonIcon)
|
||||
self.addSubnode(self.removeButton)
|
||||
|
||||
var firstTime = true
|
||||
@ -195,12 +196,29 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
firstTime = false
|
||||
}
|
||||
|
||||
self.removeButton.addTarget(self, action: #selector(self.removeButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.removeButton.highligthedChanged = { [weak self] highlighted in
|
||||
if let self {
|
||||
if highlighted {
|
||||
self.removeButtonIcon.layer.removeAnimation(forKey: "opacity")
|
||||
self.removeButtonIcon.alpha = 0.4
|
||||
} else {
|
||||
self.removeButtonIcon.alpha = 1.0
|
||||
self.removeButtonIcon.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.fetchDisposable.dispose()
|
||||
}
|
||||
|
||||
@objc private func removeButtonPressed() {
|
||||
self.item?.remove?()
|
||||
}
|
||||
|
||||
private func removePlaceholder(animated: Bool) {
|
||||
if let placeholderNode = self.placeholderNode {
|
||||
self.placeholderNode = nil
|
||||
@ -330,6 +348,14 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.activityIndicator.isHidden = true
|
||||
}
|
||||
|
||||
if case .found = item.content {
|
||||
strongSelf.removeButtonIcon.isHidden = false
|
||||
strongSelf.removeButton.isHidden = false
|
||||
} else {
|
||||
strongSelf.removeButtonIcon.isHidden = true
|
||||
strongSelf.removeButton.isHidden = true
|
||||
}
|
||||
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
|
||||
let transition: ContainedViewLayoutTransition = .immediate
|
||||
@ -377,6 +403,7 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.removeButtonIcon.image = PresentationResourcesItemList.itemListRemoveIconImage(item.theme)
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -403,17 +430,16 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: strongSelf.notFoundNode, frame: CGRect(origin: CGPoint(x: params.leftInset + 15.0 + floor((boundingSize.width - image.size.width) / 2.0), y: 13.0 + floor((boundingSize.height - image.size.height) / 2.0)), size: image.size))
|
||||
}
|
||||
|
||||
|
||||
|
||||
if let updatedImageSignal = updatedImageSignal {
|
||||
strongSelf.imageNode.setSignal(updatedImageSignal)
|
||||
}
|
||||
let imageFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0 + floor((boundingSize.width - imageSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame)
|
||||
|
||||
|
||||
|
||||
|
||||
strongSelf.removeButton.frame = CGRect(origin: CGPoint(x: layoutSize.width - params.rightInset - layoutSize.height, y: 0.0), size: CGSize(width: layoutSize.height, height: layoutSize.height))
|
||||
if let icon = strongSelf.removeButtonIcon.image {
|
||||
strongSelf.removeButtonIcon.frame = CGRect(origin: CGPoint(x: layoutSize.width - params.rightInset - icon.size.width - 18.0, y: floor((layoutSize.height - icon.size.height) / 2.0)), size: icon.size)
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
|
||||
|
@ -1588,18 +1588,16 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
case .broadcast:
|
||||
let ItemUsername = 1
|
||||
let ItemPeerColor = 2
|
||||
let ItemInviteLinks = 4
|
||||
let ItemDiscussionGroup = 5
|
||||
let ItemSignMessages = 6
|
||||
let ItemSignMessagesHelp = 7
|
||||
let ItemDeleteChannel = 8
|
||||
let ItemReactions = 9
|
||||
let ItemAdmins = 10
|
||||
let ItemMembers = 11
|
||||
let ItemMemberRequests = 12
|
||||
let ItemStats = 13
|
||||
let ItemBanned = 14
|
||||
let ItemRecentActions = 15
|
||||
let ItemInviteLinks = 3
|
||||
let ItemDiscussionGroup = 4
|
||||
let ItemDeleteChannel = 5
|
||||
let ItemReactions = 6
|
||||
let ItemAdmins = 7
|
||||
let ItemMembers = 8
|
||||
let ItemMemberRequests = 9
|
||||
let ItemStats = 10
|
||||
let ItemBanned = 11
|
||||
let ItemRecentActions = 12
|
||||
|
||||
let isCreator = channel.flags.contains(.isCreator)
|
||||
|
||||
@ -1708,19 +1706,19 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
}))
|
||||
}
|
||||
|
||||
if isCreator || (channel.adminRights != nil && channel.hasPermission(.sendSomething)) {
|
||||
let messagesShouldHaveSignatures: Bool
|
||||
switch channel.info {
|
||||
case let .broadcast(info):
|
||||
messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures)
|
||||
default:
|
||||
messagesShouldHaveSignatures = false
|
||||
}
|
||||
items[.peerSettings]!.append(PeerInfoScreenSwitchItem(id: ItemSignMessages, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures, icon: UIImage(bundleImageName: "Chat/Info/GroupSignIcon"), toggled: { value in
|
||||
interaction.editingToggleMessageSignatures(value)
|
||||
}))
|
||||
items[.peerSettings]!.append(PeerInfoScreenCommentItem(id: ItemSignMessagesHelp, text: presentationData.strings.Channel_SignMessages_Help))
|
||||
}
|
||||
// if isCreator || (channel.adminRights != nil && channel.hasPermission(.sendSomething)) {
|
||||
// let messagesShouldHaveSignatures: Bool
|
||||
// switch channel.info {
|
||||
// case let .broadcast(info):
|
||||
// messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures)
|
||||
// default:
|
||||
// messagesShouldHaveSignatures = false
|
||||
// }
|
||||
// items[.peerSettings]!.append(PeerInfoScreenSwitchItem(id: ItemSignMessages, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures, icon: UIImage(bundleImageName: "Chat/Info/GroupSignIcon"), toggled: { value in
|
||||
// interaction.editingToggleMessageSignatures(value)
|
||||
// }))
|
||||
// items[.peerSettings]!.append(PeerInfoScreenCommentItem(id: ItemSignMessagesHelp, text: presentationData.strings.Channel_SignMessages_Help))
|
||||
// }
|
||||
|
||||
var canEditMembers = false
|
||||
if channel.hasPermission(.banMembers) && (channel.adminRights != nil || channel.flags.contains(.isCreator)) {
|
||||
|
@ -10800,8 +10800,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
items.append(.custom(ChatSendAsPeerTitleContextItem(text: strongSelf.presentationInterfaceState.strings.Conversation_SendMesageAs.uppercased()), false))
|
||||
items.append(.custom(ChatSendAsPeerListContextItem(context: strongSelf.context, chatPeerId: peerId, peers: peers, selectedPeerId: myPeerId, isPremium: isPremium, presentToast: { [weak self] peer in
|
||||
if let strongSelf = self {
|
||||
let hapticFeedback = HapticFeedback()
|
||||
hapticFeedback.impact()
|
||||
HapticFeedback().impact()
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.Conversation_SendMesageAsPremiumInfo, action: strongSelf.presentationData.strings.EmojiInput_PremiumEmojiToast_Action, duration: 3), elevatedLayout: false, action: { [weak self] action in
|
||||
guard let strongSelf = self else {
|
||||
@ -11075,6 +11074,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let self, let peerId = self.chatLocation.peerId, let cachedData = self.peerView?.cachedData as? CachedChannelData, let boostToUnrestrict = cachedData.boostsToUnrestrict else {
|
||||
return
|
||||
}
|
||||
|
||||
HapticFeedback().impact()
|
||||
|
||||
let _ = combineLatest(queue: Queue.mainQueue(),
|
||||
context.engine.peers.getChannelBoostStatus(peerId: peerId),
|
||||
context.engine.peers.getMyBoostStatus()
|
||||
|
@ -4703,6 +4703,7 @@ private func generateClearImage(color: UIColor) -> UIImage? {
|
||||
|
||||
|
||||
private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
||||
let containerNode: ASDisplayNode
|
||||
let backgroundNode: ASImageNode
|
||||
let textNode: ImmediateAnimatedCountLabelNode
|
||||
let iconNode: ASImageNode
|
||||
@ -4712,6 +4713,8 @@ private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
||||
var requestUpdate: () -> Void = {}
|
||||
|
||||
override init(pointerStyle: PointerStyle? = nil) {
|
||||
self.containerNode = ASDisplayNode()
|
||||
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.clipsToBounds = true
|
||||
@ -4727,9 +4730,20 @@ private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
||||
|
||||
super.init(pointerStyle: pointerStyle)
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.containerNode)
|
||||
self.containerNode.addSubnode(self.backgroundNode)
|
||||
self.containerNode.addSubnode(self.iconNode)
|
||||
self.containerNode.addSubnode(self.textNode)
|
||||
|
||||
self.highligthedChanged = { [weak self] highlighted in
|
||||
if let self {
|
||||
if highlighted {
|
||||
self.containerNode.layer.animateScale(from: 1.0, to: 0.75, duration: 0.4, removeOnCompletion: false)
|
||||
} else if let presentationLayer = self.containerNode.layer.presentation() {
|
||||
self.containerNode.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, interfaceState: ChatPresentationInterfaceState) -> CGSize {
|
||||
@ -4778,6 +4792,8 @@ private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
||||
let textSize = self.textNode.updateLayout(size: CGSize(width: 200.0, height: 100.0), animated: true)
|
||||
let totalSize = CGSize(width: textSize.width > 0.0 ? textSize.width + 38.0 : 33.0, height: 33.0)
|
||||
|
||||
self.containerNode.bounds = CGRect(origin: .zero, size: totalSize)
|
||||
self.containerNode.position = CGPoint(x: totalSize.width / 2.0, y: totalSize.height / 2.0)
|
||||
self.backgroundNode.frame = CGRect(origin: .zero, size: totalSize)
|
||||
self.backgroundNode.cornerRadius = totalSize.height / 2.0
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: 9.0, y: floorToScreenPixels((totalSize.height - textSize.height) / 2.0)), size: textSize)
|
||||
|
Loading…
x
Reference in New Issue
Block a user