Various improvements
This commit is contained in:
parent
d5ccfe2812
commit
e279f224a1
20 changed files with 383 additions and 559 deletions
|
|
@ -3,22 +3,23 @@ import UIKit
|
|||
import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
import SolidRoundedButtonNode
|
||||
import ComponentFlow
|
||||
import ButtonComponent
|
||||
import EdgeEffect
|
||||
|
||||
final class InviteContactsCountPanelNode: ASDisplayNode {
|
||||
private let theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
private let action: () -> Void
|
||||
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let button: SolidRoundedButtonNode
|
||||
|
||||
private let edgeEffectView = EdgeEffectView()
|
||||
private let button = ComponentView<Empty>()
|
||||
|
||||
private var validLayout: (CGFloat, CGFloat, CGFloat)?
|
||||
|
||||
var count: Int = 0 {
|
||||
didSet {
|
||||
if self.count != oldValue && self.count > 0 {
|
||||
self.button.title = self.strings.Contacts_InviteContacts(Int32(self.count))
|
||||
|
||||
if let (width, sideInset, bottomInset) = self.validLayout {
|
||||
let _ = self.updateLayout(width: width, sideInset: sideInset, bottomInset: bottomInset, transition: .immediate)
|
||||
}
|
||||
|
|
@ -29,37 +30,75 @@ final class InviteContactsCountPanelNode: ASDisplayNode {
|
|||
init(theme: PresentationTheme, strings: PresentationStrings, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.action = action
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.backgroundColor = theme.rootController.navigationBar.separatorColor
|
||||
|
||||
self.button = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: theme), height: 48.0, cornerRadius: 10.0)
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = theme.rootController.navigationBar.opaqueBackgroundColor
|
||||
|
||||
self.addSubnode(self.button)
|
||||
self.addSubnode(self.separatorNode)
|
||||
|
||||
self.button.pressed = {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
self.validLayout = (width, sideInset, bottomInset)
|
||||
let topInset: CGFloat = 9.0
|
||||
var bottomInset = bottomInset
|
||||
bottomInset += topInset - (bottomInset.isZero ? 0.0 : 4.0)
|
||||
|
||||
let buttonInset: CGFloat = 16.0 + sideInset
|
||||
let buttonWidth = width - buttonInset * 2.0
|
||||
let buttonHeight = self.button.updateLayout(width: buttonWidth, transition: transition)
|
||||
transition.updateFrame(node: self.button, frame: CGRect(x: buttonInset, y: topInset, width: buttonWidth, height: buttonHeight))
|
||||
let buttonInsets = ContainerViewLayout.concentricInsets(bottomInset: bottomInset, innerDiameter: 52.0, sideInset: 30.0)
|
||||
let height: CGFloat = 52.0 + buttonInsets.bottom
|
||||
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
|
||||
let edgeEffectHeight: CGFloat = height
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: edgeEffectHeight))
|
||||
transition.updateFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
||||
self.edgeEffectView.update(
|
||||
content: self.theme.list.plainBackgroundColor,
|
||||
blur: true,
|
||||
rect: edgeEffectFrame,
|
||||
edge: .bottom,
|
||||
edgeSize: edgeEffectFrame.height,
|
||||
transition: ComponentTransition(transition)
|
||||
)
|
||||
if self.edgeEffectView.superview == nil {
|
||||
self.view.addSubview(self.edgeEffectView)
|
||||
}
|
||||
|
||||
return topInset + buttonHeight + bottomInset
|
||||
let buttonTransition: ComponentTransition = .easeInOut(duration: 0.2)
|
||||
let buttonSize = self.button.update(
|
||||
transition: buttonTransition,
|
||||
component: AnyComponent(
|
||||
ButtonComponent(
|
||||
background: ButtonComponent.Background(
|
||||
style: .glass,
|
||||
color: self.theme.list.itemCheckColors.fillColor,
|
||||
foreground: self.theme.list.itemCheckColors.foregroundColor,
|
||||
pressedColor: self.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9)
|
||||
),
|
||||
content: AnyComponentWithIdentity(
|
||||
id: AnyHashable(0),
|
||||
component: AnyComponent(ButtonTextContentComponent(
|
||||
text: self.strings.Contacts_InviteContacts(Int32(self.count)),
|
||||
badge: 0,
|
||||
textColor: self.theme.list.itemCheckColors.foregroundColor,
|
||||
badgeBackground: self.theme.list.itemCheckColors.foregroundColor,
|
||||
badgeForeground: self.theme.list.itemCheckColors.fillColor,
|
||||
badgeStyle: .roundedRectangle,
|
||||
badgeIconName: nil,
|
||||
combinedAlignment: true
|
||||
))
|
||||
),
|
||||
isEnabled: true,
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.action()
|
||||
}
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: width - sideInset * 2.0 - buttonInsets.left - buttonInsets.right, height: 52.0)
|
||||
)
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: sideInset + buttonInsets.left, y: 0.0), size: buttonSize)
|
||||
if let buttonView = self.button.view {
|
||||
if buttonView.superview == nil {
|
||||
self.view.addSubview(buttonView)
|
||||
}
|
||||
transition.updateFrame(view: buttonView, frame: buttonFrame)
|
||||
}
|
||||
return height
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -460,12 +460,12 @@ public final class DatePickerNode: ASDisplayNode {
|
|||
self.dateButtonNode = HighlightableButtonNode()
|
||||
self.dateButtonNode.clipsToBounds = true
|
||||
self.dateButtonNode.backgroundColor = theme.segmentedControlTheme.backgroundColor
|
||||
self.dateButtonNode.cornerRadius = 9.0
|
||||
self.dateButtonNode.cornerRadius = 18.0
|
||||
|
||||
self.timeButtonNode = HighlightableButtonNode()
|
||||
self.timeButtonNode.clipsToBounds = true
|
||||
self.timeButtonNode.backgroundColor = theme.segmentedControlTheme.backgroundColor
|
||||
self.timeButtonNode.cornerRadius = 9.0
|
||||
self.timeButtonNode.cornerRadius = 18.0
|
||||
|
||||
super.init()
|
||||
|
||||
|
|
@ -828,7 +828,7 @@ public final class DatePickerNode: ASDisplayNode {
|
|||
var timeSize = self.timeButtonNode.measure(size)
|
||||
timeSize.width += 24.0
|
||||
timeSize.height = 36.0
|
||||
self.timeButtonNode.frame = CGRect(x: size.width - timeSize.width - 4.0, y: 4.0, width: timeSize.width, height: timeSize.height)
|
||||
self.timeButtonNode.frame = CGRect(x: size.width - timeSize.width - 10.0, y: 4.0, width: timeSize.width, height: timeSize.height)
|
||||
|
||||
let dateString = stringForMediumDate(timestamp: Int32(date.timeIntervalSince1970), strings: self.strings, dateTimeFormat: self.dateTimeFormat, withTime: false)
|
||||
self.dateButtonNode.setTitle(dateString, with: Font.with(size: 17.0, traits: .monospacedNumbers), with: self.state.displayingDateSelection ? self.theme.accentColor : self.theme.textColor, for: .normal)
|
||||
|
|
@ -836,7 +836,7 @@ public final class DatePickerNode: ASDisplayNode {
|
|||
var dateSize = self.dateButtonNode.measure(size)
|
||||
dateSize.width += 24.0
|
||||
dateSize.height = 36.0
|
||||
self.dateButtonNode.frame = CGRect(x: size.width - timeSize.width - 4.0 - 4.0 - dateSize.width, y: 4.0, width: dateSize.width, height: dateSize.height)
|
||||
self.dateButtonNode.frame = CGRect(x: size.width - timeSize.width - 10.0 - 4.0 - dateSize.width, y: 4.0, width: dateSize.width, height: dateSize.height)
|
||||
|
||||
let daysSideInset: CGFloat = 12.0
|
||||
let cellSize: CGFloat = floor((constrainedSize.width - daysSideInset * 2.0) / 7.0)
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
|||
case let .timeCustomPicker(_, dateTimeFormat, date, displayingDateSelection, displayingTimeSelection, enabled):
|
||||
let _ = enabled
|
||||
let title = presentationData.strings.InviteLink_Create_TimeLimitExpiryTime
|
||||
return ItemListDatePickerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, date: date, title: title, displayingDateSelection: displayingDateSelection, displayingTimeSelection: displayingTimeSelection, sectionId: self.section, style: .blocks, toggleDateSelection: {
|
||||
return ItemListDatePickerItem(presentationData: presentationData, systemStyle: .glass, dateTimeFormat: dateTimeFormat, date: date, title: title, displayingDateSelection: displayingDateSelection, displayingTimeSelection: displayingTimeSelection, sectionId: self.section, style: .blocks, toggleDateSelection: {
|
||||
arguments.updateState({ state in
|
||||
var updatedState = state
|
||||
updatedState.pickingExpiryDate = !updatedState.pickingExpiryDate
|
||||
|
|
|
|||
|
|
@ -7,13 +7,15 @@ import TelegramPresentationData
|
|||
|
||||
public class ItemListPlaceholderItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let text: String
|
||||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, text: String, sectionId: ItemListSectionId, style: ItemListStyle, tag: ItemListItemTag? = nil) {
|
||||
public init(theme: PresentationTheme, systemStyle: ItemListSystemStyle = .legacy, text: String, sectionId: ItemListSectionId, style: ItemListStyle, tag: ItemListItemTag? = nil) {
|
||||
self.theme = theme
|
||||
self.systemStyle = systemStyle
|
||||
self.text = text
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
|
|
@ -198,7 +200,7 @@ public class ItemListPlaceholderItemNode: ListViewItemNode, ItemListItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
case let .modeHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .giftPremium(_, title, subtitle, isSelected):
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .premium, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, icon: .image(color: .premium, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
var openSelection = false
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
|
|
@ -448,7 +448,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
}
|
||||
})
|
||||
case let .giftStars(_, title, subtitle, isSelected):
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: .stars, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: false, isSelected: isSelected, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, icon: .image(color: .stars, name: "Peer Info/PremiumIcon"), title: title, subtitle: subtitle, subtitleActive: false, isSelected: isSelected, sectionId: self.section, action: {
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.mode = .starsGiveaway
|
||||
|
|
@ -480,7 +480,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
icon = "Premium/PremiumStar"
|
||||
boosts = boostCount
|
||||
}
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: icon), title: title, titleFont: .bold, titleBadge: "\(boosts)", subtitle: subtitle, sectionId: self.section, action: nil)
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, icon: .image(color: color, name: icon), title: title, titleFont: .bold, titleBadge: "\(boosts)", subtitle: subtitle, sectionId: self.section, action: nil)
|
||||
case let .starsHeader(_, text, additionalText):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section)
|
||||
case let .stars(_, _, stars, title, subtitle, label, isSelected, maxWinners):
|
||||
|
|
@ -501,7 +501,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
case let .subscriptionsHeader(_, text, additionalText):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section)
|
||||
case let .subscriptions(_, value, values):
|
||||
return SubscriptionsCountItem(theme: presentationData.theme, strings: presentationData.strings, value: value, values: values, sectionId: self.section, updated: { value in
|
||||
return SubscriptionsCountItem(theme: presentationData.theme, strings: presentationData.strings, systemStyle: .glass, value: value, values: values, sectionId: self.section, updated: { value in
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
if state.mode == .giveaway {
|
||||
|
|
@ -536,7 +536,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
case let .usersHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .usersAll(_, title, subtitle, isSelected):
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
var openSelection = false
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
|
|
@ -551,7 +551,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
}
|
||||
})
|
||||
case let .usersNew(_, title, subtitle, isSelected):
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, title: title, subtitle: subtitle, subtitleActive: true, isSelected: isSelected, sectionId: self.section, action: {
|
||||
var openSelection = false
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
|
|
@ -570,7 +570,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
case let .durationHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .duration(_, _, months, title, subtitle, label, badge, isSelected):
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, title: title, subtitle: subtitle, subtitleFont: .small, label: .generic(label), badge: badge, isSelected: isSelected, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, systemStyle: .glass, context: arguments.context, title: title, subtitle: subtitle, subtitleFont: .small, label: .generic(label), badge: badge, isSelected: isSelected, sectionId: self.section, action: {
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.selectedMonths = months
|
||||
|
|
@ -635,7 +635,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||
})
|
||||
case let .timeCustomPicker(_, dateTimeFormat, date, minDate, maxDate, displayingDateSelection, displayingTimeSelection):
|
||||
let title = presentationData.strings.BoostGift_DateEnds
|
||||
return ItemListDatePickerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, date: date, minDate: minDate, maxDate: maxDate, title: title, displayingDateSelection: displayingDateSelection, displayingTimeSelection: displayingTimeSelection, sectionId: self.section, style: .blocks, toggleDateSelection: {
|
||||
return ItemListDatePickerItem(presentationData: presentationData, systemStyle: .glass, dateTimeFormat: dateTimeFormat, date: date, minDate: minDate, maxDate: maxDate, title: title, displayingDateSelection: displayingDateSelection, displayingTimeSelection: displayingTimeSelection, sectionId: self.section, style: .blocks, toggleDateSelection: {
|
||||
var focus = false
|
||||
arguments.updateState({ state in
|
||||
var updatedState = state
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import TelegramPresentationData
|
|||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import ButtonComponent
|
||||
import EdgeEffect
|
||||
|
||||
final class CreateGiveawayFooterItem: ItemListControllerFooterItem {
|
||||
let theme: PresentationTheme
|
||||
|
|
@ -42,8 +43,7 @@ final class CreateGiveawayFooterItem: ItemListControllerFooterItem {
|
|||
}
|
||||
|
||||
final class CreateGiveawayFooterItemNode: ItemListControllerFooterItemNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let edgeEffectView = EdgeEffectView()
|
||||
private let button = ComponentView<Empty>()
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
|
@ -51,7 +51,6 @@ final class CreateGiveawayFooterItemNode: ItemListControllerFooterItemNode {
|
|||
private var currentIsLoading = false
|
||||
var item: CreateGiveawayFooterItem {
|
||||
didSet {
|
||||
self.updateItem()
|
||||
if let layout = self.validLayout {
|
||||
let _ = self.updateLayout(layout: layout, transition: .immediate)
|
||||
}
|
||||
|
|
@ -60,49 +59,35 @@ final class CreateGiveawayFooterItemNode: ItemListControllerFooterItemNode {
|
|||
|
||||
init(item: CreateGiveawayFooterItem) {
|
||||
self.item = item
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: item.theme.rootController.tabBar.backgroundColor)
|
||||
self.separatorNode = ASDisplayNode()
|
||||
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
|
||||
self.updateItem()
|
||||
}
|
||||
|
||||
private func updateItem() {
|
||||
self.backgroundNode.updateColor(color: self.item.theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = self.item.theme.rootController.tabBar.separatorColor
|
||||
}
|
||||
|
||||
override func updateBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
transition.updateAlpha(node: self.backgroundNode, alpha: alpha)
|
||||
transition.updateAlpha(node: self.separatorNode, alpha: alpha)
|
||||
}
|
||||
|
||||
override func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
let hadLayout = self.validLayout != nil
|
||||
self.validLayout = layout
|
||||
|
||||
let buttonInset: CGFloat = 16.0
|
||||
let buttonWidth = layout.size.width - layout.safeInsets.left - layout.safeInsets.right - buttonInset * 2.0
|
||||
let inset: CGFloat = 9.0
|
||||
let buttonInsets = ContainerViewLayout.concentricInsets(bottomInset: layout.intrinsicInsets.bottom, innerDiameter: 52.0, sideInset: 30.0)
|
||||
let height: CGFloat = 52.0 + buttonInsets.bottom
|
||||
|
||||
let insets = layout.insets(options: [.input])
|
||||
|
||||
var panelHeight: CGFloat = 50.0 + inset * 2.0
|
||||
let totalPanelHeight: CGFloat
|
||||
if let inputHeight = layout.inputHeight, inputHeight > 0.0 {
|
||||
totalPanelHeight = panelHeight + insets.bottom
|
||||
} else {
|
||||
totalPanelHeight = panelHeight + insets.bottom
|
||||
panelHeight += insets.bottom
|
||||
let edgeEffectHeight: CGFloat = height
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - edgeEffectHeight), size: CGSize(width: layout.size.width, height: edgeEffectHeight))
|
||||
transition.updateFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
||||
self.edgeEffectView.update(
|
||||
content: self.item.theme.list.plainBackgroundColor,
|
||||
blur: true,
|
||||
rect: edgeEffectFrame,
|
||||
edge: .bottom,
|
||||
edgeSize: edgeEffectFrame.height,
|
||||
transition: ComponentTransition(transition)
|
||||
)
|
||||
if self.edgeEffectView.superview == nil {
|
||||
self.view.addSubview(self.edgeEffectView)
|
||||
}
|
||||
|
||||
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - totalPanelHeight), size: CGSize(width: layout.size.width, height: panelHeight))
|
||||
|
||||
var buttonTransition: ComponentTransition = .easeInOut(duration: 0.2)
|
||||
if !hadLayout {
|
||||
buttonTransition = .immediate
|
||||
|
|
@ -112,6 +97,7 @@ final class CreateGiveawayFooterItemNode: ItemListControllerFooterItemNode {
|
|||
component: AnyComponent(
|
||||
ButtonComponent(
|
||||
background: ButtonComponent.Background(
|
||||
style: .glass,
|
||||
color: self.item.theme.list.itemCheckColors.fillColor,
|
||||
foreground: self.item.theme.list.itemCheckColors.foregroundColor,
|
||||
pressedColor: self.item.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9)
|
||||
|
|
@ -140,26 +126,21 @@ final class CreateGiveawayFooterItemNode: ItemListControllerFooterItemNode {
|
|||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: buttonWidth, height: 50.0)
|
||||
containerSize: CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - buttonInsets.left - buttonInsets.right, height: 52.0)
|
||||
)
|
||||
if let view = self.button.view {
|
||||
if view.superview == nil {
|
||||
self.view.addSubview(view)
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: layout.safeInsets.left + buttonInsets.left, y: layout.size.height - buttonInsets.bottom - buttonSize.height), size: buttonSize)
|
||||
if let buttonView = self.button.view {
|
||||
if buttonView.superview == nil {
|
||||
self.view.addSubview(buttonView)
|
||||
}
|
||||
transition.updateFrame(view: view, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + buttonInset, y: panelFrame.minY + inset), size: buttonSize))
|
||||
transition.updateFrame(view: buttonView, frame: buttonFrame)
|
||||
}
|
||||
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: panelFrame)
|
||||
self.backgroundNode.update(size: panelFrame.size, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: panelFrame.origin, size: CGSize(width: panelFrame.width, height: UIScreenPixel)))
|
||||
|
||||
return totalPanelHeight
|
||||
return height
|
||||
}
|
||||
|
||||
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||
if self.backgroundNode.frame.contains(point) {
|
||||
if self.edgeEffectView.frame.contains(point) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import PresentationDataUtils
|
|||
import Markdown
|
||||
import ComponentFlow
|
||||
import PremiumStarComponent
|
||||
import GlassBarButtonComponent
|
||||
import BundleIconComponent
|
||||
|
||||
final class CreateGiveawayHeaderItem: ItemListControllerHeaderItem {
|
||||
let theme: PresentationTheme
|
||||
|
|
@ -49,13 +51,10 @@ private let titleFont = Font.semibold(20.0)
|
|||
private let textFont = Font.regular(15.0)
|
||||
|
||||
class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
|
||||
private let cancelNode: HighlightableButtonNode
|
||||
|
||||
private let cancelButton = ComponentView<Empty>()
|
||||
private var hostView: ComponentHostView<Empty>?
|
||||
|
||||
private var component: AnyComponent<Empty>?
|
||||
|
|
@ -72,11 +71,7 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||
|
||||
init(item: CreateGiveawayHeaderItem) {
|
||||
self.item = item
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: item.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.contentMode = .left
|
||||
|
|
@ -87,26 +82,15 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||
self.textNode.contentMode = .left
|
||||
self.textNode.contentsScale = UIScreen.main.scale
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
|
||||
self.cancelNode = HighlightableButtonNode()
|
||||
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.cancelNode)
|
||||
|
||||
self.cancelNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
|
||||
self.updateItem()
|
||||
}
|
||||
|
||||
@objc private func cancelPressed() {
|
||||
self.item.cancel()
|
||||
}
|
||||
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
|
|
@ -128,23 +112,18 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||
}
|
||||
|
||||
func updateItem() {
|
||||
self.backgroundNode.updateColor(color: self.item.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = self.item.theme.rootController.navigationBar.separatorColor
|
||||
|
||||
let attributedTitle = NSAttributedString(string: self.item.title, font: titleFont, textColor: self.item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
let attributedText = NSAttributedString(string: self.item.text, font: textFont, textColor: self.item.theme.list.freeTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.titleNode.attributedText = attributedTitle
|
||||
self.textNode.attributedText = attributedText
|
||||
|
||||
self.cancelNode.setAttributedTitle(NSAttributedString(string: self.item.strings.Common_Cancel, font: Font.regular(17.0), textColor: self.item.theme.rootController.navigationBar.accentTextColor), for: .normal)
|
||||
}
|
||||
|
||||
override func updateContentOffset(_ contentOffset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
guard let layout = self.validLayout else {
|
||||
return
|
||||
}
|
||||
let navigationHeight: CGFloat = 56.0
|
||||
let navigationHeight: CGFloat = 76.0
|
||||
let statusBarHeight = layout.statusBarHeight ?? 0.0
|
||||
|
||||
let topInset : CGFloat = 0.0
|
||||
|
|
@ -155,10 +134,6 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||
let fraction = max(0.0, min(1.0, titleOffset / titleOffsetDelta))
|
||||
let titleScale = 1.0 - fraction * 0.18
|
||||
|
||||
let topPanelAlpha = min(20.0, max(0.0, contentOffset - 95.0)) / 20.0
|
||||
transition.updateAlpha(node: self.backgroundNode, alpha: topPanelAlpha)
|
||||
transition.updateAlpha(node: self.separatorNode, alpha: topPanelAlpha)
|
||||
|
||||
let starPosition = CGPoint(
|
||||
x: layout.size.width / 2.0,
|
||||
y: -contentOffset + 80.0
|
||||
|
|
@ -185,18 +160,34 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||
override func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
let leftInset: CGFloat = 24.0
|
||||
|
||||
let navigationBarHeight: CGFloat = 56.0
|
||||
let constrainedSize = CGSize(width: layout.size.width - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude)
|
||||
let titleSize = self.titleNode.updateLayout(constrainedSize)
|
||||
let textSize = self.textNode.updateLayout(constrainedSize)
|
||||
|
||||
let cancelSize = self.cancelNode.measure(constrainedSize)
|
||||
transition.updateFrame(node: self.cancelNode, frame: CGRect(origin: CGPoint(x: 16.0 + layout.safeInsets.left, y: floorToScreenPixels((navigationBarHeight - cancelSize.height) / 2.0)), size: cancelSize))
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight)))
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
|
||||
|
||||
self.backgroundNode.update(size: CGSize(width: layout.size.width, height: navigationBarHeight), transition: transition)
|
||||
|
||||
let cancelButtonSize = self.cancelButton.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
GlassBarButtonComponent(
|
||||
size: CGSize(width: 44.0, height: 44.0),
|
||||
backgroundColor: nil,
|
||||
isDark: self.item.theme.overallDarkAppearance,
|
||||
state: .glass,
|
||||
component: AnyComponentWithIdentity(id: "icon", component: AnyComponent(BundleIconComponent(name: "Navigation/Close", tintColor: self.item.theme.chat.inputPanel.panelControlColor))),
|
||||
action: { [weak self] _ in
|
||||
self?.item.cancel()
|
||||
}
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 44.0, height: 44.0)
|
||||
)
|
||||
let cancelButtonFrame = CGRect(origin: CGPoint(x: 16.0, y: 16.0), size: cancelButtonSize)
|
||||
if let cancelButtonView = self.cancelButton.view {
|
||||
if cancelButtonView.superview == nil {
|
||||
self.view.addSubview(cancelButtonView)
|
||||
}
|
||||
cancelButtonView.frame = cancelButtonFrame
|
||||
}
|
||||
|
||||
let colors: [UIColor]
|
||||
let particleColor: UIColor?
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public final class GiftOptionItem: ListViewItem, ItemListItem {
|
|||
}
|
||||
|
||||
let presentationData: ItemListPresentationData
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let context: AccountContext
|
||||
let icon: Icon?
|
||||
let title: String
|
||||
|
|
@ -68,8 +69,9 @@ public final class GiftOptionItem: ListViewItem, ItemListItem {
|
|||
public let sectionId: ItemListSectionId
|
||||
let action: (() -> Void)?
|
||||
|
||||
public init(presentationData: ItemListPresentationData, context: AccountContext, icon: Icon? = nil, title: String, titleFont: Font = .regular, titleBadge: String? = nil, subtitle: String?, subtitleFont: SubtitleFont = .regular, subtitleActive: Bool = false, label: Label? = nil, badge: String? = nil, isSelected: Bool? = nil, stars: Int64? = nil, sectionId: ItemListSectionId, action: (() -> Void)?) {
|
||||
public init(presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .legacy, context: AccountContext, icon: Icon? = nil, title: String, titleFont: Font = .regular, titleBadge: String? = nil, subtitle: String?, subtitleFont: SubtitleFont = .regular, subtitleActive: Bool = false, label: Label? = nil, badge: String? = nil, isSelected: Bool? = nil, stars: Int64? = nil, sectionId: ItemListSectionId, action: (() -> Void)?) {
|
||||
self.presentationData = presentationData
|
||||
self.systemStyle = systemStyle
|
||||
self.icon = icon
|
||||
self.context = context
|
||||
self.title = title
|
||||
|
|
@ -518,7 +520,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.containerNode.frame = CGRect(origin: CGPoint(), size: strongSelf.backgroundNode.frame.size)
|
||||
|
|
|
|||
|
|
@ -1,280 +0,0 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import AccountContext
|
||||
import TelegramPresentationData
|
||||
import UndoUI
|
||||
import PresentationDataUtils
|
||||
|
||||
private struct BoostState {
|
||||
let level: Int32
|
||||
let currentLevelBoosts: Int32
|
||||
let nextLevelBoosts: Int32?
|
||||
let boosts: Int32
|
||||
|
||||
func displayData(peer: EnginePeer, isCurrent: Bool, canBoostAgain: Bool, myBoostCount: Int32, currentMyBoostCount: Int32, replacedBoosts: Int32? = nil) -> (subject: PremiumLimitScreen.Subject, count: Int32) {
|
||||
var currentLevel = self.level
|
||||
var nextLevelBoosts = self.nextLevelBoosts
|
||||
var currentLevelBoosts = self.currentLevelBoosts
|
||||
var boosts = self.boosts
|
||||
if let replacedBoosts {
|
||||
boosts = max(currentLevelBoosts, boosts - replacedBoosts)
|
||||
}
|
||||
|
||||
if currentMyBoostCount > 0 && self.boosts == currentLevelBoosts {
|
||||
currentLevel = max(0, currentLevel - 1)
|
||||
nextLevelBoosts = currentLevelBoosts
|
||||
currentLevelBoosts = max(0, currentLevelBoosts - 1)
|
||||
}
|
||||
|
||||
return (
|
||||
.storiesChannelBoost(
|
||||
peer: peer,
|
||||
boostSubject: .stories,
|
||||
isCurrent: isCurrent,
|
||||
level: currentLevel,
|
||||
currentLevelBoosts: currentLevelBoosts,
|
||||
nextLevelBoosts: nextLevelBoosts,
|
||||
link: nil,
|
||||
myBoostCount: myBoostCount,
|
||||
canBoostAgain: canBoostAgain
|
||||
),
|
||||
boosts
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func PremiumBoostScreen(
|
||||
context: AccountContext,
|
||||
contentContext: Any?,
|
||||
peerId: EnginePeer.Id,
|
||||
isCurrent: Bool,
|
||||
status: ChannelBoostStatus?,
|
||||
myBoostStatus: MyBoostStatus?,
|
||||
replacedBoosts: (Int32, Int32)? = nil,
|
||||
forceDark: Bool,
|
||||
openPeer: @escaping (EnginePeer) -> Void,
|
||||
presentController: @escaping (ViewController) -> Void,
|
||||
pushController: @escaping (ViewController) -> Void,
|
||||
dismissed: @escaping () -> Void
|
||||
) {
|
||||
let _ = (context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)
|
||||
)
|
||||
|> deliverOnMainQueue).startStandalone(next: { peer, accountPeer in
|
||||
guard let peer, let accountPeer, let status else {
|
||||
return
|
||||
}
|
||||
|
||||
let isPremium = accountPeer.isPremium
|
||||
|
||||
var myBoostCount: Int32 = 0
|
||||
var currentMyBoostCount: Int32 = 0
|
||||
var availableBoosts: [MyBoostStatus.Boost] = []
|
||||
var occupiedBoosts: [MyBoostStatus.Boost] = []
|
||||
if let myBoostStatus {
|
||||
for boost in myBoostStatus.boosts {
|
||||
if let boostPeer = boost.peer {
|
||||
if boostPeer.id == peer.id {
|
||||
myBoostCount += 1
|
||||
} else {
|
||||
occupiedBoosts.append(boost)
|
||||
}
|
||||
} else {
|
||||
availableBoosts.append(boost)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let boosts = max(Int32(status.boosts), myBoostCount)
|
||||
let initialState = BoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: boosts)
|
||||
let updatedState = Promise<BoostState?>()
|
||||
updatedState.set(.single(BoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: boosts + 1)))
|
||||
|
||||
var updateImpl: (() -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with({ $0 }))
|
||||
let canBoostAgain = premiumConfiguration.boostsPerGiftCount > 0
|
||||
|
||||
let (initialSubject, initialCount) = initialState.displayData(peer: peer, isCurrent: isCurrent, canBoostAgain: canBoostAgain, myBoostCount: myBoostCount, currentMyBoostCount: 0, replacedBoosts: replacedBoosts?.0)
|
||||
let controller = PremiumLimitScreen(context: context, subject: initialSubject, count: initialCount, forceDark: forceDark, action: {
|
||||
let dismiss = false
|
||||
updateImpl?()
|
||||
return dismiss
|
||||
},
|
||||
openPeer: { peer in
|
||||
openPeer(peer)
|
||||
})
|
||||
pushController(controller)
|
||||
|
||||
if let (replacedBoosts, inChannels) = replacedBoosts {
|
||||
currentMyBoostCount += 1
|
||||
let (subject, count) = initialState.displayData(peer: peer, isCurrent: isCurrent, canBoostAgain: canBoostAgain, myBoostCount: myBoostCount, currentMyBoostCount: 1, replacedBoosts: nil)
|
||||
controller.updateSubject(subject, count: count)
|
||||
|
||||
Queue.mainQueue().after(0.3) {
|
||||
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: .bottom, action: { _ in return true })
|
||||
controller.present(undoController, in: .current)
|
||||
}
|
||||
}
|
||||
|
||||
controller.disposed = {
|
||||
dismissed()
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
updateImpl = { [weak controller] in
|
||||
if let _ = status.nextLevelBoosts {
|
||||
if let availableBoost = availableBoosts.first {
|
||||
currentMyBoostCount += 1
|
||||
myBoostCount += 1
|
||||
|
||||
let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot])
|
||||
|> deliverOnMainQueue).startStandalone(completed: {
|
||||
updatedState.set(context.engine.peers.getChannelBoostStatus(peerId: peerId)
|
||||
|> map { status in
|
||||
if let status {
|
||||
return BoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: Int32(status.boosts + 1))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let _ = (updatedState.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { state in
|
||||
guard let state else {
|
||||
return
|
||||
}
|
||||
let (subject, count) = state.displayData(peer: peer, isCurrent: isCurrent, canBoostAgain: canBoostAgain, myBoostCount: myBoostCount, currentMyBoostCount: currentMyBoostCount)
|
||||
controller?.updateSubject(subject, count: count)
|
||||
})
|
||||
|
||||
availableBoosts.removeFirst()
|
||||
} else if !occupiedBoosts.isEmpty, let myBoostStatus {
|
||||
if canBoostAgain {
|
||||
var dismissReplaceImpl: (() -> Void)?
|
||||
let replaceController = ReplaceBoostScreen(context: context, peerId: peerId, myBoostStatus: myBoostStatus, replaceBoosts: { slots in
|
||||
var channelIds = Set<EnginePeer.Id>()
|
||||
for boost in myBoostStatus.boosts {
|
||||
if slots.contains(boost.slot) {
|
||||
if let peer = boost.peer {
|
||||
channelIds.insert(peer.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = context.engine.peers.applyChannelBoost(peerId: peerId, slots: slots).startStandalone(completed: {
|
||||
let _ = combineLatest(
|
||||
queue: Queue.mainQueue(),
|
||||
context.engine.peers.getChannelBoostStatus(peerId: peerId),
|
||||
context.engine.peers.getMyBoostStatus()
|
||||
).startStandalone(next: { boostStatus, myBoostStatus in
|
||||
dismissReplaceImpl?()
|
||||
PremiumBoostScreen(context: context, contentContext: contentContext, peerId: peerId, isCurrent: isCurrent, status: boostStatus, myBoostStatus: myBoostStatus, replacedBoosts: (Int32(slots.count), Int32(channelIds.count)), forceDark: forceDark, openPeer: openPeer, presentController: presentController, pushController: pushController, dismissed: dismissed)
|
||||
})
|
||||
})
|
||||
})
|
||||
dismissImpl?()
|
||||
pushController(replaceController)
|
||||
dismissReplaceImpl = { [weak replaceController] in
|
||||
replaceController?.dismiss(animated: true)
|
||||
}
|
||||
} else if let boost = occupiedBoosts.first, let occupiedPeer = boost.peer {
|
||||
if let cooldown = boost.cooldownUntil {
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let timeout = cooldown - currentTime
|
||||
let valueText = timeIntervalString(strings: presentationData.strings, value: timeout, usage: .afterTime, preferLowerValue: false)
|
||||
let controller = textAlertController(
|
||||
sharedContext: context.sharedContext,
|
||||
updatedPresentationData: nil,
|
||||
title: presentationData.strings.ChannelBoost_Error_BoostTooOftenTitle,
|
||||
text: presentationData.strings.ChannelBoost_Error_BoostTooOftenText(valueText).string,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})
|
||||
],
|
||||
parseMarkdown: true
|
||||
)
|
||||
presentController(controller)
|
||||
} else {
|
||||
let replaceController = replaceBoostConfirmationController(context: context, fromPeers: [occupiedPeer], toPeer: peer, commit: {
|
||||
currentMyBoostCount += 1
|
||||
myBoostCount += 1
|
||||
let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [boost.slot])
|
||||
|> deliverOnMainQueue).startStandalone(completed: { [weak controller] in
|
||||
let _ = (updatedState.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak controller] state in
|
||||
guard let state else {
|
||||
return
|
||||
}
|
||||
let (subject, count) = state.displayData(peer: peer, isCurrent: isCurrent, canBoostAgain: canBoostAgain, myBoostCount: myBoostCount, currentMyBoostCount: currentMyBoostCount)
|
||||
controller?.updateSubject(subject, count: count)
|
||||
})
|
||||
})
|
||||
})
|
||||
presentController(replaceController)
|
||||
}
|
||||
} else {
|
||||
dismissImpl?()
|
||||
}
|
||||
} else {
|
||||
if isPremium {
|
||||
if !canBoostAgain {
|
||||
dismissImpl?()
|
||||
} else {
|
||||
let controller = textAlertController(
|
||||
sharedContext: context.sharedContext,
|
||||
updatedPresentationData: nil,
|
||||
title: presentationData.strings.ChannelBoost_MoreBoosts_Title,
|
||||
text: presentationData.strings.ChannelBoost_MoreBoosts_Text(peer.compactDisplayTitle, "\(premiumConfiguration.boostsPerGiftCount)").string,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.ChannelBoost_MoreBoosts_Gift, action: {
|
||||
dismissImpl?()
|
||||
|
||||
Queue.mainQueue().after(0.4) {
|
||||
let controller = context.sharedContext.makePremiumGiftController(context: context, source: .channelBoost, completion: nil)
|
||||
pushController(controller)
|
||||
}
|
||||
}),
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Close, action: {})
|
||||
],
|
||||
actionLayout: .vertical,
|
||||
parseMarkdown: true
|
||||
)
|
||||
presentController(controller)
|
||||
}
|
||||
} else {
|
||||
let controller = textAlertController(
|
||||
sharedContext: context.sharedContext,
|
||||
updatedPresentationData: nil,
|
||||
title: presentationData.strings.ChannelBoost_Error_PremiumNeededTitle,
|
||||
text: presentationData.strings.ChannelBoost_Error_PremiumNeededText,
|
||||
actions: [
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: {
|
||||
dismissImpl?()
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .channelBoost(peerId), forceDark: forceDark, dismissed: nil)
|
||||
pushController(controller)
|
||||
})
|
||||
],
|
||||
parseMarkdown: true
|
||||
)
|
||||
presentController(controller)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dismissImpl?()
|
||||
}
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -12,14 +12,16 @@ import PresentationDataUtils
|
|||
final class SubscriptionsCountItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let value: Int32
|
||||
let values: [Int32]
|
||||
let sectionId: ItemListSectionId
|
||||
let updated: (Int32) -> Void
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, value: Int32, values: [Int32], sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, systemStyle: ItemListSystemStyle = .legacy, value: Int32, values: [Int32], sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.systemStyle = systemStyle
|
||||
self.value = value
|
||||
self.values = values
|
||||
self.sectionId = sectionId
|
||||
|
|
@ -229,7 +231,7 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import MultilineTextComponent
|
|||
import BundleIconComponent
|
||||
import PlainButtonComponent
|
||||
import AccountContext
|
||||
import GlassBackgroundComponent
|
||||
|
||||
final class BoostHeaderItem: ItemListControllerHeaderItem {
|
||||
let context: AccountContext
|
||||
|
|
@ -291,9 +292,9 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||
let progress = Child(PremiumLimitDisplayComponent.self)
|
||||
let text = Child(MultilineTextComponent.self)
|
||||
|
||||
let boostButton = Child(PlainButtonComponent.self)
|
||||
let giveawayButton = Child(PlainButtonComponent.self)
|
||||
let featuresButton = Child(PlainButtonComponent.self)
|
||||
let boostButton = Child(HeaderButtonComponent.self)
|
||||
let giveawayButton = Child(HeaderButtonComponent.self)
|
||||
let featuresButton = Child(HeaderButtonComponent.self)
|
||||
|
||||
return { context in
|
||||
let size = context.availableSize
|
||||
|
|
@ -393,18 +394,14 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||
)
|
||||
|
||||
let minButtonWidth: CGFloat = 112.0
|
||||
// let buttonSpacing = (size.width - sideInset * 2.0 - minButtonWidth * 3.0) / 2.0
|
||||
let buttonHeight: CGFloat = 58.0
|
||||
|
||||
let buttonColor = UIColor(rgb: 0x908eff)
|
||||
|
||||
let boostButton = boostButton.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
BoostButtonComponent(
|
||||
iconName: "Premium/Boosts/Boost",
|
||||
title: component.strings.ChannelBoost_Header_Boost
|
||||
)
|
||||
),
|
||||
effectAlignment: .center,
|
||||
component: HeaderButtonComponent(
|
||||
title: component.strings.ChannelBoost_Header_Boost,
|
||||
buttonColor: buttonColor,
|
||||
iconName: "Premium/Boosts/Boost",
|
||||
action: {
|
||||
component.openBoost()
|
||||
}
|
||||
|
|
@ -417,14 +414,10 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||
)
|
||||
|
||||
let giveawayButton = giveawayButton.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
BoostButtonComponent(
|
||||
iconName: "Premium/Boosts/Giveaway",
|
||||
title: component.strings.ChannelBoost_Header_Giveaway
|
||||
)
|
||||
),
|
||||
effectAlignment: .center,
|
||||
component: HeaderButtonComponent(
|
||||
title: component.strings.ChannelBoost_Header_Giveaway,
|
||||
buttonColor: buttonColor,
|
||||
iconName: "Premium/Boosts/Giveaway",
|
||||
action: {
|
||||
component.createGiveaway()
|
||||
}
|
||||
|
|
@ -437,14 +430,10 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||
)
|
||||
|
||||
let featuresButton = featuresButton.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
BoostButtonComponent(
|
||||
iconName: "Premium/Boosts/Features",
|
||||
title: component.strings.ChannelBoost_Header_Features
|
||||
)
|
||||
),
|
||||
effectAlignment: .center,
|
||||
component: HeaderButtonComponent(
|
||||
title: component.strings.ChannelBoost_Header_Features,
|
||||
buttonColor: buttonColor,
|
||||
iconName: "Premium/Boosts/Features",
|
||||
action: {
|
||||
component.openFeatures()
|
||||
}
|
||||
|
|
@ -537,3 +526,167 @@ private final class BoostButtonComponent: CombinedComponent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class HeaderButtonComponent: Component {
|
||||
let title: String
|
||||
let buttonColor: UIColor
|
||||
let iconName: String
|
||||
let isLocked: Bool
|
||||
let action: () -> Void
|
||||
|
||||
public init(
|
||||
title: String,
|
||||
buttonColor: UIColor,
|
||||
iconName: String,
|
||||
isLocked: Bool = false,
|
||||
action: @escaping () -> Void
|
||||
) {
|
||||
self.title = title
|
||||
self.buttonColor = buttonColor
|
||||
self.iconName = iconName
|
||||
self.isLocked = isLocked
|
||||
self.action = action
|
||||
}
|
||||
|
||||
static func ==(lhs: HeaderButtonComponent, rhs: HeaderButtonComponent) -> Bool {
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.buttonColor != rhs.buttonColor {
|
||||
return false
|
||||
}
|
||||
if lhs.iconName != rhs.iconName {
|
||||
return false
|
||||
}
|
||||
if lhs.isLocked != rhs.isLocked {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private var component: HeaderButtonComponent?
|
||||
private weak var componentState: EmptyComponentState?
|
||||
|
||||
private let backgroundView = GlassBackgroundView()
|
||||
private let title = ComponentView<Empty>()
|
||||
private let icon = ComponentView<Empty>()
|
||||
private let lockIcon = ComponentView<Empty>()
|
||||
private let button = HighlightTrackingButton()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.backgroundView)
|
||||
self.backgroundView.contentView.addSubview(self.button)
|
||||
|
||||
self.button.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
if let component = self.component {
|
||||
component.action()
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: HeaderButtonComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.component = component
|
||||
self.componentState = state
|
||||
|
||||
let bounds = CGRect(origin: .zero, size: availableSize)
|
||||
|
||||
self.backgroundView.update(size: bounds.size, cornerRadius: 16.0, isDark: true, tintColor: .init(kind: .custom(style: .default, color: component.buttonColor)), isInteractive: true, transition: transition)
|
||||
transition.setFrame(view: self.backgroundView, frame: bounds)
|
||||
|
||||
let iconSize = self.icon.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
BundleIconComponent(
|
||||
name: component.iconName,
|
||||
tintColor: UIColor.white
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
if let iconView = self.icon.view {
|
||||
if iconView.superview == nil {
|
||||
iconView.isUserInteractionEnabled = false
|
||||
self.backgroundView.contentView.addSubview(iconView)
|
||||
}
|
||||
iconView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - iconSize.width) / 2.0), y: floorToScreenPixels(22.0 - iconSize.height * 0.5)), size: iconSize)
|
||||
}
|
||||
|
||||
let titleSize = self.title.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: component.title,
|
||||
font: Font.regular(11.0),
|
||||
textColor: UIColor.white,
|
||||
paragraphAlignment: .natural
|
||||
)),
|
||||
horizontalAlignment: .center,
|
||||
maximumNumberOfLines: 1
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 16.0, height: availableSize.height)
|
||||
)
|
||||
|
||||
var totalTitleWidth = titleSize.width
|
||||
var titleOriginX = availableSize.width / 2.0 - totalTitleWidth / 2.0
|
||||
if component.isLocked {
|
||||
let titleSpacing: CGFloat = 3.0
|
||||
|
||||
let lockIconSize = self.lockIcon.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
BundleIconComponent(
|
||||
name: "Chat List/StatusLockIcon",
|
||||
tintColor: .white
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
totalTitleWidth += lockIconSize.width + titleSpacing
|
||||
titleOriginX = availableSize.width / 2.0 - totalTitleWidth / 2.0
|
||||
|
||||
if let lockIconView = self.lockIcon.view {
|
||||
if lockIconView.superview == nil {
|
||||
lockIconView.isUserInteractionEnabled = false
|
||||
self.backgroundView.contentView.addSubview(lockIconView)
|
||||
}
|
||||
lockIconView.frame = CGRect(origin: CGPoint(x: titleOriginX, y: floorToScreenPixels(42.0 - lockIconSize.height * 0.5)), size: lockIconSize)
|
||||
}
|
||||
titleOriginX += lockIconSize.width + titleSpacing
|
||||
}
|
||||
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
titleView.isUserInteractionEnabled = false
|
||||
self.backgroundView.contentView.addSubview(titleView)
|
||||
}
|
||||
titleView.frame = CGRect(origin: CGPoint(x: titleOriginX, y: floorToScreenPixels(42.0 - titleSize.height * 0.5)), size: titleSize)
|
||||
}
|
||||
|
||||
self.button.frame = bounds
|
||||
|
||||
return availableSize
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
let .adsProceedsInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .overview(_, stats):
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: false, stats: stats, sectionId: self.section, style: .blocks)
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, isGroup: false, stats: stats, sectionId: self.section, style: .blocks)
|
||||
case let .growthGraph(_, _, _, graph, type),
|
||||
let .followersGraph(_, _, _, graph, type),
|
||||
let .notificationsGraph(_, _, _, graph, type),
|
||||
|
|
@ -943,15 +943,15 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
let .reactionsByEmotionGraph(_, _, _, graph, type),
|
||||
let .storyReactionsByEmotionGraph(_, _, _, graph, type),
|
||||
let .adsImpressionsGraph(_, _, _, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .adsTonRevenueGraph(_, _, _, graph, type, rate):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, conversionRate: rate, sectionId: self.section, style: .blocks)
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, conversionRate: rate, sectionId: self.section, style: .blocks)
|
||||
case let .adsStarsRevenueGraph(_, _, _, graph, type, rate):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, conversionRate: rate, sectionId: self.section, style: .blocks)
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, conversionRate: rate, sectionId: self.section, style: .blocks)
|
||||
case let .postInteractionsGraph(_, _, _, graph, type),
|
||||
let .instantPageInteractionsGraph(_, _, _, graph, type),
|
||||
let .storyInteractionsGraph(_, _, _, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, getDetailsData: { date, completion in
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, getDetailsData: { date, completion in
|
||||
let _ = arguments.loadDetailedGraph(graph, Int64(date.timeIntervalSince1970) * 1000).start(next: { graph in
|
||||
if let graph = graph, case let .Loaded(_, data) = graph {
|
||||
completion(data)
|
||||
|
|
@ -1035,7 +1035,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
arguments.openBoost(boost)
|
||||
})
|
||||
case let .boostersExpand(theme, title):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandBoosters()
|
||||
})
|
||||
case let .boostLevel(_, count, level, position):
|
||||
|
|
@ -1046,15 +1046,15 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: isGroup, stats: stats, sectionId: self.section, style: .blocks)
|
||||
case let .boostLink(_, link):
|
||||
let invite: ExportedInvitation = .link(link: link, title: nil, isPermanent: false, requestApproval: false, isRevoked: false, adminId: PeerId(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil, pricing: nil)
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, count: 0, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: {
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, invite: invite, count: 0, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: {
|
||||
arguments.copyBoostLink(link)
|
||||
}, shareAction: {
|
||||
arguments.shareBoostLink(link)
|
||||
}, contextAction: nil, viewAction: nil, openCallAction: nil, tag: nil)
|
||||
case let .boostersPlaceholder(_, text):
|
||||
return ItemListPlaceholderItem(theme: presentationData.theme, text: text, sectionId: self.section, style: .blocks)
|
||||
return ItemListPlaceholderItem(theme: presentationData.theme, systemStyle: .glass, text: text, sectionId: self.section, style: .blocks)
|
||||
case let .boostGifts(theme, title):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addBoostsIcon(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.addBoostsIcon(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.openGifts()
|
||||
})
|
||||
case let .boostPrepaid(_, _, title, subtitle, prepaidGiveaway):
|
||||
|
|
@ -1200,7 +1200,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
label.addAttribute(.baselineOffset, value: 1.0, range: NSRange(range, in: label.string))
|
||||
}
|
||||
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "", attributedTitle: title, label: "", attributedLabel: label, labelStyle: .coloredText(labelColor), additionalDetailLabel: detailText, additionalDetailLabelColor: detailColor, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: "", attributedTitle: title, label: "", attributedLabel: label, labelStyle: .coloredText(labelColor), additionalDetailLabel: detailText, additionalDetailLabelColor: detailColor, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||
arguments.openTonTransaction(transaction)
|
||||
})
|
||||
case let .adsStarsTransaction(_, _, transaction):
|
||||
|
|
@ -1208,7 +1208,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
arguments.openStarsTransaction(transaction)
|
||||
}, sectionId: self.section, style: .blocks)
|
||||
case let .adsTransactionsExpand(theme, title, stars):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandTransactions(stars)
|
||||
})
|
||||
case let .adsCpmToggle(_, title, minLevel, value):
|
||||
|
|
@ -1219,7 +1219,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
level: Int(minLevel)
|
||||
))
|
||||
}
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: title, titleBadgeComponent: badgeComponent, value: value == true, enableInteractiveChanges: value != nil, enabled: true, displayLocked: value == nil, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, titleBadgeComponent: badgeComponent, value: value == true, enableInteractiveChanges: value != nil, enabled: true, displayLocked: value == nil, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||
if value != nil {
|
||||
arguments.updateCpmEnabled(updatedValue)
|
||||
} else {
|
||||
|
|
@ -1229,7 +1229,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
arguments.presentCpmLocked()
|
||||
})
|
||||
case .earnStarsInfo:
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.earnStars, title: presentationData.strings.Monetization_EarnStarsInfo_Title, titleBadge: nil, label: presentationData.strings.Monetization_EarnStarsInfo_Text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesSettings.earnStars, title: presentationData.strings.Monetization_EarnStarsInfo_Title, titleBadge: nil, label: presentationData.strings.Monetization_EarnStarsInfo_Text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openEarnStars()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
let .topInvitersTitle(_, text, dates):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: dates, color: .generic), sectionId: self.section)
|
||||
case let .overview(_, stats):
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: true, stats: stats, sectionId: self.section, style: .blocks)
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, isGroup: true, stats: stats, sectionId: self.section, style: .blocks)
|
||||
case let .growthGraph(_, _, _, graph, type),
|
||||
let .membersGraph(_, _, _, graph, type),
|
||||
let .newMembersBySourceGraph(_, _, _, graph, type),
|
||||
|
|
@ -390,7 +390,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
let .actionsGraph(_, _, _, graph, type),
|
||||
let .topHoursGraph(_, _, _, graph, type),
|
||||
let .topWeekdaysGraph(_, _, _, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .topPoster(_, _, strings, dateTimeFormat, peer, topPoster, revealed, canPromote):
|
||||
var textComponents: [String] = []
|
||||
if topPoster.messageCount > 0 {
|
||||
|
|
@ -410,13 +410,13 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
}))
|
||||
}
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, systemStyle: .glass, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setPostersPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
case let .topPostersExpand(theme, title):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandTopPosters()
|
||||
})
|
||||
case let .topAdmin(_, _, strings, dateTimeFormat, peer, topAdmin, revealed, canPromote):
|
||||
|
|
@ -441,13 +441,13 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
}))
|
||||
}
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, systemStyle: .glass, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setAdminsPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
case let .topAdminsExpand(theme, title):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandTopAdmins()
|
||||
})
|
||||
case let .topInviter(_, _, strings, dateTimeFormat, peer, topInviter, revealed, canPromote):
|
||||
|
|
@ -464,13 +464,13 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
}))
|
||||
}
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, systemStyle: .glass, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", "), .secondary), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: arguments.context.account.peerId != peer.id, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setInvitersPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
case let .topInvitersExpand(theme, title):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandTopInviters()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,9 +160,9 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
let .publicForwardsTitle(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .overview(_, stats, storyViews, publicShares):
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: false, stats: stats as? Stats, storyViews: storyViews, publicShares: publicShares, sectionId: self.section, style: .blocks)
|
||||
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, isGroup: false, stats: stats as? Stats, storyViews: storyViews, publicShares: publicShares, sectionId: self.section, style: .blocks)
|
||||
case let .interactionsGraph(_, _, _, graph, type, noInitialZoom), let .reactionsGraph(_, _, _, graph, type, noInitialZoom):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, noInitialZoom: noInitialZoom, getDetailsData: { date, completion in
|
||||
return StatsGraphItem(presentationData: presentationData, systemStyle: .glass, graph: graph, type: type, noInitialZoom: noInitialZoom, getDetailsData: { date, completion in
|
||||
let _ = arguments.loadDetailedGraph(graph, Int64(date.timeIntervalSince1970) * 1000).start(next: { graph in
|
||||
if let graph = graph, case let .Loaded(_, data) = graph {
|
||||
completion(data)
|
||||
|
|
@ -197,7 +197,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||
reactions = Int32(story.views?.reactedCount ?? 0)
|
||||
isStory = true
|
||||
}
|
||||
return StatsMessageItem(context: arguments.context, presentationData: presentationData, peer: peer, item: item, views: views, reactions: reactions, forwards: forwards, isPeer: true, sectionId: self.section, style: .blocks, action: {
|
||||
return StatsMessageItem(context: arguments.context, presentationData: presentationData, systemStyle: .glass, peer: peer, item: item, views: views, reactions: reactions, forwards: forwards, isPeer: true, sectionId: self.section, style: .blocks, action: {
|
||||
switch item {
|
||||
case let .message(message):
|
||||
arguments.openMessage(message.id)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import ListItemComponentAdaptor
|
|||
|
||||
public final class StatsGraphItem: ListViewItem, ItemListItem, ListItemComponentAdaptor.ItemGenerator {
|
||||
let presentationData: ItemListPresentationData
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let graph: StatsGraph
|
||||
let type: ChartType
|
||||
let noInitialZoom: Bool
|
||||
|
|
@ -22,8 +23,9 @@ public final class StatsGraphItem: ListViewItem, ItemListItem, ListItemComponent
|
|||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
|
||||
public init(presentationData: ItemListPresentationData, graph: StatsGraph, type: ChartType, noInitialZoom: Bool = false, conversionRate: Double = 1.0, getDetailsData: ((Date, @escaping (String?) -> Void) -> Void)? = nil, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
public init(presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .legacy, graph: StatsGraph, type: ChartType, noInitialZoom: Bool = false, conversionRate: Double = 1.0, getDetailsData: ((Date, @escaping (String?) -> Void) -> Void)? = nil, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.presentationData = presentationData
|
||||
self.systemStyle = systemStyle
|
||||
self.graph = graph
|
||||
self.type = type
|
||||
self.noInitialZoom = noInitialZoom
|
||||
|
|
@ -215,6 +217,7 @@ public final class StatsGraphItemNode: ListViewItemNode {
|
|||
contentSize.height += visibilityHeight
|
||||
}
|
||||
contentSize.height += 7.0
|
||||
contentSize.height += 8.0
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
return (ListViewItemNodeLayout(contentSize: contentSize, insets: insets), { [weak self] in
|
||||
|
|
@ -280,9 +283,9 @@ public final class StatsGraphItemNode: ListViewItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.chartContainerNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: contentSize.height))
|
||||
strongSelf.chartContainerNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 8.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: contentSize.height - 8.0))
|
||||
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: 0.0, y: item.type == .hourlyStep ? -40.0 : 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 750.0))
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import AvatarNode
|
|||
public class StatsMessageItem: ListViewItem, ItemListItem {
|
||||
let context: AccountContext
|
||||
let presentationData: ItemListPresentationData
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let peer: Peer
|
||||
let item: StatsPostItem
|
||||
let views: Int32
|
||||
|
|
@ -30,9 +31,10 @@ public class StatsMessageItem: ListViewItem, ItemListItem {
|
|||
let openStory: (UIView) -> Void
|
||||
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, peer: Peer, item: StatsPostItem, views: Int32, reactions: Int32, forwards: Int32, isPeer: Bool = false, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, openStory: @escaping (UIView) -> Void, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .glass, peer: Peer, item: StatsPostItem, views: Int32, reactions: Int32, forwards: Int32, isPeer: Bool = false, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, openStory: @escaping (UIView) -> Void, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.systemStyle = systemStyle
|
||||
self.peer = peer
|
||||
self.item = item
|
||||
self.views = views
|
||||
|
|
@ -576,7 +578,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
|
|
|||
|
|
@ -40,9 +40,10 @@ extension StarsRevenueStats: Stats {
|
|||
|
||||
}
|
||||
|
||||
class StatsOverviewItem: ListViewItem, ItemListItem {
|
||||
final class StatsOverviewItem: ListViewItem, ItemListItem {
|
||||
let context: AccountContext
|
||||
let presentationData: ItemListPresentationData
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let isGroup: Bool
|
||||
let stats: Stats?
|
||||
let additionalStats: Stats?
|
||||
|
|
@ -51,9 +52,10 @@ class StatsOverviewItem: ListViewItem, ItemListItem {
|
|||
let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, isGroup: Bool, stats: Stats?, additionalStats: Stats? = nil, storyViews: EngineStoryItem.Views? = nil, publicShares: Int32? = nil, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .glass, isGroup: Bool, stats: Stats?, additionalStats: Stats? = nil, storyViews: EngineStoryItem.Views? = nil, publicShares: Int32? = nil, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.systemStyle = systemStyle
|
||||
self.isGroup = isGroup
|
||||
self.stats = stats
|
||||
self.additionalStats = additionalStats
|
||||
|
|
@ -968,7 +970,7 @@ class StatsOverviewItemNode: ListViewItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
|
|
|||
|
|
@ -6416,80 +6416,6 @@ private final class HeaderButtonComponent: Component {
|
|||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
|
||||
// static var body: Body {
|
||||
// let background = Child(RoundedRectangle.self)
|
||||
// let title = Child(MultilineTextComponent.self)
|
||||
// let icon = Child(BundleIconComponent.self)
|
||||
// let lockIcon = Child(BundleIconComponent.self)
|
||||
//
|
||||
// return { context in
|
||||
// let component = context.component
|
||||
//
|
||||
// let background = background.update(
|
||||
// component: RoundedRectangle(
|
||||
// color: UIColor.white.withAlphaComponent(0.16),
|
||||
// cornerRadius: 16.0
|
||||
// ),
|
||||
// availableSize: context.availableSize,
|
||||
// transition: .immediate
|
||||
// )
|
||||
// context.add(background
|
||||
// .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
||||
// )
|
||||
//
|
||||
// let icon = icon.update(
|
||||
// component: BundleIconComponent(
|
||||
// name: component.iconName,
|
||||
// tintColor: UIColor.white
|
||||
// ),
|
||||
// availableSize: context.availableSize,
|
||||
// transition: .immediate
|
||||
// )
|
||||
// context.add(icon
|
||||
// .position(CGPoint(x: context.availableSize.width / 2.0, y: 22.0))
|
||||
// )
|
||||
//
|
||||
// let title = title.update(
|
||||
// component: MultilineTextComponent(
|
||||
// text: .plain(NSAttributedString(
|
||||
// string: component.title,
|
||||
// font: Font.regular(11.0),
|
||||
// textColor: UIColor.white,
|
||||
// paragraphAlignment: .natural
|
||||
// )),
|
||||
// horizontalAlignment: .center,
|
||||
// maximumNumberOfLines: 1
|
||||
// ),
|
||||
// availableSize: CGSize(width: context.availableSize.width - 16.0, height: context.availableSize.height),
|
||||
// transition: .immediate
|
||||
// )
|
||||
// var totalTitleWidth = title.size.width
|
||||
// var titleOriginX = context.availableSize.width / 2.0 - totalTitleWidth / 2.0
|
||||
// if component.isLocked {
|
||||
// let titleSpacing: CGFloat = 3.0
|
||||
// let lockIcon = lockIcon.update(
|
||||
// component: BundleIconComponent(
|
||||
// name: "Chat List/StatusLockIcon",
|
||||
// tintColor: UIColor.white
|
||||
// ),
|
||||
// availableSize: context.availableSize,
|
||||
// transition: .immediate
|
||||
// )
|
||||
// totalTitleWidth += lockIcon.size.width + titleSpacing
|
||||
// titleOriginX = context.availableSize.width / 2.0 - totalTitleWidth / 2.0
|
||||
// context.add(lockIcon
|
||||
// .position(CGPoint(x: titleOriginX + lockIcon.size.width / 2.0, y: 42.0))
|
||||
// )
|
||||
// titleOriginX += lockIcon.size.width + titleSpacing
|
||||
// }
|
||||
// context.add(title
|
||||
// .position(CGPoint(x: titleOriginX + title.size.width / 2.0, y: 42.0))
|
||||
// )
|
||||
//
|
||||
// return context.availableSize
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private struct GiftViewConfiguration {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import DatePickerNode
|
|||
|
||||
public class ItemListDatePickerItem: ListViewItem, ItemListItem {
|
||||
let presentationData: ItemListPresentationData
|
||||
let systemStyle: ItemListSystemStyle
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let date: Int32?
|
||||
let minDate: Int32?
|
||||
|
|
@ -28,6 +29,7 @@ public class ItemListDatePickerItem: ListViewItem, ItemListItem {
|
|||
|
||||
public init(
|
||||
presentationData: ItemListPresentationData,
|
||||
systemStyle: ItemListSystemStyle = .legacy,
|
||||
dateTimeFormat: PresentationDateTimeFormat,
|
||||
date: Int32?,
|
||||
minDate: Int32? = nil,
|
||||
|
|
@ -43,6 +45,7 @@ public class ItemListDatePickerItem: ListViewItem, ItemListItem {
|
|||
tag: ItemListItemTag? = nil
|
||||
) {
|
||||
self.presentationData = presentationData
|
||||
self.systemStyle = systemStyle
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.date = date
|
||||
self.minDate = minDate
|
||||
|
|
@ -158,14 +161,14 @@ public class ItemListDatePickerItemNode: ListViewItemNode, ItemListItemNode {
|
|||
let width = params.width - params.leftInset - params.rightInset
|
||||
let constrainedWidth = min(390.0, width)
|
||||
let cellSize = floor((constrainedWidth - 12.0 * 2.0) / 7.0)
|
||||
let pickerHeight = 122.0 + cellSize * 6.0
|
||||
let pickerHeight = 132.0 + cellSize * 6.0
|
||||
let height: CGFloat
|
||||
if item.displayingDateSelection {
|
||||
height = pickerHeight
|
||||
} else if item.displayingTimeSelection {
|
||||
height = 260.0
|
||||
} else {
|
||||
height = 44.0
|
||||
height = 56.0
|
||||
}
|
||||
switch item.style {
|
||||
case .plain:
|
||||
|
|
@ -244,7 +247,7 @@ public class ItemListDatePickerItemNode: ListViewItemNode, ItemListItemNode {
|
|||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil
|
||||
|
||||
transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))))
|
||||
transition.updateFrame(node: strongSelf.maskNode, frame: strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0))
|
||||
|
|
@ -291,7 +294,7 @@ public class ItemListDatePickerItemNode: ListViewItemNode, ItemListItemNode {
|
|||
datePickerNode.date = item.date.flatMap { Date(timeIntervalSince1970: TimeInterval($0)) }
|
||||
|
||||
let datePickerSize = CGSize(width: width, height: pickerHeight)
|
||||
datePickerNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - datePickerSize.width) / 2.0), y: 0.0), size: datePickerSize)
|
||||
datePickerNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - datePickerSize.width) / 2.0), y: 6.0), size: datePickerSize)
|
||||
datePickerNode.updateLayout(size: datePickerSize, transition: .immediate)
|
||||
|
||||
transition.updateFrame(node: strongSelf.containerNode, frame: CGRect(origin: .zero, size: CGSize(width: params.width, height: contentSize.height)))
|
||||
|
|
|
|||
|
|
@ -479,10 +479,8 @@ private final class SheetContent: Component {
|
|||
contentHeight += itemSize.height
|
||||
}
|
||||
|
||||
contentHeight += 31.0
|
||||
|
||||
contentHeight += 82.0
|
||||
|
||||
contentHeight += 113.0
|
||||
|
||||
return CGSize(width: availableSize.width, height: contentHeight)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue