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
43204554cd
commit
b4ca0637a6
@ -10222,6 +10222,10 @@ Sorry for the inconvenience.";
|
|||||||
"ReassignBoost.Boosts_any" = "%@ boosts are reassigned";
|
"ReassignBoost.Boosts_any" = "%@ boosts are reassigned";
|
||||||
"ReassignBoost.OtherChannels_1" = "%@ other channel";
|
"ReassignBoost.OtherChannels_1" = "%@ other channel";
|
||||||
"ReassignBoost.OtherChannels_any" = "%@ other channels";
|
"ReassignBoost.OtherChannels_any" = "%@ other channels";
|
||||||
|
"ReassignBoost.OtherGroups_1" = "%@ other group";
|
||||||
|
"ReassignBoost.OtherGroups_any" = "%@ other groups";
|
||||||
|
"ReassignBoost.OtherGroupsAndChannels_1" = "%@ other group and channel";
|
||||||
|
"ReassignBoost.OtherGroupsAndChannels_any" = "%@ other groups and channels";
|
||||||
|
|
||||||
"ChannelBoost.MoreBoosts.Title" = "More Boosts Needed";
|
"ChannelBoost.MoreBoosts.Title" = "More Boosts Needed";
|
||||||
"ChannelBoost.MoreBoosts.Text" = "To boost **%1$@** again, gift **Telegram Premium** to a friend and get **%2$@** additional boosts.";
|
"ChannelBoost.MoreBoosts.Text" = "To boost **%1$@** again, gift **Telegram Premium** to a friend and get **%2$@** additional boosts.";
|
||||||
@ -11247,7 +11251,7 @@ Sorry for the inconvenience.";
|
|||||||
"Chat.Giveaway.Message.Group.Participants" = "All members of this 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.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.ParticipantsMany" = "All members of the groups below:";
|
||||||
"Chat.Giveaway.Message.Group.ParticipantsNewMany" = "All users who join the groups below after this date:";
|
"Chat.Giveaway.Message.Group.ParticipantsNewMany" = "All users who join the groups below after this date:";
|
||||||
|
|
||||||
"Story.Privacy.KeepOnGroupPage" = "Post to Group Page";
|
"Story.Privacy.KeepOnGroupPage" = "Post to Group Page";
|
||||||
@ -11260,3 +11264,15 @@ Sorry for the inconvenience.";
|
|||||||
"BoostGift.Members.MaximumReached" = "You can select maximum %@ members.";
|
"BoostGift.Members.MaximumReached" = "You can select maximum %@ members.";
|
||||||
|
|
||||||
"Chat.ErrorCantBoost" = "Sorry, you can't boost this group or channel.";
|
"Chat.ErrorCantBoost" = "Sorry, you can't boost this group or channel.";
|
||||||
|
|
||||||
|
"ChannelBoost.Boost" = "Boost";
|
||||||
|
"ChannelBoost.Copy" = "Copy";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.OtherGroups_1" = "**%@** other listed group";
|
||||||
|
"Chat.Giveaway.Info.OtherGroups_any" = "**%@** other listed groups";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.OtherGroupsAndChannels_1" = "**%@** other listed group and channel";
|
||||||
|
"Chat.Giveaway.Info.OtherGroupsAndChannels_any" = "**%@** other listed groups and channels";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.OtherChannelsAndGroups_1" = "**%@** other listed channel and group";
|
||||||
|
"Chat.Giveaway.Info.OtherChannelsAndGroups_any" = "**%@** other listed channels and groups";
|
||||||
|
@ -134,6 +134,7 @@ final class BadgeLabelView: UIView {
|
|||||||
} else {
|
} else {
|
||||||
itemTransition = transition.withAnimation(.none)
|
itemTransition = transition.withAnimation(.none)
|
||||||
itemView = StackView()
|
itemView = StackView()
|
||||||
|
itemView.color = self.color
|
||||||
self.itemViews[i] = itemView
|
self.itemViews[i] = itemView
|
||||||
self.addSubview(itemView)
|
self.addSubview(itemView)
|
||||||
}
|
}
|
||||||
|
@ -70,21 +70,38 @@ public func presentGiveawayInfoController(
|
|||||||
onlyNewSubscribers = true
|
onlyNewSubscribers = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var channelsCount: Int32 = 1
|
|
||||||
if let giveaway {
|
|
||||||
channelsCount = Int32(giveaway.channelPeerIds.count)
|
|
||||||
} else if let giveawayResults {
|
|
||||||
channelsCount = 1 + giveawayResults.additionalChannelsCount
|
|
||||||
}
|
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
|
||||||
|
|
||||||
let author = message.forwardInfo?.author ?? message.author?._asPeer()
|
let author = message.forwardInfo?.author ?? message.author?._asPeer()
|
||||||
var isGroup = false
|
var isGroup = false
|
||||||
if let channel = author as? TelegramChannel, case .group = channel.info {
|
if let channel = author as? TelegramChannel, case .group = channel.info {
|
||||||
isGroup = true
|
isGroup = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var groupsAndChannels = false
|
||||||
|
var channelsCount: Int32 = 1
|
||||||
|
if let giveaway {
|
||||||
|
channelsCount = Int32(giveaway.channelPeerIds.count)
|
||||||
|
|
||||||
|
var channelCount = 0
|
||||||
|
var groupCount = 0
|
||||||
|
for peerId in giveaway.channelPeerIds {
|
||||||
|
if let peer = message.peers[peerId] as? TelegramChannel {
|
||||||
|
switch peer.info {
|
||||||
|
case .broadcast:
|
||||||
|
channelCount += 1
|
||||||
|
case .group:
|
||||||
|
groupCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if groupCount > 0 && channelCount > 0 {
|
||||||
|
groupsAndChannels = true
|
||||||
|
}
|
||||||
|
} else if let giveawayResults {
|
||||||
|
channelsCount = 1 + giveawayResults.additionalChannelsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
var peerName = ""
|
var peerName = ""
|
||||||
if let channel = author as? TelegramChannel {
|
if let channel = author as? TelegramChannel {
|
||||||
peerName = EnginePeer(channel).compactDisplayTitle
|
peerName = EnginePeer(channel).compactDisplayTitle
|
||||||
@ -132,18 +149,43 @@ public func presentGiveawayInfoController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var otherText: String = ""
|
||||||
|
if channelsCount > 1 {
|
||||||
|
if isGroup {
|
||||||
|
if groupsAndChannels {
|
||||||
|
if channelsCount == 2 {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))
|
||||||
|
} else {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroupsAndChannels(Int32(channelsCount - 1))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroups(Int32(channelsCount - 1))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if groupsAndChannels {
|
||||||
|
if channelsCount == 2 {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroups(Int32(channelsCount - 1))
|
||||||
|
} else {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannelsAndGroups(Int32(channelsCount - 1))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ending: String
|
let ending: String
|
||||||
if onlyNewSubscribers {
|
if onlyNewSubscribers {
|
||||||
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(quantity)
|
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(quantity)
|
||||||
if channelsCount > 1 {
|
if channelsCount > 1 {
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNewMany(untilDate, randomUsers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1)), startDate).string
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNewMany(untilDate, randomUsers, peerName, otherText, startDate).string
|
||||||
} else {
|
} else {
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNew(untilDate, randomUsers, peerName, startDate).string
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNew(untilDate, randomUsers, peerName, startDate).string
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let randomSubscribers = isGroup ? presentationData.strings.Chat_Giveaway_Info_Group_RandomMembers(quantity) : presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(quantity)
|
let randomSubscribers = isGroup ? presentationData.strings.Chat_Giveaway_Info_Group_RandomMembers(quantity) : presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(quantity)
|
||||||
if channelsCount > 1 {
|
if channelsCount > 1 {
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingMany(untilDate, randomSubscribers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))).string
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingMany(untilDate, randomSubscribers, peerName, otherText).string
|
||||||
} else {
|
} else {
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_Ongoing(untilDate, randomSubscribers, peerName).string
|
ending = presentationData.strings.Chat_Giveaway_Info_Ongoing(untilDate, randomSubscribers, peerName).string
|
||||||
}
|
}
|
||||||
@ -153,7 +195,7 @@ public func presentGiveawayInfoController(
|
|||||||
switch status {
|
switch status {
|
||||||
case .notQualified:
|
case .notQualified:
|
||||||
if channelsCount > 1 {
|
if channelsCount > 1 {
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotQualifiedMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1)), untilDate).string
|
participation = presentationData.strings.Chat_Giveaway_Info_NotQualifiedMany(peerName, otherText, untilDate).string
|
||||||
} else {
|
} else {
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotQualified(peerName, untilDate).string
|
participation = presentationData.strings.Chat_Giveaway_Info_NotQualified(peerName, untilDate).string
|
||||||
}
|
}
|
||||||
@ -177,7 +219,7 @@ public func presentGiveawayInfoController(
|
|||||||
}
|
}
|
||||||
case .participating:
|
case .participating:
|
||||||
if channelsCount > 1 {
|
if channelsCount > 1 {
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_ParticipatingMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))).string
|
participation = presentationData.strings.Chat_Giveaway_Info_ParticipatingMany(peerName, otherText).string
|
||||||
} else {
|
} else {
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_Participating(peerName).string
|
participation = presentationData.strings.Chat_Giveaway_Info_Participating(peerName).string
|
||||||
}
|
}
|
||||||
|
@ -918,10 +918,9 @@ private final class SheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
contentSize.height += linkButton.size.height + 16.0
|
contentSize.height += linkButton.size.height + 16.0
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
let boostButton = boostButton.update(
|
let boostButton = boostButton.update(
|
||||||
component: SolidRoundedButtonComponent(
|
component: SolidRoundedButtonComponent(
|
||||||
title: "Boost",
|
title: strings.ChannelBoost_Boost,
|
||||||
theme: SolidRoundedButtonComponent.Theme(
|
theme: SolidRoundedButtonComponent.Theme(
|
||||||
backgroundColor: .black,
|
backgroundColor: .black,
|
||||||
backgroundColors: buttonGradientColors,
|
backgroundColors: buttonGradientColors,
|
||||||
@ -945,7 +944,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let copyButton = copyButton.update(
|
let copyButton = copyButton.update(
|
||||||
component: SolidRoundedButtonComponent(
|
component: SolidRoundedButtonComponent(
|
||||||
title: "Copy",
|
title: strings.ChannelBoost_Copy,
|
||||||
theme: SolidRoundedButtonComponent.Theme(
|
theme: SolidRoundedButtonComponent.Theme(
|
||||||
backgroundColor: .black,
|
backgroundColor: .black,
|
||||||
backgroundColors: buttonGradientColors,
|
backgroundColors: buttonGradientColors,
|
||||||
@ -1185,6 +1184,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
private final class BoostLevelsContainerComponent: CombinedComponent {
|
private final class BoostLevelsContainerComponent: CombinedComponent {
|
||||||
class ExternalState {
|
class ExternalState {
|
||||||
var isGroup: Bool = false
|
var isGroup: Bool = false
|
||||||
|
var contentHeight: CGFloat = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
@ -1201,6 +1201,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
let openStats: (() -> Void)?
|
let openStats: (() -> Void)?
|
||||||
let openGift: (() -> Void)?
|
let openGift: (() -> Void)?
|
||||||
let openPeer: ((EnginePeer) -> Void)?
|
let openPeer: ((EnginePeer) -> Void)?
|
||||||
|
let updated: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
@ -1216,7 +1217,8 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
dismiss: @escaping () -> Void,
|
dismiss: @escaping () -> Void,
|
||||||
openStats: (() -> Void)?,
|
openStats: (() -> Void)?,
|
||||||
openGift: (() -> Void)?,
|
openGift: (() -> Void)?,
|
||||||
openPeer: ((EnginePeer) -> Void)?
|
openPeer: ((EnginePeer) -> Void)?,
|
||||||
|
updated: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
@ -1232,6 +1234,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
self.openStats = openStats
|
self.openStats = openStats
|
||||||
self.openGift = openGift
|
self.openGift = openGift
|
||||||
self.openPeer = openPeer
|
self.openPeer = openPeer
|
||||||
|
self.updated = updated
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: BoostLevelsContainerComponent, rhs: BoostLevelsContainerComponent) -> Bool {
|
static func ==(lhs: BoostLevelsContainerComponent, rhs: BoostLevelsContainerComponent) -> Bool {
|
||||||
@ -1264,7 +1267,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
private(set) var peer: EnginePeer?
|
private(set) var peer: EnginePeer?
|
||||||
|
|
||||||
init(context: AccountContext, peerId: EnginePeer.Id) {
|
init(context: AccountContext, peerId: EnginePeer.Id, updated: @escaping () -> Void) {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.disposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
self.disposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||||
@ -1274,6 +1277,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.updated()
|
self.updated()
|
||||||
|
updated()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,7 +1287,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeState() -> State {
|
func makeState() -> State {
|
||||||
return State(context: self.context, peerId: self.peerId)
|
return State(context: self.context, peerId: self.peerId, updated: self.updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: Body {
|
static var body: Body {
|
||||||
@ -1295,6 +1299,8 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
let statsButton = Child(Button.self)
|
let statsButton = Child(Button.self)
|
||||||
let closeButton = Child(Button.self)
|
let closeButton = Child(Button.self)
|
||||||
|
|
||||||
|
let externalScrollState = ScrollComponent<Empty>.ExternalState()
|
||||||
|
|
||||||
return { context in
|
return { context in
|
||||||
let state = context.state
|
let state = context.state
|
||||||
|
|
||||||
@ -1337,6 +1343,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
openPeer: component.openPeer
|
openPeer: component.openPeer
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
externalState: externalScrollState,
|
||||||
contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 0.0, right: 0.0),
|
contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 0.0, right: 0.0),
|
||||||
contentOffsetUpdated: { [weak state] topContentOffset, _ in
|
contentOffsetUpdated: { [weak state] topContentOffset, _ in
|
||||||
state?.topContentOffset = topContentOffset
|
state?.topContentOffset = topContentOffset
|
||||||
@ -1349,6 +1356,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
|
|||||||
availableSize: context.availableSize,
|
availableSize: context.availableSize,
|
||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
component.externalState.contentHeight = externalScrollState.contentHeight
|
||||||
|
|
||||||
let background = background.update(
|
let background = background.update(
|
||||||
component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor),
|
component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor),
|
||||||
@ -1563,11 +1571,11 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
let footerContainerView: UIView
|
let footerContainerView: UIView
|
||||||
let footerView: ComponentHostView<Empty>
|
let footerView: ComponentHostView<Empty>
|
||||||
|
|
||||||
private let externalState = BoostLevelsContainerComponent.ExternalState()
|
private let containerExternalState = 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?)?
|
||||||
|
|
||||||
private let hapticFeedback = HapticFeedback()
|
private let hapticFeedback = HapticFeedback()
|
||||||
|
|
||||||
@ -1633,7 +1641,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
self.updatedState.set(.single(InternalBoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: boosts + 1)))
|
self.updatedState.set(.single(InternalBoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: boosts + 1)))
|
||||||
|
|
||||||
if let (replacedBoosts, inChannels) = controller.replacedBoosts {
|
if let (replacedBoosts, sourcePeers) = controller.replacedBoosts {
|
||||||
currentMyBoostCount += 1
|
currentMyBoostCount += 1
|
||||||
|
|
||||||
self.boostState = initialState.displayData(myBoostCount: myBoostCount, currentMyBoostCount: 1)
|
self.boostState = initialState.displayData(myBoostCount: myBoostCount, currentMyBoostCount: 1)
|
||||||
@ -1643,7 +1651,29 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
Queue.mainQueue().after(0.3) {
|
Queue.mainQueue().after(0.3) {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let undoController = UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Premium/BoostReplaceIcon"), color: .white)!, title: nil, text: presentationData.strings.ReassignBoost_Success(presentationData.strings.ReassignBoost_Boosts(replacedBoosts), presentationData.strings.ReassignBoost_OtherChannels(inChannels)).string, round: false, undoText: nil), elevatedLayout: false, position: .top, action: { _ in return true })
|
|
||||||
|
var groupCount: Int32 = 0
|
||||||
|
var channelCount: Int32 = 0
|
||||||
|
for peer in sourcePeers {
|
||||||
|
if case let .channel(channel) = peer {
|
||||||
|
switch channel.info {
|
||||||
|
case .broadcast:
|
||||||
|
channelCount += 1
|
||||||
|
case .group:
|
||||||
|
groupCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let otherText: String
|
||||||
|
if channelCount > 0 && groupCount == 0 {
|
||||||
|
otherText = presentationData.strings.ReassignBoost_OtherChannels(channelCount)
|
||||||
|
} else if groupCount > 0 && channelCount == 0 {
|
||||||
|
otherText = presentationData.strings.ReassignBoost_OtherGroups(groupCount)
|
||||||
|
} else {
|
||||||
|
otherText = presentationData.strings.ReassignBoost_OtherGroupsAndChannels(Int32(sourcePeers.count))
|
||||||
|
}
|
||||||
|
let text = presentationData.strings.ReassignBoost_Success(presentationData.strings.ReassignBoost_Boosts(replacedBoosts), otherText).string
|
||||||
|
let undoController = UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Premium/BoostReplaceIcon"), color: .white)!, title: nil, text: text, round: false, undoText: nil), elevatedLayout: false, position: .top, action: { _ in return true })
|
||||||
controller.present(undoController, in: .current)
|
controller.present(undoController, in: .current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1732,31 +1762,10 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
self.currentLayout = layout
|
self.currentLayout = layout
|
||||||
|
|
||||||
self.dim.frame = CGRect(origin: CGPoint(x: 0.0, y: -layout.size.height), size: CGSize(width: layout.size.width, height: layout.size.height * 3.0))
|
self.dim.frame = CGRect(origin: CGPoint(x: 0.0, y: -layout.size.height), size: CGSize(width: layout.size.width, height: layout.size.height * 3.0))
|
||||||
|
|
||||||
var effectiveExpanded = self.isExpanded
|
|
||||||
if case .regular = layout.metrics.widthClass {
|
|
||||||
effectiveExpanded = true
|
|
||||||
}
|
|
||||||
|
|
||||||
let isLandscape = layout.orientation == .landscape
|
let isLandscape = layout.orientation == .landscape
|
||||||
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
|
||||||
let topInset: CGFloat
|
|
||||||
if let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments {
|
|
||||||
if effectiveExpanded {
|
|
||||||
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
|
||||||
} else {
|
|
||||||
topInset = max(0.0, panInitialTopInset + min(0.0, panOffset))
|
|
||||||
}
|
|
||||||
} else if let dismissOffset = self.dismissOffset, !dismissOffset.isZero {
|
|
||||||
topInset = edgeTopInset * dismissOffset
|
|
||||||
} else {
|
|
||||||
topInset = effectiveExpanded ? 0.0 : edgeTopInset
|
|
||||||
}
|
|
||||||
transition.setFrame(view: self.wrappingView, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: layout.size), completion: nil)
|
|
||||||
|
|
||||||
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / self.defaultTopInset)
|
|
||||||
self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition)
|
|
||||||
|
|
||||||
|
var containerTopInset: CGFloat = 0.0
|
||||||
let clipFrame: CGRect
|
let clipFrame: CGRect
|
||||||
if layout.metrics.widthClass == .compact {
|
if layout.metrics.widthClass == .compact {
|
||||||
self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.25)
|
self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.25)
|
||||||
@ -1778,7 +1787,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
clipFrame = CGRect(origin: CGPoint(), size: layout.size)
|
clipFrame = CGRect(origin: CGPoint(), size: layout.size)
|
||||||
} else {
|
} else {
|
||||||
let coveredByModalTransition: CGFloat = 0.0
|
let coveredByModalTransition: CGFloat = 0.0
|
||||||
var containerTopInset: CGFloat = 10.0
|
containerTopInset = 10.0
|
||||||
if let statusBarHeight = layout.statusBarHeight {
|
if let statusBarHeight = layout.statusBarHeight {
|
||||||
containerTopInset += statusBarHeight
|
containerTopInset += statusBarHeight
|
||||||
}
|
}
|
||||||
@ -1806,19 +1815,45 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
transition.setFrame(view: self.containerView, frame: clipFrame)
|
transition.setFrame(view: self.containerView, frame: clipFrame)
|
||||||
|
|
||||||
|
var effectiveExpanded = self.isExpanded
|
||||||
|
if case .regular = layout.metrics.widthClass {
|
||||||
|
effectiveExpanded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updated(transition: transition)
|
||||||
|
|
||||||
|
let contentHeight = self.containerExternalState.contentHeight
|
||||||
|
if contentHeight > 0.0 && contentHeight < 400.0, let view = self.footerView.componentView as? FooterComponent.View {
|
||||||
|
view.backgroundView.alpha = 0.0
|
||||||
|
view.separator.opacity = 0.0
|
||||||
|
}
|
||||||
|
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
||||||
|
|
||||||
|
let topInset: CGFloat
|
||||||
|
if let (panInitialTopInset, panOffset, _) = self.panGestureArguments {
|
||||||
|
if effectiveExpanded {
|
||||||
|
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset))
|
||||||
|
} else {
|
||||||
|
topInset = max(0.0, panInitialTopInset + min(0.0, panOffset))
|
||||||
|
}
|
||||||
|
} else if let dismissOffset = self.dismissOffset, !dismissOffset.isZero {
|
||||||
|
topInset = edgeTopInset * dismissOffset
|
||||||
|
} else {
|
||||||
|
topInset = effectiveExpanded ? 0.0 : edgeTopInset
|
||||||
|
}
|
||||||
|
transition.setFrame(view: self.wrappingView, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: layout.size), completion: nil)
|
||||||
|
|
||||||
var footerHeight: CGFloat = 8.0 + 50.0
|
let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / self.defaultTopInset)
|
||||||
footerHeight += layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : 8.0
|
self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition)
|
||||||
|
|
||||||
|
let footerHeight = self.footerHeight
|
||||||
let convertedFooterFrame = self.view.convert(CGRect(origin: CGPoint(x: clipFrame.minX, y: clipFrame.maxY - footerHeight), size: CGSize(width: clipFrame.width, height: footerHeight)), to: self.containerView)
|
let convertedFooterFrame = self.view.convert(CGRect(origin: CGPoint(x: clipFrame.minX, y: clipFrame.maxY - footerHeight), size: CGSize(width: clipFrame.width, height: footerHeight)), to: self.containerView)
|
||||||
transition.setFrame(view: self.footerContainerView, frame: convertedFooterFrame)
|
transition.setFrame(view: self.footerContainerView, frame: convertedFooterFrame)
|
||||||
|
|
||||||
self.updated(transition: transition)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var boostState: InternalBoostState.DisplayData?
|
private var boostState: InternalBoostState.DisplayData?
|
||||||
func updated(transition: Transition) {
|
func updated(transition: Transition) {
|
||||||
guard let controller = self.controller, let layout = self.currentLayout else {
|
guard let controller = self.controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let contentSize = self.contentView.update(
|
let contentSize = self.contentView.update(
|
||||||
@ -1828,7 +1863,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,
|
externalState: self.containerExternalState,
|
||||||
peerId: controller.peerId,
|
peerId: controller.peerId,
|
||||||
mode: controller.mode,
|
mode: controller.mode,
|
||||||
status: controller.status,
|
status: controller.status,
|
||||||
@ -1867,7 +1902,10 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
},
|
},
|
||||||
openStats: controller.openStats,
|
openStats: controller.openStats,
|
||||||
openGift: controller.openGift,
|
openGift: controller.openGift,
|
||||||
openPeer: controller.openPeer
|
openPeer: controller.openPeer,
|
||||||
|
updated: { [weak self] in
|
||||||
|
self?.controller?.requestLayout(transition: .immediate)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
environment: {},
|
environment: {},
|
||||||
@ -1875,14 +1913,13 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
)
|
)
|
||||||
self.contentView.frame = CGRect(origin: .zero, size: contentSize)
|
self.contentView.frame = CGRect(origin: .zero, size: contentSize)
|
||||||
|
|
||||||
var footerHeight: CGFloat = 8.0 + 50.0
|
let footerHeight = self.footerHeight
|
||||||
footerHeight += layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : 8.0
|
|
||||||
|
|
||||||
let actionTitle: String
|
let actionTitle: String
|
||||||
if self.currentMyBoostCount > 0 {
|
if self.currentMyBoostCount > 0 {
|
||||||
actionTitle = self.presentationData.strings.ChannelBoost_BoostAgain
|
actionTitle = self.presentationData.strings.ChannelBoost_BoostAgain
|
||||||
} else {
|
} else {
|
||||||
actionTitle = self.externalState.isGroup ? self.presentationData.strings.GroupBoost_BoostGroup : self.presentationData.strings.ChannelBoost_BoostChannel
|
actionTitle = self.containerExternalState.isGroup ? self.presentationData.strings.GroupBoost_BoostGroup : self.presentationData.strings.ChannelBoost_BoostChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
let footerSize = self.footerView.update(
|
let footerSize = self.footerView.update(
|
||||||
@ -1924,6 +1961,15 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var footerHeight: CGFloat {
|
||||||
|
guard let layout = self.currentLayout else {
|
||||||
|
return 58.0
|
||||||
|
}
|
||||||
|
var footerHeight: CGFloat = 8.0 + 50.0
|
||||||
|
footerHeight += layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : 8.0
|
||||||
|
return footerHeight
|
||||||
|
}
|
||||||
|
|
||||||
private var defaultTopInset: CGFloat {
|
private var defaultTopInset: CGFloat {
|
||||||
guard let layout = self.currentLayout else {
|
guard let layout = self.currentLayout else {
|
||||||
return 210.0
|
return 210.0
|
||||||
@ -1933,16 +1979,27 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
let bottomInset: CGFloat = layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : bottomPanelPadding
|
let bottomInset: CGFloat = layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : bottomPanelPadding
|
||||||
let panelHeight: CGFloat = bottomPanelPadding + 50.0 + bottomInset + 28.0
|
let panelHeight: CGFloat = bottomPanelPadding + 50.0 + bottomInset + 28.0
|
||||||
|
|
||||||
return layout.size.height - layout.size.width - 128.0 - panelHeight
|
var defaultTopInset = layout.size.height - layout.size.width - 128.0 - panelHeight
|
||||||
|
|
||||||
|
let containerTopInset = 10.0 + (layout.statusBarHeight ?? 0.0)
|
||||||
|
let contentHeight = self.containerExternalState.contentHeight
|
||||||
|
let footerHeight = self.footerHeight
|
||||||
|
if contentHeight > 0.0 {
|
||||||
|
let delta = (layout.size.height - defaultTopInset - containerTopInset) - contentHeight - footerHeight - 16.0
|
||||||
|
if delta > 0.0 {
|
||||||
|
defaultTopInset += delta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultTopInset
|
||||||
} else {
|
} else {
|
||||||
return 210.0
|
return 210.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func findVerticalScrollView(view: UIView?) -> (UIScrollView, ListView?)? {
|
private func findVerticalScrollView(view: UIView?) -> UIScrollView? {
|
||||||
if let view = view {
|
if let view = view {
|
||||||
if let view = view as? UIScrollView, view.contentSize.height > view.contentSize.width {
|
if let view = view as? UIScrollView, view.contentSize.height > view.contentSize.width {
|
||||||
return (view, nil)
|
return view
|
||||||
}
|
}
|
||||||
return findVerticalScrollView(view: view.superview)
|
return findVerticalScrollView(view: view.superview)
|
||||||
} else {
|
} else {
|
||||||
@ -1963,12 +2020,13 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
let point = recognizer.location(in: self.view)
|
let point = recognizer.location(in: self.view)
|
||||||
let currentHitView = self.hitTest(point, with: nil)
|
let currentHitView = self.hitTest(point, with: nil)
|
||||||
|
|
||||||
var scrollViewAndListNode = self.findVerticalScrollView(view: currentHitView)
|
var scrollView = self.findVerticalScrollView(view: currentHitView)
|
||||||
if scrollViewAndListNode?.0.frame.height == self.frame.width {
|
if scrollView?.frame.height == self.frame.width {
|
||||||
scrollViewAndListNode = nil
|
scrollView = nil
|
||||||
|
}
|
||||||
|
if scrollView?.isDescendant(of: self.view) == false {
|
||||||
|
scrollView = nil
|
||||||
}
|
}
|
||||||
let scrollView = scrollViewAndListNode?.0
|
|
||||||
let listNode = scrollViewAndListNode?.1
|
|
||||||
|
|
||||||
let topInset: CGFloat
|
let topInset: CGFloat
|
||||||
if self.isExpanded {
|
if self.isExpanded {
|
||||||
@ -1977,25 +2035,19 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
topInset = edgeTopInset
|
topInset = edgeTopInset
|
||||||
}
|
}
|
||||||
|
|
||||||
self.panGestureArguments = (topInset, 0.0, scrollView, listNode)
|
self.panGestureArguments = (topInset, 0.0, scrollView)
|
||||||
case .changed:
|
case .changed:
|
||||||
guard let (topInset, panOffset, scrollView, listNode) = self.panGestureArguments else {
|
guard let (topInset, panOffset, scrollView) = self.panGestureArguments else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let visibleContentOffset = listNode?.visibleContentOffset()
|
|
||||||
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
||||||
|
|
||||||
var translation = recognizer.translation(in: self.view).y
|
var translation = recognizer.translation(in: self.view).y
|
||||||
|
|
||||||
var currentOffset = topInset + translation
|
var currentOffset = topInset + translation
|
||||||
|
|
||||||
let epsilon = 1.0
|
let epsilon = 1.0
|
||||||
if case let .known(value) = visibleContentOffset, value <= epsilon {
|
if let scrollView = scrollView, contentOffset <= -scrollView.contentInset.top + epsilon {
|
||||||
if let scrollView = scrollView {
|
|
||||||
scrollView.bounces = false
|
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: 0.0), animated: false)
|
|
||||||
}
|
|
||||||
} else if let scrollView = scrollView, contentOffset <= -scrollView.contentInset.top + epsilon {
|
|
||||||
scrollView.bounces = false
|
scrollView.bounces = false
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
} else if let scrollView = scrollView {
|
} else if let scrollView = scrollView {
|
||||||
@ -2012,7 +2064,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
translation = max(0.0, translation)
|
translation = max(0.0, translation)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.panGestureArguments = (topInset, translation, scrollView, listNode)
|
self.panGestureArguments = (topInset, translation, scrollView)
|
||||||
|
|
||||||
if !self.isExpanded {
|
if !self.isExpanded {
|
||||||
if currentOffset > 0.0, let scrollView = scrollView {
|
if currentOffset > 0.0, let scrollView = scrollView {
|
||||||
@ -2031,23 +2083,18 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
self.containerLayoutUpdated(layout: layout, transition: .immediate)
|
self.containerLayoutUpdated(layout: layout, transition: .immediate)
|
||||||
case .ended:
|
case .ended:
|
||||||
guard let (currentTopInset, panOffset, scrollView, listNode) = self.panGestureArguments else {
|
guard let (currentTopInset, panOffset, scrollView) = self.panGestureArguments else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.panGestureArguments = nil
|
self.panGestureArguments = nil
|
||||||
|
|
||||||
let visibleContentOffset = listNode?.visibleContentOffset()
|
|
||||||
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
let contentOffset = scrollView?.contentOffset.y ?? 0.0
|
||||||
|
|
||||||
let translation = recognizer.translation(in: self.view).y
|
let translation = recognizer.translation(in: self.view).y
|
||||||
var velocity = recognizer.velocity(in: self.view)
|
var velocity = recognizer.velocity(in: self.view)
|
||||||
|
|
||||||
if self.isExpanded {
|
if self.isExpanded {
|
||||||
if case let .known(value) = visibleContentOffset, value > 0.1 {
|
if contentOffset > 0.1 {
|
||||||
velocity = CGPoint()
|
|
||||||
} else if case .unknown = visibleContentOffset {
|
|
||||||
velocity = CGPoint()
|
|
||||||
} else if contentOffset > 0.1 {
|
|
||||||
velocity = CGPoint()
|
velocity = CGPoint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2072,9 +2119,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
} else if self.isExpanded {
|
} else if self.isExpanded {
|
||||||
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
||||||
self.isExpanded = false
|
self.isExpanded = false
|
||||||
if let listNode = listNode {
|
if let scrollView = scrollView {
|
||||||
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
|
||||||
} else if let scrollView = scrollView {
|
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2089,21 +2134,13 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
self.containerLayoutUpdated(layout: layout, transition: Transition(.animated(duration: 0.3, curve: .easeInOut)))
|
self.containerLayoutUpdated(layout: layout, transition: Transition(.animated(duration: 0.3, curve: .easeInOut)))
|
||||||
}
|
}
|
||||||
} else if scrollView != nil, (velocity.y < -300.0 || offset < topInset / 2.0) {
|
} else if scrollView != nil, (velocity.y < -300.0 || offset < topInset / 2.0) {
|
||||||
if velocity.y > -2200.0 && velocity.y < -300.0, let listNode = listNode {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset)
|
let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset)
|
||||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
||||||
self.isExpanded = true
|
self.isExpanded = true
|
||||||
|
|
||||||
self.containerLayoutUpdated(layout: layout, transition: Transition(transition))
|
self.containerLayoutUpdated(layout: layout, transition: Transition(transition))
|
||||||
} else {
|
} else {
|
||||||
if let listNode = listNode {
|
if let scrollView = scrollView {
|
||||||
listNode.scroller.setContentOffset(CGPoint(), animated: false)
|
|
||||||
} else if let scrollView = scrollView {
|
|
||||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2205,11 +2242,15 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
var dismissReplaceImpl: (() -> Void)?
|
var dismissReplaceImpl: (() -> Void)?
|
||||||
let replaceController = ReplaceBoostScreen(context: context, peerId: peerId, myBoostStatus: myBoostStatus, replaceBoosts: { slots in
|
let replaceController = ReplaceBoostScreen(context: context, peerId: peerId, myBoostStatus: myBoostStatus, replaceBoosts: { slots in
|
||||||
var channelIds = Set<EnginePeer.Id>()
|
var sourcePeerIds = Set<EnginePeer.Id>()
|
||||||
|
var sourcePeers: [EnginePeer] = []
|
||||||
for boost in myBoostStatus.boosts {
|
for boost in myBoostStatus.boosts {
|
||||||
if slots.contains(boost.slot) {
|
if slots.contains(boost.slot) {
|
||||||
if let peer = boost.peer {
|
if let peer = boost.peer {
|
||||||
channelIds.insert(peer.id)
|
if !sourcePeerIds.contains(peer.id) {
|
||||||
|
sourcePeerIds.insert(peer.id)
|
||||||
|
sourcePeers.append(peer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2228,7 +2269,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
mode: mode,
|
mode: mode,
|
||||||
status: status,
|
status: status,
|
||||||
myBoostStatus: myBoostStatus,
|
myBoostStatus: myBoostStatus,
|
||||||
replacedBoosts: (Int32(slots.count), Int32(channelIds.count)),
|
replacedBoosts: (Int32(slots.count), sourcePeers),
|
||||||
openStats: nil, openGift: nil, openPeer: openPeer, forceDark: forceDark
|
openStats: nil, openGift: nil, openPeer: openPeer, forceDark: forceDark
|
||||||
)
|
)
|
||||||
if let navigationController {
|
if let navigationController {
|
||||||
@ -2379,7 +2420,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
private let mode: Mode
|
private let mode: Mode
|
||||||
private let status: ChannelBoostStatus?
|
private let status: ChannelBoostStatus?
|
||||||
private let myBoostStatus: MyBoostStatus?
|
private let myBoostStatus: MyBoostStatus?
|
||||||
private let replacedBoosts: (Int32, Int32)?
|
private let replacedBoosts: (Int32, [EnginePeer])?
|
||||||
private let openStats: (() -> Void)?
|
private let openStats: (() -> Void)?
|
||||||
private let openGift: (() -> Void)?
|
private let openGift: (() -> Void)?
|
||||||
private let openPeer: ((EnginePeer) -> Void)?
|
private let openPeer: ((EnginePeer) -> Void)?
|
||||||
@ -2395,7 +2436,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
mode: Mode,
|
mode: Mode,
|
||||||
status: ChannelBoostStatus?,
|
status: ChannelBoostStatus?,
|
||||||
myBoostStatus: MyBoostStatus? = nil,
|
myBoostStatus: MyBoostStatus? = nil,
|
||||||
replacedBoosts: (Int32, Int32)? = nil,
|
replacedBoosts: (Int32, [EnginePeer])? = nil,
|
||||||
openStats: (() -> Void)? = nil,
|
openStats: (() -> Void)? = nil,
|
||||||
openGift: (() -> Void)? = nil,
|
openGift: (() -> Void)? = nil,
|
||||||
openPeer: ((EnginePeer) -> Void)? = nil,
|
openPeer: ((EnginePeer) -> Void)? = nil,
|
||||||
@ -2495,8 +2536,8 @@ private final class FooterComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class View: UIView {
|
final class View: UIView {
|
||||||
private let backgroundView: BlurredBackgroundView
|
let backgroundView: BlurredBackgroundView
|
||||||
private let separator = SimpleLayer()
|
let separator = SimpleLayer()
|
||||||
|
|
||||||
private let button = ComponentView<Empty>()
|
private let button = ComponentView<Empty>()
|
||||||
|
|
||||||
|
@ -22,7 +22,12 @@ final class ScrollChildEnvironment: Equatable {
|
|||||||
final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
||||||
typealias EnvironmentType = ChildEnvironment
|
typealias EnvironmentType = ChildEnvironment
|
||||||
|
|
||||||
|
class ExternalState {
|
||||||
|
var contentHeight: CGFloat = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>
|
let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>
|
||||||
|
let externalState: ExternalState?
|
||||||
let contentInsets: UIEdgeInsets
|
let contentInsets: UIEdgeInsets
|
||||||
let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void
|
let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void
|
||||||
let contentOffsetWillCommit: (UnsafeMutablePointer<CGPoint>) -> Void
|
let contentOffsetWillCommit: (UnsafeMutablePointer<CGPoint>) -> Void
|
||||||
@ -30,12 +35,14 @@ final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>,
|
content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>,
|
||||||
|
externalState: ExternalState? = nil,
|
||||||
contentInsets: UIEdgeInsets,
|
contentInsets: UIEdgeInsets,
|
||||||
contentOffsetUpdated: @escaping (_ top: CGFloat, _ bottom: CGFloat) -> Void,
|
contentOffsetUpdated: @escaping (_ top: CGFloat, _ bottom: CGFloat) -> Void,
|
||||||
contentOffsetWillCommit: @escaping (UnsafeMutablePointer<CGPoint>) -> Void,
|
contentOffsetWillCommit: @escaping (UnsafeMutablePointer<CGPoint>) -> Void,
|
||||||
resetScroll: ActionSlot<Void> = ActionSlot()
|
resetScroll: ActionSlot<Void> = ActionSlot()
|
||||||
) {
|
) {
|
||||||
self.content = content
|
self.content = content
|
||||||
|
self.externalState = externalState
|
||||||
self.contentInsets = contentInsets
|
self.contentInsets = contentInsets
|
||||||
self.contentOffsetUpdated = contentOffsetUpdated
|
self.contentOffsetUpdated = contentOffsetUpdated
|
||||||
self.contentOffsetWillCommit = contentOffsetWillCommit
|
self.contentOffsetWillCommit = contentOffsetWillCommit
|
||||||
@ -121,6 +128,7 @@ final class ScrollComponent<ChildEnvironment: Equatable>: Component {
|
|||||||
if self.scrollIndicatorInsets != component.contentInsets {
|
if self.scrollIndicatorInsets != component.contentInsets {
|
||||||
self.scrollIndicatorInsets = component.contentInsets
|
self.scrollIndicatorInsets = component.contentInsets
|
||||||
}
|
}
|
||||||
|
component.externalState?.contentHeight = contentSize.height
|
||||||
|
|
||||||
self.component = component
|
self.component = component
|
||||||
|
|
||||||
|
@ -752,7 +752,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
|
|
||||||
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(13.0), textColor: self.theme.chat.inputPanel.secondaryTextColor)
|
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(13.0), textColor: self.theme.chat.inputPanel.secondaryTextColor)
|
||||||
|
|
||||||
var constrainedWidth = size.width / 2.0 - 56.0
|
var constrainedWidth = size.width - leftInset - rightInset - 32.0 - joinButtonSize.width - 60.0
|
||||||
if isScheduled {
|
if isScheduled {
|
||||||
constrainedWidth = size.width - 100.0
|
constrainedWidth = size.width - 100.0
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user