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
cad0d5f360
commit
b938726fb8
@ -11101,8 +11101,6 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Notification.GiveawayStartedGroup" = "%1$@ just started a giveaway of Telegram Premium subscriptions for its members.";
|
"Notification.GiveawayStartedGroup" = "%1$@ just started a giveaway of Telegram Premium subscriptions for its members.";
|
||||||
|
|
||||||
"Chat.Giveaway.Message.Group.Participants" = "All subscribers of this group:";
|
|
||||||
|
|
||||||
"Chat.Giveaway.Info.Group.RandomMembers_1" = "**%@** random member";
|
"Chat.Giveaway.Info.Group.RandomMembers_1" = "**%@** random member";
|
||||||
"Chat.Giveaway.Info.Group.RandomMembers_any" = "**%@** random members";
|
"Chat.Giveaway.Info.Group.RandomMembers_any" = "**%@** random members";
|
||||||
|
|
||||||
@ -11238,3 +11236,25 @@ Sorry for the inconvenience.";
|
|||||||
"GroupBoost.Error.PremiumNeededText" = "Only **Telegram Premium** subscribers can boost groups. Do you want to subscribe to **Telegram Premium**?";
|
"GroupBoost.Error.PremiumNeededText" = "Only **Telegram Premium** subscribers can boost groups. Do you want to subscribe to **Telegram Premium**?";
|
||||||
|
|
||||||
"Notification.GroupChangedWallpaper" = "Group set a new wallpaper";
|
"Notification.GroupChangedWallpaper" = "Group set a new wallpaper";
|
||||||
|
"Notification.YouChangedGroupWallpaper" = "You set a new wallpaper for this group";
|
||||||
|
|
||||||
|
"WallpaperPreview.GroupHeader" = "All members will see this wallpaper";
|
||||||
|
|
||||||
|
"GroupBoost.BoostGroup" = "Boost Group";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.NotAllowedAdminGroup" = "You are not eligible to participate in this giveaway, because you are an admin of participating group (**%@**).";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Message.Group.Participants" = "All members of this group:";
|
||||||
|
"Chat.Giveaway.Message.Group.ParticipantsNew" = "All users who join this group after this date:";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Message.Group.ParticipantsMany" = "All subscribers of the channels below:";
|
||||||
|
"Chat.Giveaway.Message.Group.ParticipantsNewMany" = "All users who join the groups below after this date:";
|
||||||
|
|
||||||
|
"Story.Privacy.KeepOnGroupPage" = "Post to Group Page";
|
||||||
|
"Story.Privacy.KeepOnGroupPageInfo" = "Keep this story on group page even after it expires in %@.";
|
||||||
|
"Story.Privacy.TooltipStoryArchivedGroup" = "Users will see this story on the group page even after it expires.";
|
||||||
|
|
||||||
|
"BoostGift.Members.Subtitle" = "select up to %@ members";
|
||||||
|
"BoostGift.Members.SectionTitle" = "MEMBERS";
|
||||||
|
"BoostGift.Members.Search" = "Search Members";
|
||||||
|
"BoostGift.Members.MaximumReached" = "You can select maximum %@ members.";
|
||||||
|
@ -11,7 +11,7 @@ import PresentationDataUtils
|
|||||||
final class MediaPickerPlaceholderNode: ASDisplayNode {
|
final class MediaPickerPlaceholderNode: ASDisplayNode {
|
||||||
enum Content {
|
enum Content {
|
||||||
case intro(story: Bool)
|
case intro(story: Bool)
|
||||||
case bannedSendMedia(String)
|
case bannedSendMedia(text: String, canBoost: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
private let content: Content
|
private let content: Content
|
||||||
@ -147,7 +147,7 @@ final class MediaPickerPlaceholderNode: ASDisplayNode {
|
|||||||
case let .intro(story):
|
case let .intro(story):
|
||||||
title = strings.Attachment_MediaAccessTitle
|
title = strings.Attachment_MediaAccessTitle
|
||||||
text = story ? strings.Attachment_MediaAccessStoryText : strings.Attachment_MediaAccessText
|
text = story ? strings.Attachment_MediaAccessStoryText : strings.Attachment_MediaAccessText
|
||||||
case let .bannedSendMedia(banDescription):
|
case let .bannedSendMedia(banDescription, _):
|
||||||
title = ""
|
title = ""
|
||||||
text = banDescription
|
text = banDescription
|
||||||
}
|
}
|
||||||
|
@ -1308,6 +1308,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
if let (untilDate, personal) = bannedSendMedia {
|
if let (untilDate, personal) = bannedSendMedia {
|
||||||
self.gridNode.isHidden = true
|
self.gridNode.isHidden = true
|
||||||
|
self.controller?.titleView.isEnabled = false
|
||||||
|
|
||||||
let banDescription: String
|
let banDescription: String
|
||||||
if untilDate != 0 && untilDate != Int32.max {
|
if untilDate != 0 && untilDate != Int32.max {
|
||||||
@ -1323,7 +1324,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
if let current = self.placeholderNode {
|
if let current = self.placeholderNode {
|
||||||
placeholderNode = current
|
placeholderNode = current
|
||||||
} else {
|
} else {
|
||||||
placeholderNode = MediaPickerPlaceholderNode(content: .bannedSendMedia(banDescription))
|
placeholderNode = MediaPickerPlaceholderNode(content: .bannedSendMedia(text: banDescription, canBoost: false))
|
||||||
self.containerNode.insertSubnode(placeholderNode, aboveSubnode: self.gridNode)
|
self.containerNode.insertSubnode(placeholderNode, aboveSubnode: self.gridNode)
|
||||||
self.placeholderNode = placeholderNode
|
self.placeholderNode = placeholderNode
|
||||||
|
|
||||||
|
@ -1051,6 +1051,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
buyActionImpl = { [weak controller] in
|
buyActionImpl = { [weak controller] in
|
||||||
|
let isGroup = isGroupValue.with { $0 }
|
||||||
|
|
||||||
let state = stateValue.with { $0 }
|
let state = stateValue.with { $0 }
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
@ -1131,10 +1133,10 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
switch state.mode {
|
switch state.mode {
|
||||||
case .giveaway:
|
case .giveaway:
|
||||||
title = presentationData.strings.BoostGift_GiveawayCreated_Title
|
title = presentationData.strings.BoostGift_GiveawayCreated_Title
|
||||||
text = presentationData.strings.BoostGift_GiveawayCreated_Text
|
text = isGroup ? presentationData.strings.BoostGift_Group_GiveawayCreated_Text : presentationData.strings.BoostGift_GiveawayCreated_Text
|
||||||
case .gift:
|
case .gift:
|
||||||
title = presentationData.strings.BoostGift_PremiumGifted_Title
|
title = presentationData.strings.BoostGift_PremiumGifted_Title
|
||||||
text = presentationData.strings.BoostGift_PremiumGifted_Text
|
text = isGroup ? presentationData.strings.BoostGift_Group_PremiumGifted_Text : presentationData.strings.BoostGift_PremiumGifted_Text
|
||||||
}
|
}
|
||||||
|
|
||||||
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
||||||
@ -1224,11 +1226,11 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
openPeersSelectionImpl = {
|
openPeersSelectionImpl = {
|
||||||
|
let isGroup = isGroupValue.with { $0 }
|
||||||
let state = stateValue.with { $0 }
|
let state = stateValue.with { $0 }
|
||||||
|
|
||||||
let stateContext = ShareWithPeersScreen.StateContext(
|
let stateContext = ShareWithPeersScreen.StateContext(
|
||||||
context: context,
|
context: context,
|
||||||
subject: .members(peerId: peerId, searchQuery: nil),
|
subject: .members(isGroup: isGroup, peerId: peerId, searchQuery: nil),
|
||||||
initialPeerIds: Set(state.peers)
|
initialPeerIds: Set(state.peers)
|
||||||
)
|
)
|
||||||
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).startStandalone(next: { _ in
|
let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).startStandalone(next: { _ in
|
||||||
|
@ -35,15 +35,6 @@ public func presentGiveawayInfoController(
|
|||||||
let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway
|
let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway
|
||||||
let giveawayResults = message.media.first(where: { $0 is TelegramMediaGiveawayResults }) as? TelegramMediaGiveawayResults
|
let giveawayResults = message.media.first(where: { $0 is TelegramMediaGiveawayResults }) as? TelegramMediaGiveawayResults
|
||||||
|
|
||||||
// var channelPeerId: EnginePeer.Id?
|
|
||||||
// if let giveaway {
|
|
||||||
// if let peerId = giveaway.channelPeerIds.first {
|
|
||||||
// channelPeerId = peerId
|
|
||||||
// }
|
|
||||||
// } else if let _ = giveawayResults {
|
|
||||||
// channelPeerId = message.author?.id
|
|
||||||
// }
|
|
||||||
|
|
||||||
var quantity: Int32 = 0
|
var quantity: Int32 = 0
|
||||||
if let giveaway {
|
if let giveaway {
|
||||||
quantity = giveaway.quantity
|
quantity = giveaway.quantity
|
||||||
@ -173,10 +164,14 @@ public func presentGiveawayInfoController(
|
|||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedJoinedEarly(joinDate).string
|
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedJoinedEarly(joinDate).string
|
||||||
case let .channelAdmin(adminId):
|
case let .channelAdmin(adminId):
|
||||||
var channelName = peerName
|
var channelName = peerName
|
||||||
|
var isGroup = false
|
||||||
if let maybePeer = peerMap[adminId], let peer = maybePeer {
|
if let maybePeer = peerMap[adminId], let peer = maybePeer {
|
||||||
channelName = peer.compactDisplayTitle
|
channelName = peer.compactDisplayTitle
|
||||||
|
if case let .channel(channel) = peer, case .group = channel.info {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedAdmin(channelName).string
|
participation = isGroup ? presentationData.strings.Chat_Giveaway_Info_NotAllowedAdminGroup(channelName).string : presentationData.strings.Chat_Giveaway_Info_NotAllowedAdmin(channelName).string
|
||||||
case .disallowedCountry:
|
case .disallowedCountry:
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedCountry
|
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedCountry
|
||||||
}
|
}
|
||||||
|
@ -1183,10 +1183,14 @@ private final class SheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class BoostLevelsContainerComponent: CombinedComponent {
|
private final class BoostLevelsContainerComponent: CombinedComponent {
|
||||||
|
class ExternalState {
|
||||||
|
var isGroup: Bool = false
|
||||||
|
}
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let strings: PresentationStrings
|
let strings: PresentationStrings
|
||||||
|
let externalState: ExternalState
|
||||||
let peerId: EnginePeer.Id
|
let peerId: EnginePeer.Id
|
||||||
let mode: PremiumBoostLevelsScreen.Mode
|
let mode: PremiumBoostLevelsScreen.Mode
|
||||||
let status: ChannelBoostStatus?
|
let status: ChannelBoostStatus?
|
||||||
@ -1202,6 +1206,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
strings: PresentationStrings,
|
strings: PresentationStrings,
|
||||||
|
externalState: ExternalState,
|
||||||
peerId: EnginePeer.Id,
|
peerId: EnginePeer.Id,
|
||||||
mode: PremiumBoostLevelsScreen.Mode,
|
mode: PremiumBoostLevelsScreen.Mode,
|
||||||
status: ChannelBoostStatus?,
|
status: ChannelBoostStatus?,
|
||||||
@ -1216,6 +1221,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
self.context = context
|
self.context = context
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
|
self.externalState = externalState
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.status = status
|
self.status = status
|
||||||
@ -1309,6 +1315,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let isGroup {
|
if let isGroup {
|
||||||
|
component.externalState.isGroup = isGroup
|
||||||
let scroll = scroll.update(
|
let scroll = scroll.update(
|
||||||
component: ScrollComponent<Empty>(
|
component: ScrollComponent<Empty>(
|
||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
@ -1556,6 +1563,8 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
let footerContainerView: UIView
|
let footerContainerView: UIView
|
||||||
let footerView: ComponentHostView<Empty>
|
let footerView: ComponentHostView<Empty>
|
||||||
|
|
||||||
|
private let externalState = BoostLevelsContainerComponent.ExternalState()
|
||||||
|
|
||||||
private(set) var isExpanded = false
|
private(set) var isExpanded = false
|
||||||
private var panGestureRecognizer: UIPanGestureRecognizer?
|
private var panGestureRecognizer: UIPanGestureRecognizer?
|
||||||
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
|
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
|
||||||
@ -1819,6 +1828,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
context: controller.context,
|
context: controller.context,
|
||||||
theme: self.presentationData.theme,
|
theme: self.presentationData.theme,
|
||||||
strings: self.presentationData.strings,
|
strings: self.presentationData.strings,
|
||||||
|
externalState: self.externalState,
|
||||||
peerId: controller.peerId,
|
peerId: controller.peerId,
|
||||||
mode: controller.mode,
|
mode: controller.mode,
|
||||||
status: controller.status,
|
status: controller.status,
|
||||||
@ -1868,13 +1878,20 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
var footerHeight: CGFloat = 8.0 + 50.0
|
var footerHeight: CGFloat = 8.0 + 50.0
|
||||||
footerHeight += layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : 8.0
|
footerHeight += layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : 8.0
|
||||||
|
|
||||||
|
let actionTitle: String
|
||||||
|
if self.currentMyBoostCount > 0 {
|
||||||
|
actionTitle = self.presentationData.strings.ChannelBoost_BoostAgain
|
||||||
|
} else {
|
||||||
|
actionTitle = self.externalState.isGroup ? self.presentationData.strings.GroupBoost_BoostGroup : self.presentationData.strings.ChannelBoost_BoostChannel
|
||||||
|
}
|
||||||
|
|
||||||
let footerSize = self.footerView.update(
|
let footerSize = self.footerView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
FooterComponent(
|
FooterComponent(
|
||||||
context: controller.context,
|
context: controller.context,
|
||||||
theme: self.presentationData.theme,
|
theme: self.presentationData.theme,
|
||||||
title: self.currentMyBoostCount > 0 ? "Boost Again" : "Boost Group",
|
title: actionTitle,
|
||||||
action: { [weak self] in
|
action: { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
@ -279,7 +279,7 @@ final class PremiumStickerPackAccessoryNode: SparseNode, PeekControllerAccessory
|
|||||||
self.textNode.displaysAsynchronously = false
|
self.textNode.displaysAsynchronously = false
|
||||||
self.textNode.textAlignment = .center
|
self.textNode.textAlignment = .center
|
||||||
self.textNode.maximumNumberOfLines = 0
|
self.textNode.maximumNumberOfLines = 0
|
||||||
self.textNode.attributedText = NSAttributedString(string: isEmoji ? strings.Premium_Stickers_Description : strings.Premium_Stickers_Description, font: Font.regular(17.0), textColor: theme.actionSheet.secondaryTextColor)
|
self.textNode.attributedText = NSAttributedString(string: isEmoji ? strings.Premium_Emoji_Description : strings.Premium_Stickers_Description, font: Font.regular(17.0), textColor: theme.actionSheet.secondaryTextColor)
|
||||||
self.textNode.lineSpacing = 0.1
|
self.textNode.lineSpacing = 0.1
|
||||||
|
|
||||||
self.proceedButton = SolidRoundedButtonNode(title: isEmoji ? strings.Premium_Emoji_Proceed: strings.Premium_Stickers_Proceed, theme: SolidRoundedButtonTheme(
|
self.proceedButton = SolidRoundedButtonNode(title: isEmoji ? strings.Premium_Emoji_Proceed: strings.Premium_Stickers_Proceed, theme: SolidRoundedButtonTheme(
|
||||||
|
@ -900,21 +900,21 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
}
|
}
|
||||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||||
case let .setChatWallpaper(_, forBoth):
|
case let .setChatWallpaper(_, forBoth):
|
||||||
|
var isGroup = false
|
||||||
|
let messagePeer = message.peers[message.id.peerId]
|
||||||
|
if let channel = messagePeer as? TelegramChannel, case .group = channel.info {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
if message.author?.id == accountPeerId {
|
if message.author?.id == accountPeerId {
|
||||||
if forBoth {
|
if forBoth {
|
||||||
let peerName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.compactDisplayTitle ?? ""
|
let peerName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.compactDisplayTitle ?? ""
|
||||||
let resultTitleString = strings.Notification_YouChangedWallpaperBoth(peerName)
|
let resultTitleString = strings.Notification_YouChangedWallpaperBoth(peerName)
|
||||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
} else {
|
} else {
|
||||||
attributedString = NSAttributedString(string: strings.Notification_YouChangedWallpaper, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: isGroup ? strings.Notification_YouChangedGroupWallpaper : strings.Notification_YouChangedWallpaper, font: titleFont, textColor: primaryTextColor)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if message.id.peerId.isGroupOrChannel {
|
if message.id.peerId.isGroupOrChannel {
|
||||||
var isGroup = false
|
|
||||||
let messagePeer = message.peers[message.id.peerId]
|
|
||||||
if let channel = messagePeer as? TelegramChannel, case .group = channel.info {
|
|
||||||
isGroup = true
|
|
||||||
}
|
|
||||||
attributedString = NSAttributedString(string: isGroup ? strings.Notification_GroupChangedWallpaper : strings.Notification_ChannelChangedWallpaper, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: isGroup ? strings.Notification_GroupChangedWallpaper : strings.Notification_ChannelChangedWallpaper, font: titleFont, textColor: primaryTextColor)
|
||||||
} else {
|
} else {
|
||||||
let resultTitleString = strings.Notification_ChangedWallpaper(compactAuthorName)
|
let resultTitleString = strings.Notification_ChangedWallpaper(compactAuthorName)
|
||||||
|
@ -371,13 +371,13 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode,
|
|||||||
if let giveaway {
|
if let giveaway {
|
||||||
if giveaway.flags.contains(.onlyNewSubscribers) {
|
if giveaway.flags.contains(.onlyNewSubscribers) {
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
participantsText = item.presentationData.strings.Chat_Giveaway_Message_ParticipantsNewMany
|
participantsText = isGroup ? item.presentationData.strings.Chat_Giveaway_Message_Group_ParticipantsNewMany : item.presentationData.strings.Chat_Giveaway_Message_ParticipantsNewMany
|
||||||
} else {
|
} else {
|
||||||
participantsText = item.presentationData.strings.Chat_Giveaway_Message_ParticipantsNew
|
participantsText = isGroup ? item.presentationData.strings.Chat_Giveaway_Message_Group_ParticipantsNew : item.presentationData.strings.Chat_Giveaway_Message_ParticipantsNew
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
participantsText = item.presentationData.strings.Chat_Giveaway_Message_ParticipantsMany
|
participantsText = isGroup ? item.presentationData.strings.Chat_Giveaway_Message_Group_ParticipantsMany : item.presentationData.strings.Chat_Giveaway_Message_ParticipantsMany
|
||||||
} else {
|
} else {
|
||||||
participantsText = isGroup ? item.presentationData.strings.Chat_Giveaway_Message_Group_Participants : item.presentationData.strings.Chat_Giveaway_Message_Participants
|
participantsText = isGroup ? item.presentationData.strings.Chat_Giveaway_Message_Group_Participants : item.presentationData.strings.Chat_Giveaway_Message_Participants
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,12 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fromYou = item.message.author?.id == item.context.account.peerId
|
let fromYou = item.message.author?.id == item.context.account.peerId
|
||||||
let isChannel = item.message.id.peerId.isGroupOrChannel
|
let isGroupOrChannel = item.message.id.peerId.isGroupOrChannel
|
||||||
|
var isGroup = false
|
||||||
|
let messagePeer = item.message.peers[item.message.id.peerId]
|
||||||
|
if let channel = messagePeer as? TelegramChannel, case .group = channel.info {
|
||||||
|
isGroup = true
|
||||||
|
}
|
||||||
|
|
||||||
let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
||||||
let text: String
|
let text: String
|
||||||
@ -278,19 +283,14 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
|
|||||||
if forBoth {
|
if forBoth {
|
||||||
text = item.presentationData.strings.Notification_YouChangedWallpaperBoth(peerName).string
|
text = item.presentationData.strings.Notification_YouChangedWallpaperBoth(peerName).string
|
||||||
} else {
|
} else {
|
||||||
text = item.presentationData.strings.Notification_YouChangedWallpaper
|
text = isGroup ? item.presentationData.strings.Notification_YouChangedGroupWallpaper : item.presentationData.strings.Notification_YouChangedWallpaper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if item.associatedData.isRecentActions {
|
if item.associatedData.isRecentActions {
|
||||||
let authorName = item.message.author.flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
let authorName = item.message.author.flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
||||||
text = item.presentationData.strings.Channel_AdminLog_ChannelChangedWallpaper(authorName).string
|
text = item.presentationData.strings.Channel_AdminLog_ChannelChangedWallpaper(authorName).string
|
||||||
} else if item.message.id.peerId.isGroupOrChannel {
|
} else if isGroupOrChannel {
|
||||||
var isGroup = false
|
|
||||||
let messagePeer = item.message.peers[item.message.id.peerId]
|
|
||||||
if let channel = messagePeer as? TelegramChannel, case .group = channel.info {
|
|
||||||
isGroup = true
|
|
||||||
}
|
|
||||||
text = isGroup ? item.presentationData.strings.Notification_GroupChangedWallpaper : item.presentationData.strings.Notification_ChannelChangedWallpaper
|
text = isGroup ? item.presentationData.strings.Notification_GroupChangedWallpaper : item.presentationData.strings.Notification_ChannelChangedWallpaper
|
||||||
} else {
|
} else {
|
||||||
text = item.presentationData.strings.Notification_ChangedWallpaper(peerName).string
|
text = item.presentationData.strings.Notification_ChangedWallpaper(peerName).string
|
||||||
@ -324,15 +324,15 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
|
|||||||
if displayTrailingAnimatedDots {
|
if displayTrailingAnimatedDots {
|
||||||
textHeight += subtitleLayout.size.height
|
textHeight += subtitleLayout.size.height
|
||||||
}
|
}
|
||||||
let backgroundSize = CGSize(width: width, height: textHeight + 140.0 + (fromYou || isChannel ? 0.0 : 42.0))
|
let backgroundSize = CGSize(width: width, height: textHeight + 140.0 + (fromYou || isGroupOrChannel ? 0.0 : 42.0))
|
||||||
|
|
||||||
return (backgroundSize.width, { boundingWidth in
|
return (backgroundSize.width, { boundingWidth in
|
||||||
return (backgroundSize, { [weak self] animation, synchronousLoads, _ in
|
return (backgroundSize, { [weak self] animation, synchronousLoads, _ in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.item = item
|
strongSelf.item = item
|
||||||
|
|
||||||
strongSelf.buttonNode.isHidden = fromYou || isChannel
|
strongSelf.buttonNode.isHidden = fromYou || isGroupOrChannel
|
||||||
strongSelf.buttonTitleNode.isHidden = fromYou || isChannel
|
strongSelf.buttonTitleNode.isHidden = fromYou || isGroupOrChannel
|
||||||
|
|
||||||
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
||||||
if let media, mediaUpdated {
|
if let media, mediaUpdated {
|
||||||
|
@ -1698,11 +1698,15 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
var stickersEnabled = true
|
var stickersEnabled = true
|
||||||
var emojiEnabled = true
|
var emojiEnabled = true
|
||||||
if let peer = interfaceState.renderedPeer?.peer as? TelegramChannel {
|
if let peer = interfaceState.renderedPeer?.peer as? TelegramChannel {
|
||||||
if peer.hasBannedPermission(.banSendStickers) != nil {
|
if let boostsToUnrestrict = interfaceState.boostsToUnrestrict, boostsToUnrestrict > 0 {
|
||||||
stickersEnabled = false
|
|
||||||
}
|
} else {
|
||||||
if peer.hasBannedPermission(.banSendText) != nil {
|
if peer.hasBannedPermission(.banSendStickers) != nil {
|
||||||
emojiEnabled = false
|
stickersEnabled = false
|
||||||
|
}
|
||||||
|
if peer.hasBannedPermission(.banSendText) != nil {
|
||||||
|
emojiEnabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if let peer = interfaceState.renderedPeer?.peer as? TelegramGroup {
|
} else if let peer = interfaceState.renderedPeer?.peer as? TelegramGroup {
|
||||||
if peer.hasBannedPermission(.banSendStickers) {
|
if peer.hasBannedPermission(.banSendStickers) {
|
||||||
|
@ -10,6 +10,9 @@ import ItemListUI
|
|||||||
import PresentationDataUtils
|
import PresentationDataUtils
|
||||||
import ActivityIndicator
|
import ActivityIndicator
|
||||||
import StickerResources
|
import StickerResources
|
||||||
|
import AnimatedStickerNode
|
||||||
|
import TelegramAnimatedStickerNode
|
||||||
|
import ShimmerEffect
|
||||||
import AppBundle
|
import AppBundle
|
||||||
|
|
||||||
enum GroupStickerPackCurrentItemContent: Equatable {
|
enum GroupStickerPackCurrentItemContent: Equatable {
|
||||||
@ -94,6 +97,9 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
private let maskNode: ASImageNode
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
fileprivate let imageNode: TransformImageNode
|
fileprivate let imageNode: TransformImageNode
|
||||||
|
private var animationNode: AnimatedStickerNode?
|
||||||
|
private var placeholderNode: StickerShimmerEffectNode?
|
||||||
|
|
||||||
private let notFoundNode: ASImageNode
|
private let notFoundNode: ASImageNode
|
||||||
private let titleNode: TextNode
|
private let titleNode: TextNode
|
||||||
private let statusNode: TextNode
|
private let statusNode: TextNode
|
||||||
@ -133,6 +139,9 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.imageNode = TransformImageNode()
|
self.imageNode = TransformImageNode()
|
||||||
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
|
self.imageNode.isLayerBacked = !smartInvertColorsEnabled()
|
||||||
|
|
||||||
|
self.placeholderNode = StickerShimmerEffectNode()
|
||||||
|
self.placeholderNode?.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.notFoundNode = ASImageNode()
|
self.notFoundNode = ASImageNode()
|
||||||
self.notFoundNode.isLayerBacked = true
|
self.notFoundNode.isLayerBacked = true
|
||||||
self.notFoundNode.displayWithoutProcessing = true
|
self.notFoundNode.displayWithoutProcessing = true
|
||||||
@ -161,6 +170,10 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||||
|
|
||||||
|
if let placeholderNode = self.placeholderNode {
|
||||||
|
self.addSubnode(placeholderNode)
|
||||||
|
}
|
||||||
|
|
||||||
self.addSubnode(self.imageNode)
|
self.addSubnode(self.imageNode)
|
||||||
self.addSubnode(self.titleNode)
|
self.addSubnode(self.titleNode)
|
||||||
self.addSubnode(self.statusNode)
|
self.addSubnode(self.statusNode)
|
||||||
@ -168,12 +181,50 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.addSubnode(self.activityIndicator)
|
self.addSubnode(self.activityIndicator)
|
||||||
|
|
||||||
self.addSubnode(self.removeButton)
|
self.addSubnode(self.removeButton)
|
||||||
|
|
||||||
|
var firstTime = true
|
||||||
|
self.imageNode.imageUpdated = { [weak self] image in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if image != nil {
|
||||||
|
strongSelf.removePlaceholder(animated: !firstTime)
|
||||||
|
if firstTime {
|
||||||
|
strongSelf.imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstTime = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.fetchDisposable.dispose()
|
self.fetchDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func removePlaceholder(animated: Bool) {
|
||||||
|
if let placeholderNode = self.placeholderNode {
|
||||||
|
self.placeholderNode = nil
|
||||||
|
if !animated {
|
||||||
|
placeholderNode.removeFromSupernode()
|
||||||
|
} else {
|
||||||
|
placeholderNode.allowsGroupOpacity = true
|
||||||
|
placeholderNode.alpha = 0.0
|
||||||
|
placeholderNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak placeholderNode] _ in
|
||||||
|
placeholderNode?.removeFromSupernode()
|
||||||
|
placeholderNode?.allowsGroupOpacity = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var absoluteLocation: (CGRect, CGSize)?
|
||||||
|
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absoluteLocation = (rect, containerSize)
|
||||||
|
if let placeholderNode = placeholderNode {
|
||||||
|
placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + placeholderNode.frame.minX, y: rect.minY + placeholderNode.frame.minY), size: placeholderNode.frame.size), within: containerSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func asyncLayout() -> (_ item: GroupStickerPackCurrentItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) {
|
func asyncLayout() -> (_ item: GroupStickerPackCurrentItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) {
|
||||||
let makeImageLayout = self.imageNode.asyncLayout()
|
let makeImageLayout = self.imageNode.asyncLayout()
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
@ -300,22 +351,6 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
if strongSelf.maskNode.supernode == nil {
|
if strongSelf.maskNode.supernode == nil {
|
||||||
strongSelf.addSubnode(strongSelf.maskNode)
|
strongSelf.addSubnode(strongSelf.maskNode)
|
||||||
}
|
}
|
||||||
// switch neighbors.top {
|
|
||||||
// case .sameSection(false):
|
|
||||||
// strongSelf.topStripeNode.isHidden = true
|
|
||||||
// default:
|
|
||||||
// strongSelf.topStripeNode.isHidden = false
|
|
||||||
// }
|
|
||||||
// let bottomStripeInset: CGFloat
|
|
||||||
// let bottomStripeOffset: CGFloat
|
|
||||||
// switch neighbors.bottom {
|
|
||||||
// case .sameSection(false):
|
|
||||||
// bottomStripeInset = leftInset + editingOffset
|
|
||||||
// bottomStripeOffset = -separatorHeight
|
|
||||||
// default:
|
|
||||||
// bottomStripeInset = 0.0
|
|
||||||
// bottomStripeOffset = 0.0
|
|
||||||
// }
|
|
||||||
|
|
||||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||||
var hasTopCorners = false
|
var hasTopCorners = false
|
||||||
@ -358,7 +393,6 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode {
|
|||||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset, y: 32.0), size: statusLayout.size))
|
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset, y: 32.0), size: statusLayout.size))
|
||||||
|
|
||||||
let boundingSize = CGSize(width: 34.0, height: 34.0)
|
let boundingSize = CGSize(width: 34.0, height: 34.0)
|
||||||
transition.updateFrame(node: strongSelf.imageNode, frame: 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))
|
|
||||||
let indicatorSize = CGSize(width: 22.0, height: 22.0)
|
let indicatorSize = CGSize(width: 22.0, height: 22.0)
|
||||||
transition.updateFrame(node: strongSelf.activityIndicator, frame: CGRect(origin: CGPoint(x: params.leftInset + 15.0 + floor((boundingSize.width - indicatorSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - indicatorSize.height) / 2.0)), size: indicatorSize))
|
transition.updateFrame(node: strongSelf.activityIndicator, frame: CGRect(origin: CGPoint(x: params.leftInset + 15.0 + floor((boundingSize.width - indicatorSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - indicatorSize.height) / 2.0)), size: indicatorSize))
|
||||||
|
|
||||||
@ -369,9 +403,17 @@ 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))
|
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 {
|
if let updatedImageSignal = updatedImageSignal {
|
||||||
strongSelf.imageNode.setSignal(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.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel + UIScreenPixel))
|
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||||
|
|
||||||
|
@ -1077,6 +1077,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
if hasSavedMessages, hasSavedMessagesChats, var availablePanesValue = availablePanes {
|
if hasSavedMessages, hasSavedMessagesChats, var availablePanesValue = availablePanes {
|
||||||
if let index = availablePanesValue.firstIndex(of: .media) {
|
if let index = availablePanesValue.firstIndex(of: .media) {
|
||||||
availablePanesValue.insert(.savedMessages, at: index + 1)
|
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||||
|
} else if let index = availablePanesValue.firstIndex(of: .stories) {
|
||||||
|
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||||
} else {
|
} else {
|
||||||
availablePanesValue.insert(.savedMessages, at: 0)
|
availablePanesValue.insert(.savedMessages, at: 0)
|
||||||
}
|
}
|
||||||
@ -1240,6 +1242,23 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
let requestsContextPromise = Promise<PeerInvitationImportersContext?>(nil)
|
let requestsContextPromise = Promise<PeerInvitationImportersContext?>(nil)
|
||||||
let requestsStatePromise = Promise<PeerInvitationImportersState?>(nil)
|
let requestsStatePromise = Promise<PeerInvitationImportersState?>(nil)
|
||||||
|
|
||||||
|
let storyListContext: PeerStoryListContext?
|
||||||
|
let hasStories: Signal<Bool?, NoError>
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
storyListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: false)
|
||||||
|
hasStories = storyListContext!.state
|
||||||
|
|> map { state -> Bool? in
|
||||||
|
if !state.hasCache {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return !state.items.isEmpty
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
} else {
|
||||||
|
storyListContext = nil
|
||||||
|
hasStories = .single(false)
|
||||||
|
}
|
||||||
|
|
||||||
let threadData: Signal<MessageHistoryThreadData?, NoError>
|
let threadData: Signal<MessageHistoryThreadData?, NoError>
|
||||||
if case let .replyThread(message) = chatLocation {
|
if case let .replyThread(message) = chatLocation {
|
||||||
let threadId = message.threadId
|
let threadId = message.threadId
|
||||||
@ -1306,6 +1325,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
invitationsStatePromise.get(),
|
invitationsStatePromise.get(),
|
||||||
requestsContextPromise.get(),
|
requestsContextPromise.get(),
|
||||||
requestsStatePromise.get(),
|
requestsStatePromise.get(),
|
||||||
|
hasStories,
|
||||||
threadData,
|
threadData,
|
||||||
context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]),
|
context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]),
|
||||||
accountIsPremium,
|
accountIsPremium,
|
||||||
@ -1313,12 +1333,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
hasSavedMessagesChats,
|
hasSavedMessagesChats,
|
||||||
hasSavedMessageTags
|
hasSavedMessageTags
|
||||||
)
|
)
|
||||||
|> mapToSignal { peerView, availablePanes, globalNotificationSettings, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests, threadData, preferencesView, accountIsPremium, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags -> Signal<PeerInfoScreenData, NoError> in
|
|> mapToSignal { peerView, availablePanes, globalNotificationSettings, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests, hasStories, threadData, preferencesView, accountIsPremium, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags -> Signal<PeerInfoScreenData, NoError> in
|
||||||
var discussionPeer: Peer?
|
var discussionPeer: Peer?
|
||||||
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
|
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
|
||||||
discussionPeer = peer
|
discussionPeer = peer
|
||||||
}
|
}
|
||||||
|
|
||||||
var availablePanes = availablePanes
|
var availablePanes = availablePanes
|
||||||
if let membersData = membersData, case .longList = membersData {
|
if let membersData = membersData, case .longList = membersData {
|
||||||
if availablePanes != nil {
|
if availablePanes != nil {
|
||||||
@ -1328,17 +1348,24 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .peer = chatLocation {
|
if let hasStories {
|
||||||
if hasSavedMessages, hasSavedMessagesChats, var availablePanesValue = availablePanes {
|
if hasStories {
|
||||||
if let index = availablePanesValue.firstIndex(of: .media) {
|
availablePanes?.insert(.stories, at: 0)
|
||||||
availablePanesValue.insert(.savedMessages, at: index + 1)
|
}
|
||||||
} else {
|
if case .peer = chatLocation {
|
||||||
availablePanesValue.insert(.savedMessages, at: 0)
|
if hasSavedMessages, hasSavedMessagesChats, var availablePanesValue = availablePanes {
|
||||||
|
if let index = availablePanesValue.firstIndex(of: .media) {
|
||||||
|
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||||
|
} else if let index = availablePanesValue.firstIndex(of: .stories) {
|
||||||
|
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||||
|
} else {
|
||||||
|
availablePanesValue.insert(.savedMessages, at: 0)
|
||||||
|
}
|
||||||
|
availablePanes = availablePanesValue
|
||||||
}
|
}
|
||||||
availablePanes = availablePanesValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var canManageInvitations = false
|
var canManageInvitations = false
|
||||||
if let group = peerViewMainPeer(peerView) as? TelegramGroup {
|
if let group = peerViewMainPeer(peerView) as? TelegramGroup {
|
||||||
let previousValue = wasUpgradedGroup.swap(group.migrationReference != nil)
|
let previousValue = wasUpgradedGroup.swap(group.migrationReference != nil)
|
||||||
@ -1389,7 +1416,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
groupsInCommon: nil,
|
groupsInCommon: nil,
|
||||||
linkedDiscussionPeer: discussionPeer,
|
linkedDiscussionPeer: discussionPeer,
|
||||||
members: membersData,
|
members: membersData,
|
||||||
storyListContext: nil,
|
storyListContext: storyListContext,
|
||||||
encryptionKeyFingerprint: nil,
|
encryptionKeyFingerprint: nil,
|
||||||
globalSettings: nil,
|
globalSettings: nil,
|
||||||
invitations: invitations,
|
invitations: invitations,
|
||||||
|
@ -10375,7 +10375,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
} else if peerInfoCanEdit(peer: self.data?.peer, chatLocation: self.chatLocation, threadData: self.data?.threadData, cachedData: self.data?.cachedData, isContact: self.data?.isContact) {
|
} else if peerInfoCanEdit(peer: self.data?.peer, chatLocation: self.chatLocation, threadData: self.data?.threadData, cachedData: self.data?.cachedData, isContact: self.data?.isContact) {
|
||||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
||||||
}
|
}
|
||||||
if let data = self.data, data.accountIsPremium, let channel = data.peer as? TelegramChannel, case .broadcast = channel.info, channel.hasPermission(.postStories) {
|
if let data = self.data, data.accountIsPremium, let channel = data.peer as? TelegramChannel, channel.hasPermission(.postStories) {
|
||||||
rightNavigationButtons.insert(PeerInfoHeaderNavigationButtonSpec(key: .postStory, isForExpandedView: false), at: 0)
|
rightNavigationButtons.insert(PeerInfoHeaderNavigationButtonSpec(key: .postStory, isForExpandedView: false), at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,6 +540,10 @@ final class ChannelAppearanceScreenComponent: Component {
|
|||||||
if self.isApplyingSettings {
|
if self.isApplyingSettings {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if resolvedState.changes.isEmpty {
|
||||||
|
self.environment?.controller()?.dismiss()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let requiredLevel = requiredBoostSubject.requiredLevel(group: self.isGroup, context: component.context, configuration: premiumConfiguration)
|
let requiredLevel = requiredBoostSubject.requiredLevel(group: self.isGroup, context: component.context, configuration: premiumConfiguration)
|
||||||
if let boostLevel = self.boostLevel, requiredLevel > boostLevel {
|
if let boostLevel = self.boostLevel, requiredLevel > boostLevel {
|
||||||
|
@ -1601,10 +1601,15 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let mode = self.mode, case let .peer(peer, existing) = mode {
|
if let mode = self.mode, case let .peer(peer, existing) = mode {
|
||||||
if case .channel = peer {
|
if case let .channel(channel) = peer {
|
||||||
topMessageText = presentationData.strings.WallpaperPreview_ChannelTopText
|
topMessageText = presentationData.strings.WallpaperPreview_ChannelTopText
|
||||||
bottomMessageText = ""
|
bottomMessageText = ""
|
||||||
serviceMessageText = presentationData.strings.WallpaperPreview_ChannelHeader
|
switch channel.info {
|
||||||
|
case .group:
|
||||||
|
serviceMessageText = presentationData.strings.WallpaperPreview_GroupHeader
|
||||||
|
case .broadcast:
|
||||||
|
serviceMessageText = presentationData.strings.WallpaperPreview_ChannelHeader
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
topMessageText = presentationData.strings.WallpaperPreview_ChatTopText
|
topMessageText = presentationData.strings.WallpaperPreview_ChatTopText
|
||||||
bottomMessageText = presentationData.strings.WallpaperPreview_ChatBottomText
|
bottomMessageText = presentationData.strings.WallpaperPreview_ChatBottomText
|
||||||
|
@ -544,8 +544,12 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
case .pin:
|
case .pin:
|
||||||
if self.selectedOptions.contains(.pin) {
|
if self.selectedOptions.contains(.pin) {
|
||||||
animationName = "anim_profileadd"
|
animationName = "anim_profileadd"
|
||||||
if let peerId = self.sendAsPeerId, peerId.namespace != Namespaces.Peer.CloudUser {
|
if let sendAsPeerId = self.sendAsPeerId, sendAsPeerId.isGroupOrChannel {
|
||||||
text = presentationData.strings.Story_Privacy_TooltipStoryArchivedChannel
|
if let selectedPeer = self.effectiveStateValue?.sendAsPeers.first(where: { $0.id == sendAsPeerId }), case let .channel(channel) = selectedPeer, case .group = channel.info {
|
||||||
|
text = presentationData.strings.Story_Privacy_TooltipStoryArchivedGroup
|
||||||
|
} else {
|
||||||
|
text = presentationData.strings.Story_Privacy_TooltipStoryArchivedChannel
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
text = presentationData.strings.Story_Privacy_TooltipStoryArchived
|
text = presentationData.strings.Story_Privacy_TooltipStoryArchived
|
||||||
}
|
}
|
||||||
@ -837,6 +841,15 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isSendAsGroup = false
|
||||||
|
if let sendAsPeerId = self.sendAsPeerId, sendAsPeerId.isGroupOrChannel == true {
|
||||||
|
if let selectedPeer = stateValue.sendAsPeers.first(where: { $0.id == sendAsPeerId }) {
|
||||||
|
if case let .channel(channel) = selectedPeer, case .group = channel.info {
|
||||||
|
isSendAsGroup = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var topOffset = -self.scrollView.bounds.minY + itemLayout.topInset
|
var topOffset = -self.scrollView.bounds.minY + itemLayout.topInset
|
||||||
topOffset = max(0.0, topOffset)
|
topOffset = max(0.0, topOffset)
|
||||||
transition.setTransform(layer: self.backgroundView.layer, transform: CATransform3DMakeTranslation(0.0, topOffset + itemLayout.containerInset, 0.0))
|
transition.setTransform(layer: self.backgroundView.layer, transform: CATransform3DMakeTranslation(0.0, topOffset + itemLayout.containerInset, 0.0))
|
||||||
@ -939,10 +952,10 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
} else if section.id == 2 {
|
} else if section.id == 2 {
|
||||||
sectionTitle = environment.strings.Story_Privacy_WhoCanViewHeader
|
sectionTitle = environment.strings.Story_Privacy_WhoCanViewHeader
|
||||||
} else if section.id == 1 {
|
} else if section.id == 1 {
|
||||||
if case .members = component.stateContext.subject {
|
if case let .members(isGroup, _, _) = component.stateContext.subject {
|
||||||
sectionTitle = environment.strings.BoostGift_Subscribers_SectionTitle
|
sectionTitle = isGroup ? environment.strings.BoostGift_Members_SectionTitle : environment.strings.BoostGift_Subscribers_SectionTitle
|
||||||
} else if case .channels = component.stateContext.subject {
|
} else if case let .channels(isGroup, _, _) = component.stateContext.subject {
|
||||||
sectionTitle = environment.strings.BoostGift_Channels_SectionTitle
|
sectionTitle = isGroup ? environment.strings.BoostGift_GroupsOrChannels_SectionTitle : environment.strings.BoostGift_ChannelsOrGroups_SectionTitle
|
||||||
} else {
|
} else {
|
||||||
sectionTitle = environment.strings.Story_Privacy_ContactsHeader
|
sectionTitle = environment.strings.Story_Privacy_ContactsHeader
|
||||||
}
|
}
|
||||||
@ -1494,11 +1507,11 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if case .members = component.stateContext.subject, self.selectedPeers.count >= 10, index == nil {
|
if case let .members(isGroup, _, _) = component.stateContext.subject, self.selectedPeers.count >= 10, index == nil {
|
||||||
self.hapticFeedback.error()
|
self.hapticFeedback.error()
|
||||||
|
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: environment.strings.BoostGift_Subscribers_MaximumReached("\(10)").string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: isGroup ? environment.strings.BoostGift_Members_MaximumReached("\(10)").string : environment.strings.BoostGift_Subscribers_MaximumReached("\(10)").string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
togglePeer()
|
togglePeer()
|
||||||
@ -1541,7 +1554,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
|
|
||||||
var title = item.title
|
var title = item.title
|
||||||
if item.id == .pin && !hasCategories {
|
if item.id == .pin && !hasCategories {
|
||||||
title = environment.strings.Story_Privacy_KeepOnChannelPage
|
title = isSendAsGroup ? environment.strings.Story_Privacy_KeepOnGroupPage : environment.strings.Story_Privacy_KeepOnChannelPage
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = visibleItem.update(
|
let _ = visibleItem.update(
|
||||||
@ -1595,8 +1608,8 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
let footerValue = environment.strings.Story_Privacy_KeepOnMyPageHours(Int32(component.timeout / 3600))
|
let footerValue = environment.strings.Story_Privacy_KeepOnMyPageHours(Int32(component.timeout / 3600))
|
||||||
var footerText = environment.strings.Story_Privacy_KeepOnMyPageInfo(footerValue).string
|
var footerText = environment.strings.Story_Privacy_KeepOnMyPageInfo(footerValue).string
|
||||||
|
|
||||||
if self.sendAsPeerId?.isGroupOrChannel == true {
|
if let sendAsPeerId = self.sendAsPeerId, sendAsPeerId.isGroupOrChannel == true {
|
||||||
footerText = environment.strings.Story_Privacy_KeepOnChannelPageInfo(footerValue).string
|
footerText = isSendAsGroup ? environment.strings.Story_Privacy_KeepOnGroupPageInfo(footerValue).string : environment.strings.Story_Privacy_KeepOnChannelPageInfo(footerValue).string
|
||||||
}
|
}
|
||||||
|
|
||||||
let footerSize = sectionFooter.update(
|
let footerSize = sectionFooter.update(
|
||||||
@ -1701,7 +1714,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
if let searchStateContext = self.searchStateContext, let value = searchStateContext.stateValue {
|
if let searchStateContext = self.searchStateContext, let value = searchStateContext.stateValue {
|
||||||
if case let .contactsSearch(query, _) = searchStateContext.subject {
|
if case let .contactsSearch(query, _) = searchStateContext.subject {
|
||||||
searchQuery = query
|
searchQuery = query
|
||||||
} else if case let .members(_, query) = searchStateContext.subject {
|
} else if case let .members(_, _, query) = searchStateContext.subject {
|
||||||
searchQuery = query
|
searchQuery = query
|
||||||
} else if case let .channels(_, _, query) = searchStateContext.subject {
|
} else if case let .channels(_, _, query) = searchStateContext.subject {
|
||||||
searchQuery = query
|
searchQuery = query
|
||||||
@ -2040,10 +2053,10 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
|
|
||||||
let placeholder: String
|
let placeholder: String
|
||||||
switch component.stateContext.subject {
|
switch component.stateContext.subject {
|
||||||
case .members:
|
case let .members(isGroup, _, _):
|
||||||
placeholder = environment.strings.BoostGift_Subscribers_Search
|
placeholder = isGroup ? environment.strings.BoostGift_Members_Search : environment.strings.BoostGift_Subscribers_Search
|
||||||
case .channels:
|
case let .channels(isGroup, _, _):
|
||||||
placeholder = environment.strings.BoostGift_Channels_Search
|
placeholder = isGroup ? environment.strings.BoostGift_GroupsOrChannels_Search : environment.strings.BoostGift_ChannelsOrGroups_Search
|
||||||
case .chats:
|
case .chats:
|
||||||
placeholder = environment.strings.Story_Privacy_SearchChats
|
placeholder = environment.strings.Story_Privacy_SearchChats
|
||||||
default:
|
default:
|
||||||
@ -2090,8 +2103,8 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
switch component.stateContext.subject {
|
switch component.stateContext.subject {
|
||||||
case let .channels(isGroup, exclude, _):
|
case let .channels(isGroup, exclude, _):
|
||||||
searchSubject = .channels(isGroup: isGroup, exclude: exclude, searchQuery: searchQuery)
|
searchSubject = .channels(isGroup: isGroup, exclude: exclude, searchQuery: searchQuery)
|
||||||
case let .members(peerId, _):
|
case let .members(isGroup, peerId, _):
|
||||||
searchSubject = .members(peerId: peerId, searchQuery: searchQuery)
|
searchSubject = .members(isGroup: isGroup, peerId: peerId, searchQuery: searchQuery)
|
||||||
default:
|
default:
|
||||||
searchSubject = .contactsSearch(query: searchQuery, onlyContacts: onlyContacts)
|
searchSubject = .contactsSearch(query: searchQuery, onlyContacts: onlyContacts)
|
||||||
}
|
}
|
||||||
@ -2389,9 +2402,9 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
case .contactsSearch:
|
case .contactsSearch:
|
||||||
title = ""
|
title = ""
|
||||||
case .members:
|
case let .members(isGroup, _, _):
|
||||||
title = environment.strings.BoostGift_Subscribers_Title
|
title = environment.strings.BoostGift_Subscribers_Title
|
||||||
subtitle = environment.strings.BoostGift_Subscribers_Subtitle("\(10)").string
|
subtitle = isGroup ? environment.strings.BoostGift_Members_Subtitle("\(10)").string : environment.strings.BoostGift_Subscribers_Subtitle("\(10)").string
|
||||||
actionButtonTitle = environment.strings.BoostGift_Subscribers_Save
|
actionButtonTitle = environment.strings.BoostGift_Subscribers_Save
|
||||||
case let .channels(isGroup, _, _):
|
case let .channels(isGroup, _, _):
|
||||||
title = isGroup ? environment.strings.BoostGift_GroupsOrChannels_Title : environment.strings.BoostGift_ChannelsOrGroups_Title
|
title = isGroup ? environment.strings.BoostGift_GroupsOrChannels_Title : environment.strings.BoostGift_ChannelsOrGroups_Title
|
||||||
|
@ -48,7 +48,7 @@ public extension ShareWithPeersScreen {
|
|||||||
case chats(blocked: Bool)
|
case chats(blocked: Bool)
|
||||||
case contacts(base: EngineStoryPrivacy.Base)
|
case contacts(base: EngineStoryPrivacy.Base)
|
||||||
case contactsSearch(query: String, onlyContacts: Bool)
|
case contactsSearch(query: String, onlyContacts: Bool)
|
||||||
case members(peerId: EnginePeer.Id, searchQuery: String?)
|
case members(isGroup: Bool, peerId: EnginePeer.Id, searchQuery: String?)
|
||||||
case channels(isGroup: Bool, exclude: Set<EnginePeer.Id>, searchQuery: String?)
|
case channels(isGroup: Bool, exclude: Set<EnginePeer.Id>, searchQuery: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +515,7 @@ public extension ShareWithPeersScreen {
|
|||||||
|
|
||||||
self.readySubject.set(true)
|
self.readySubject.set(true)
|
||||||
})
|
})
|
||||||
case let .members(peerId, searchQuery):
|
case let .members(_, peerId, searchQuery):
|
||||||
let membersState = Promise<ChannelMemberListState>()
|
let membersState = Promise<ChannelMemberListState>()
|
||||||
let contactsState = Promise<ChannelMemberListState>()
|
let contactsState = Promise<ChannelMemberListState>()
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ func makeAttachmentFileControllerImpl(context: AccountContext, updatedPresentati
|
|||||||
} else {
|
} else {
|
||||||
banDescription = presentationData.strings.Conversation_DefaultRestrictedMedia
|
banDescription = presentationData.strings.Conversation_DefaultRestrictedMedia
|
||||||
}
|
}
|
||||||
emptyItem = AttachmentFileEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings, content: .bannedSendMedia(banDescription))
|
emptyItem = AttachmentFileEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings, content: .bannedSendMedia(text: banDescription, canBoost: false))
|
||||||
} else if let recentDocuments = recentDocuments, recentDocuments.isEmpty {
|
} else if let recentDocuments = recentDocuments, recentDocuments.isEmpty {
|
||||||
emptyItem = AttachmentFileEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings, content: .intro)
|
emptyItem = AttachmentFileEmptyStateItem(context: context, theme: presentationData.theme, strings: presentationData.strings, content: .intro)
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,12 @@ import PresentationDataUtils
|
|||||||
import AnimatedStickerNode
|
import AnimatedStickerNode
|
||||||
import TelegramAnimatedStickerNode
|
import TelegramAnimatedStickerNode
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import SolidRoundedButtonNode
|
||||||
|
|
||||||
final class AttachmentFileEmptyStateItem: ItemListControllerEmptyStateItem {
|
final class AttachmentFileEmptyStateItem: ItemListControllerEmptyStateItem {
|
||||||
enum Content: Equatable {
|
enum Content: Equatable {
|
||||||
case intro
|
case intro
|
||||||
case bannedSendMedia(String)
|
case bannedSendMedia(text: String, canBoost: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
@ -48,6 +49,7 @@ final class AttachmentFileEmptyStateItem: ItemListControllerEmptyStateItem {
|
|||||||
final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNode {
|
final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNode {
|
||||||
private var animationNode: AnimatedStickerNode
|
private var animationNode: AnimatedStickerNode
|
||||||
private let textNode: ASTextNode
|
private let textNode: ASTextNode
|
||||||
|
private let buttonNode: SolidRoundedButtonNode
|
||||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||||
|
|
||||||
var item: AttachmentFileEmptyStateItem {
|
var item: AttachmentFileEmptyStateItem {
|
||||||
@ -62,8 +64,19 @@ final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNo
|
|||||||
init(item: AttachmentFileEmptyStateItem) {
|
init(item: AttachmentFileEmptyStateItem) {
|
||||||
self.item = item
|
self.item = item
|
||||||
|
|
||||||
|
let name: String
|
||||||
|
let playbackMode: AnimatedStickerPlaybackMode
|
||||||
|
switch item.content {
|
||||||
|
case .intro:
|
||||||
|
name = "Files"
|
||||||
|
playbackMode = .loop
|
||||||
|
case .bannedSendMedia:
|
||||||
|
name = "Banned"
|
||||||
|
playbackMode = .once
|
||||||
|
}
|
||||||
|
|
||||||
self.animationNode = DefaultAnimatedStickerNodeImpl()
|
self.animationNode = DefaultAnimatedStickerNodeImpl()
|
||||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Files"), width: 320, height: 320, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
|
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: name), width: 320, height: 320, playbackMode: playbackMode, mode: .direct(cachePathPrefix: nil))
|
||||||
self.animationNode.visibility = true
|
self.animationNode.visibility = true
|
||||||
|
|
||||||
self.textNode = ASTextNode()
|
self.textNode = ASTextNode()
|
||||||
@ -71,6 +84,8 @@ final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNo
|
|||||||
self.textNode.lineSpacing = 0.1
|
self.textNode.lineSpacing = 0.1
|
||||||
self.textNode.textAlignment = .center
|
self.textNode.textAlignment = .center
|
||||||
|
|
||||||
|
self.buttonNode = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: .black, foregroundColor: .white), height: 50.0, cornerRadius: 11.0, gloss: true)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.isUserInteractionEnabled = false
|
self.isUserInteractionEnabled = false
|
||||||
@ -79,6 +94,10 @@ final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNo
|
|||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.textNode)
|
||||||
|
|
||||||
self.updateThemeAndStrings(theme: self.item.theme, strings: self.item.strings)
|
self.updateThemeAndStrings(theme: self.item.theme, strings: self.item.strings)
|
||||||
|
|
||||||
|
if case .bannedSendMedia(_, true) = item.content {
|
||||||
|
self.addSubnode(self.buttonNode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
private func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||||
@ -86,46 +105,47 @@ final class AttachmentFileEmptyStateItemNode: ItemListControllerEmptyStateItemNo
|
|||||||
switch self.item.content {
|
switch self.item.content {
|
||||||
case .intro:
|
case .intro:
|
||||||
text = strings.Attachment_FilesIntro
|
text = strings.Attachment_FilesIntro
|
||||||
case let .bannedSendMedia(banDescription):
|
case let .bannedSendMedia(banDescription, _):
|
||||||
text = banDescription
|
text = banDescription
|
||||||
}
|
}
|
||||||
self.textNode.attributedText = NSAttributedString(string: text.replacingOccurrences(of: "\n", with: " "), font: Font.regular(15.0), textColor: theme.list.freeTextColor, paragraphAlignment: .center)
|
self.textNode.attributedText = NSAttributedString(string: text.replacingOccurrences(of: "\n", with: " "), font: Font.regular(15.0), textColor: theme.list.freeTextColor, paragraphAlignment: .center)
|
||||||
|
self.buttonNode.title = strings.Attachment_OpenSettings
|
||||||
|
self.buttonNode.updateTheme(SolidRoundedButtonTheme(theme: theme))
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
override func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
self.validLayout = (layout, navigationBarHeight)
|
self.validLayout = (layout, navigationBarHeight)
|
||||||
var insets = layout.insets(options: [])
|
|
||||||
insets.top += navigationBarHeight
|
|
||||||
|
|
||||||
let imageSpacing: CGFloat = 12.0
|
|
||||||
|
|
||||||
var imageSize = CGSize(width: 144.0, height: 144.0)
|
var imageSize = CGSize(width: 144.0, height: 144.0)
|
||||||
|
var insets = layout.insets(options: [])
|
||||||
if layout.size.width == 320.0 {
|
if layout.size.width == 320.0 {
|
||||||
|
insets.top += -60.0
|
||||||
imageSize = CGSize(width: 112.0, height: 112.0)
|
imageSize = CGSize(width: 112.0, height: 112.0)
|
||||||
|
} else {
|
||||||
|
insets.top += -160.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let imageSpacing: CGFloat = 12.0
|
||||||
|
let textSpacing: CGFloat = 12.0
|
||||||
|
let buttonSpacing: CGFloat = 15.0
|
||||||
|
let bottomSpacing: CGFloat = 33.0
|
||||||
|
|
||||||
let imageHeight = layout.size.width < layout.size.height ? imageSize.height + imageSpacing : 0.0
|
let imageHeight = layout.size.width < layout.size.height ? imageSize.height + imageSpacing : 0.0
|
||||||
if !imageHeight.isZero {
|
|
||||||
if case .intro = self.item.content {
|
|
||||||
insets.top -= 92.0
|
|
||||||
} else {
|
|
||||||
insets.top -= 160.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if layout.size.width == 320.0 {
|
let buttonWidth: CGFloat = 248.0
|
||||||
insets.top += 110.0
|
let buttonHeight = self.buttonNode.updateLayout(width: buttonWidth, transition: transition)
|
||||||
}
|
|
||||||
|
|
||||||
let textSize = self.textNode.measure(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - 70.0, height: max(1.0, layout.size.height - insets.top - insets.bottom)))
|
|
||||||
|
|
||||||
let totalHeight = imageHeight + textSize.height
|
let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - 40.0, height: max(1.0, layout.size.height - insets.top - insets.bottom)))
|
||||||
|
|
||||||
|
let totalHeight = imageHeight + textSpacing + textSize.height + buttonSpacing + buttonHeight + bottomSpacing
|
||||||
let topOffset = insets.top + floor((layout.size.height - insets.top - insets.bottom - totalHeight) / 2.0)
|
let topOffset = insets.top + floor((layout.size.height - insets.top - insets.bottom - totalHeight) / 2.0)
|
||||||
|
|
||||||
transition.updateAlpha(node: self.animationNode, alpha: imageHeight > 0.0 ? 1.0 : 0.0)
|
transition.updateAlpha(node: self.animationNode, alpha: imageHeight > 0.0 ? 1.0 : 0.0)
|
||||||
transition.updateFrame(node: self.animationNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - imageSize.width) / 2.0), y: topOffset), size: imageSize))
|
transition.updateFrame(node: self.animationNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - imageSize.width) / 2.0), y: topOffset), size: imageSize))
|
||||||
self.animationNode.updateLayout(size: imageSize)
|
self.animationNode.updateLayout(size: imageSize)
|
||||||
|
|
||||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - textSize.width - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: topOffset + imageHeight), size: textSize))
|
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - textSize.width - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: topOffset + imageHeight + textSpacing), size: textSize))
|
||||||
|
|
||||||
|
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - buttonWidth - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: self.textNode.frame.maxY + buttonSpacing), size: CGSize(width: buttonWidth, height: buttonHeight)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1692,6 +1692,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, peer.hasBannedPermission(.banSendStickers) != nil {
|
||||||
|
if let boostsToUnrestrict = strongSelf.presentationInterfaceState.boostsToUnrestrict, boostsToUnrestrict > 0, (strongSelf.presentationInterfaceState.appliedBoosts ?? 0) < boostsToUnrestrict {
|
||||||
|
strongSelf.interfaceInteraction?.openBoostToUnrestrict()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var attributes: [MessageAttribute] = []
|
var attributes: [MessageAttribute] = []
|
||||||
if let query = query {
|
if let query = query {
|
||||||
attributes.append(EmojiSearchQueryMessageAttribute(query: query))
|
attributes.append(EmojiSearchQueryMessageAttribute(query: query))
|
||||||
@ -1837,6 +1844,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, peer.hasBannedPermission(.banSendGifs) != nil {
|
||||||
|
if let boostsToUnrestrict = strongSelf.presentationInterfaceState.boostsToUnrestrict, boostsToUnrestrict > 0, (strongSelf.presentationInterfaceState.appliedBoosts ?? 0) < boostsToUnrestrict {
|
||||||
|
strongSelf.interfaceInteraction?.openBoostToUnrestrict()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.collapseInput()
|
strongSelf.chatDisplayNode.collapseInput()
|
||||||
@ -1881,6 +1895,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, peer.hasBannedPermission(.banSendGifs) != nil {
|
||||||
|
if let boostsToUnrestrict = strongSelf.presentationInterfaceState.boostsToUnrestrict, boostsToUnrestrict > 0, (strongSelf.presentationInterfaceState.appliedBoosts ?? 0) < boostsToUnrestrict {
|
||||||
|
strongSelf.interfaceInteraction?.openBoostToUnrestrict()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strongSelf.enqueueChatContextResult(collection, result, hideVia: true, closeMediaInput: true, silentPosting: silentPosting, resetTextInputState: resetTextInputState)
|
strongSelf.enqueueChatContextResult(collection, result, hideVia: true, closeMediaInput: true, silentPosting: silentPosting, resetTextInputState: resetTextInputState)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -9538,10 +9559,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let boostsToUnrestrict = (strongSelf.peerView?.cachedData as? CachedChannelData)?.boostsToUnrestrict, boostsToUnrestrict > 0 {
|
|
||||||
strongSelf.interfaceInteraction?.openBoostToUnrestrict()
|
let canBypassRestrictions = canBypassRestrictions(chatPresentationInterfaceState: strongSelf.presentationInterfaceState)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let subjectFlags: [TelegramChatBannedRightsFlags]
|
let subjectFlags: [TelegramChatBannedRightsFlags]
|
||||||
switch subject {
|
switch subject {
|
||||||
@ -9554,7 +9573,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var bannedPermission: (Int32, Bool)? = nil
|
var bannedPermission: (Int32, Bool)? = nil
|
||||||
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
|
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
|
||||||
for subjectFlag in subjectFlags {
|
for subjectFlag in subjectFlags {
|
||||||
if let value = channel.hasBannedPermission(subjectFlag) {
|
if let value = channel.hasBannedPermission(subjectFlag, ignoreDefault: canBypassRestrictions) {
|
||||||
bannedPermission = value
|
bannedPermission = value
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -9568,6 +9587,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let boostsToUnrestrict = (strongSelf.peerView?.cachedData as? CachedChannelData)?.boostsToUnrestrict, boostsToUnrestrict > 0, bannedPermission == nil {
|
||||||
|
strongSelf.interfaceInteraction?.openBoostToUnrestrict()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var displayToast = false
|
var displayToast = false
|
||||||
|
|
||||||
if let (untilDate, personal) = bannedPermission {
|
if let (untilDate, personal) = bannedPermission {
|
||||||
|
@ -44,11 +44,12 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
|
|
||||||
let inputIsActive = self.presentationInterfaceState.inputMode == .text
|
let inputIsActive = self.presentationInterfaceState.inputMode == .text
|
||||||
|
|
||||||
self.chatDisplayNode.dismissInput()
|
self.chatDisplayNode.dismissInput()
|
||||||
|
|
||||||
|
let canByPassRestrictions = canBypassRestrictions(chatPresentationInterfaceState: self.presentationInterfaceState)
|
||||||
|
|
||||||
var banSendText: (Int32, Bool)?
|
var banSendText: (Int32, Bool)?
|
||||||
var bannedSendPhotos: (Int32, Bool)?
|
var bannedSendPhotos: (Int32, Bool)?
|
||||||
var bannedSendVideos: (Int32, Bool)?
|
var bannedSendVideos: (Int32, Bool)?
|
||||||
@ -60,19 +61,19 @@ extension ChatControllerImpl {
|
|||||||
} else if peer is TelegramSecretChat {
|
} else if peer is TelegramSecretChat {
|
||||||
canSendPolls = false
|
canSendPolls = false
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
if let value = channel.hasBannedPermission(.banSendPhotos) {
|
if let value = channel.hasBannedPermission(.banSendPhotos, ignoreDefault: canByPassRestrictions) {
|
||||||
bannedSendPhotos = value
|
bannedSendPhotos = value
|
||||||
}
|
}
|
||||||
if let value = channel.hasBannedPermission(.banSendVideos) {
|
if let value = channel.hasBannedPermission(.banSendVideos, ignoreDefault: canByPassRestrictions) {
|
||||||
bannedSendVideos = value
|
bannedSendVideos = value
|
||||||
}
|
}
|
||||||
if let value = channel.hasBannedPermission(.banSendFiles) {
|
if let value = channel.hasBannedPermission(.banSendFiles, ignoreDefault: canByPassRestrictions) {
|
||||||
bannedSendFiles = value
|
bannedSendFiles = value
|
||||||
}
|
}
|
||||||
if let value = channel.hasBannedPermission(.banSendText) {
|
if let value = channel.hasBannedPermission(.banSendText, ignoreDefault: canByPassRestrictions) {
|
||||||
banSendText = value
|
banSendText = value
|
||||||
}
|
}
|
||||||
if channel.hasBannedPermission(.banSendPolls) != nil {
|
if channel.hasBannedPermission(.banSendPolls, ignoreDefault: canByPassRestrictions) != nil {
|
||||||
canSendPolls = false
|
canSendPolls = false
|
||||||
}
|
}
|
||||||
} else if let group = peer as? TelegramGroup {
|
} else if let group = peer as? TelegramGroup {
|
||||||
|
@ -201,8 +201,12 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
|
|||||||
if isTextEmpty, case .broadcast = peer.info, canSendMessagesToPeer(peer) {
|
if isTextEmpty, case .broadcast = peer.info, canSendMessagesToPeer(peer) {
|
||||||
accessoryItems.append(.silentPost(chatPresentationInterfaceState.interfaceState.silentPosting))
|
accessoryItems.append(.silentPost(chatPresentationInterfaceState.interfaceState.silentPosting))
|
||||||
}
|
}
|
||||||
if peer.hasBannedPermission(.banSendStickers) != nil {
|
if let boostsToUnrestrict = chatPresentationInterfaceState.boostsToUnrestrict, boostsToUnrestrict > 0 {
|
||||||
stickersEnabled = false
|
|
||||||
|
} else {
|
||||||
|
if peer.hasBannedPermission(.banSendStickers) != nil {
|
||||||
|
stickersEnabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramGroup {
|
} else if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramGroup {
|
||||||
if peer.hasBannedPermission(.banSendStickers) {
|
if peer.hasBannedPermission(.banSendStickers) {
|
||||||
|
@ -4743,13 +4743,17 @@ private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
|||||||
case .pendingMessages:
|
case .pendingMessages:
|
||||||
relativeTimestamp = CGFloat(slowmodeState.timeout)
|
relativeTimestamp = CGFloat(slowmodeState.timeout)
|
||||||
}
|
}
|
||||||
text = stringForDuration(Int32(relativeTimestamp))
|
|
||||||
|
|
||||||
self.updateTimer?.invalidate()
|
self.updateTimer?.invalidate()
|
||||||
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
|
||||||
self?.requestUpdate()
|
if relativeTimestamp >= 0.0 {
|
||||||
}, queue: .mainQueue())
|
text = stringForDuration(Int32(relativeTimestamp))
|
||||||
self.updateTimer?.start()
|
|
||||||
|
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
||||||
|
self?.requestUpdate()
|
||||||
|
}, queue: .mainQueue())
|
||||||
|
self.updateTimer?.start()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.updateTimer?.invalidate()
|
self.updateTimer?.invalidate()
|
||||||
self.updateTimer = nil
|
self.updateTimer = nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user