Various improvements

This commit is contained in:
Ilya Laktyushin 2023-10-24 11:57:42 +04:00
parent 85207874a1
commit 54489f428a
10 changed files with 571 additions and 86 deletions

View File

@ -41,6 +41,14 @@ public let sheetComponentTag = GenericComponentViewTag()
public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
public typealias EnvironmentType = (ChildEnvironmentType, SheetComponentEnvironment)
public class ExternalState {
public fileprivate(set) var contentHeight: CGFloat
public init() {
self.contentHeight = 0.0
}
}
public enum BackgroundColor: Equatable {
public enum BlurStyle: Equatable {
case light
@ -54,17 +62,20 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
public let content: AnyComponent<ChildEnvironmentType>
public let backgroundColor: BackgroundColor
public let followContentSizeChanges: Bool
public let externalState: ExternalState?
public let animateOut: ActionSlot<Action<()>>
public init(
content: AnyComponent<ChildEnvironmentType>,
backgroundColor: BackgroundColor,
followContentSizeChanges: Bool = false,
externalState: ExternalState? = nil,
animateOut: ActionSlot<Action<()>>
) {
self.content = content
self.backgroundColor = backgroundColor
self.followContentSizeChanges = followContentSizeChanges
self.externalState = externalState
self.animateOut = animateOut
}
@ -327,6 +338,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
},
containerSize: containerSize
)
component.externalState?.contentHeight = contentSize.height
self.ignoreScrolling = true
if let contentView = self.contentView.view {

View File

@ -591,7 +591,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
let badgeSize = strongSelf.titleBadge.update(
transition: .immediate,
component: AnyComponent(
BoostIconComponent(text: badge)
BoostIconComponent(hasIcon: true, text: badge)
),
environment: {},
containerSize: CGSize(width: params.width, height: 100.0)

View File

@ -10,6 +10,34 @@ import PresentationDataUtils
//TODO:localize
private struct BoostState {
let level: Int32
let currentLevelBoosts: Int32
let nextLevelBoosts: Int32?
let boosts: Int32
func displayData(peer: EnginePeer, isCurrent: 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, isCurrent: isCurrent, level: currentLevel, currentLevelBoosts: currentLevelBoosts, nextLevelBoosts: nextLevelBoosts, link: nil, myBoostCount: myBoostCount),
boosts
)
}
}
public func PremiumBoostScreen(
context: AccountContext,
contentContext: Any?,
@ -17,6 +45,7 @@ public func PremiumBoostScreen(
isCurrent: Bool,
status: ChannelBoostStatus?,
myBoostStatus: MyBoostStatus?,
replacedBoosts: (Int32, Int32)? = nil,
forceDark: Bool,
openPeer: @escaping (EnginePeer) -> Void,
presentController: @escaping (ViewController) -> Void,
@ -35,6 +64,7 @@ public func PremiumBoostScreen(
let isPremium = accountPeer.isPremium
var myBoostCount: Int32 = 0
var currentMyBoostCount: Int32 = 0
var availableBoosts: [MyBoostStatus.Boost] = []
var occupiedBoosts: [MyBoostStatus.Boost] = []
if let myBoostStatus {
@ -51,25 +81,15 @@ public func PremiumBoostScreen(
}
}
var currentLevel = Int32(status.level)
var currentLevelBoosts = Int32(status.currentLevelBoosts)
var nextLevelBoosts = status.nextLevelBoosts.flatMap(Int32.init)
if myBoostCount > 0 && status.boosts == currentLevelBoosts {
currentLevel = max(0, currentLevel - 1)
nextLevelBoosts = currentLevelBoosts
currentLevelBoosts = max(0, currentLevelBoosts - 1)
}
let subject: PremiumLimitScreen.Subject = .storiesChannelBoost(peer: peer, isCurrent: isCurrent, level: currentLevel, currentLevelBoosts: currentLevelBoosts, nextLevelBoosts: nextLevelBoosts, link: nil, myBoostCount: myBoostCount)
let nextSubject = Promise<PremiumLimitScreen.Subject>()
nextSubject.set(.single(.storiesChannelBoost(peer: peer, isCurrent: isCurrent, level: currentLevel, currentLevelBoosts: currentLevelBoosts, nextLevelBoosts: nextLevelBoosts, link: nil, myBoostCount: myBoostCount + 1)))
var nextCount = Int32(status.boosts + 1)
let initialState = BoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: Int32(status.boosts))
let updatedState = Promise<BoostState?>()
updatedState.set(.single(BoostState(level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), boosts: Int32(status.boosts + 1))))
var updateImpl: (() -> Void)?
var dismissImpl: (() -> Void)?
let controller = PremiumLimitScreen(context: context, subject: subject, count: Int32(status.boosts), forceDark: forceDark, action: {
let (initialSubject, initialCount) = initialState.displayData(peer: peer, isCurrent: isCurrent, 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
@ -78,33 +98,88 @@ public func PremiumBoostScreen(
openPeer(peer)
})
pushController(controller)
if let (replacedBoosts, inChannels) = replacedBoosts {
currentMyBoostCount += 1
let (subject, count) = initialState.displayData(peer: peer, isCurrent: isCurrent, 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: "\(replacedBoosts) boosts are reassigned from \(inChannels) other channel.", round: false, undoText: nil), elevatedLayout: false, position: .bottom, action: { _ in return true })
controller.present(undoController, in: .current)
}
}
controller.disposed = {
dismissed()
}
var updating = false
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
updateImpl = { [weak controller] in
guard !updating else {
return
}
if let _ = status.nextLevelBoosts {
if let availableBoost = availableBoosts.first {
let _ = context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot]).startStandalone()
let _ = (nextSubject.get()
currentMyBoostCount += 1
myBoostCount += 1
updating = true
let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot])
|> deliverOnMainQueue).startStandalone(completed: {
updating = false
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: { nextSubject in
controller?.updateSubject(nextSubject, count: nextCount)
|> deliverOnMainQueue).startStandalone(next: { state in
guard let state else {
return
}
let (subject, count) = state.displayData(peer: peer, isCurrent: isCurrent, myBoostCount: myBoostCount, currentMyBoostCount: currentMyBoostCount)
controller?.updateSubject(subject, count: count)
})
availableBoosts.removeFirst()
nextCount += 1
} else if !occupiedBoosts.isEmpty, let myBoostStatus {
var dismissReplaceImpl: (() -> Void)?
let replaceController = ReplaceBoostScreen(context: context, peerId: peerId, myBoostStatus: myBoostStatus, replaceBoosts: { slots in
let _ = context.engine.peers.applyChannelBoost(peerId: peerId, slots: slots).startStandalone()
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 undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "\(slots.count) boosts are reassigned from 1 other channel.", timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, action: { _ in return true })
presentController(undoController)
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 isPremium {
let controller = textAlertController(

View File

@ -821,7 +821,7 @@ private final class LimitSheetContent: CombinedComponent {
let closeButton = Child(Button.self)
let title = Child(MultilineTextComponent.self)
let text = Child(BalancedTextComponent.self)
let alternateText = Child(BalancedTextComponent.self)
let alternateText = Child(List<Empty>.self)
let limit = Child(PremiumLimitDisplayComponent.self)
let linkButton = Child(SolidRoundedButtonComponent.self)
let button = Child(SolidRoundedButtonComponent.self)
@ -881,6 +881,9 @@ private final class LimitSheetContent: CombinedComponent {
var peerShortcutChild: _UpdatedChildComponent?
var useAlternateText = false
var alternateTitle = ""
var alternateBadge: String?
var titleText = strings.Premium_LimitReached
var actionButtonText: String?
var actionButtonHasGloss = true
@ -1159,7 +1162,7 @@ private final class LimitSheetContent: CombinedComponent {
state.myBoostCount = myBoostCount
boostUpdated = true
}
useAlternateText = (myBoostCount % 2) != 0
useAlternateText = myBoostCount > 0
iconName = "Premium/Boost"
badgeText = "\(component.count)"
@ -1217,8 +1220,10 @@ private final class LimitSheetContent: CombinedComponent {
premiumTitle = ""
if myBoostCount > 0 {
let prefixString = isCurrent ? strings.ChannelBoost_YouBoostedChannelText(peer.compactDisplayTitle).string : strings.ChannelBoost_YouBoostedOtherChannelText
alternateTitle = isCurrent ? strings.ChannelBoost_YouBoostedChannelText(peer.compactDisplayTitle).string : strings.ChannelBoost_YouBoostedOtherChannelText
if myBoostCount > 1 {
alternateBadge = "X\(myBoostCount)"
}
let storiesString = strings.ChannelBoost_StoriesPerDay(level + 1)
if let _ = remaining {
actionButtonText = "Boost Again"
@ -1246,8 +1251,6 @@ private final class LimitSheetContent: CombinedComponent {
} else {
string = strings.ChannelBoost_BoostedChannelReachedLevel("\(level + 1)", storiesString).string
}
string = "**\(prefixString)**\n\(string)"
}
let progress: CGFloat
@ -1299,15 +1302,42 @@ private final class LimitSheetContent: CombinedComponent {
var alternateTextChild: _UpdatedChildComponent?
if useAlternateText {
alternateTextChild = alternateText.update(
component: BalancedTextComponent(
text: .markdown(text: string, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.1
component: List(
[
AnyComponentWithIdentity(
id: "title",
component: AnyComponent(
BoostedTitleContent(text: NSAttributedString(string: alternateTitle, font: Font.semibold(15.0), textColor: textColor), badge: alternateBadge)
)
),
AnyComponentWithIdentity(
id: "text",
component: AnyComponent(
BalancedTextComponent(
text: .markdown(text: string, attributes: markdownAttributes),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.1
)
)
)
],
centerAlignment: true
),
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
transition: .immediate
)
// alternateTextChild = alternateText.update(
// component: BalancedTextComponent(
// text: .markdown(text: string, attributes: markdownAttributes),
// horizontalAlignment: .center,
// maximumNumberOfLines: 0,
// lineSpacing: 0.1
// ),
// availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
// transition: .immediate
// )
} else {
textChild = text.update(
component: BalancedTextComponent(
@ -1417,7 +1447,7 @@ private final class LimitSheetContent: CombinedComponent {
)
buttonOffset += 66.0
let linkFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + ceil((textChild?.size ?? .zero).height / 2.0) + 24.0), size: linkButton.size)
let linkFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + (textChild?.size ?? .zero).height + 24.0), size: linkButton.size)
context.add(linkButton
.position(CGPoint(x: linkFrame.midX, y: linkFrame.midY))
)
@ -1637,6 +1667,8 @@ private final class LimitSheetComponent: CombinedComponent {
let sheet = Child(SheetComponent<EnvironmentType>.self)
let animateOut = StoredActionSlot(Action<Void>.self)
let sheetExternalState = SheetComponent<EnvironmentType>.ExternalState()
return { context in
let environment = context.environment[EnvironmentType.self]
@ -1663,6 +1695,7 @@ private final class LimitSheetComponent: CombinedComponent {
)),
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
followContentSizeChanges: true,
externalState: sheetExternalState,
animateOut: animateOut
),
environment: {
@ -1695,6 +1728,22 @@ private final class LimitSheetComponent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
)
if let controller = controller(), !controller.automaticallyControlPresentationContextLayout {
let layout = ContainerViewLayout(
size: context.availableSize,
metrics: environment.metrics,
deviceMetrics: environment.deviceMetrics,
intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: max(environment.safeInsets.bottom, sheetExternalState.contentHeight), right: 0.0),
safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
additionalInsets: .zero,
statusBarHeight: environment.statusBarHeight,
inputHeight: nil,
inputHeightIsInteractivellyChanging: false,
inVoiceOver: false
)
controller.presentationContext.containerLayoutUpdated(layout, transition: context.transition.containedViewLayoutTransition)
}
return context.availableSize
}
}
@ -1734,6 +1783,9 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
}, openPeer: openPeer, openStats: openStats, openGift: openGift), navigationBarAppearance: .none, statusBarStyle: .ignore, theme: forceDark ? .dark : .default)
self.navigationPresentation = .flatModal
if case .storiesChannelBoost = subject {
self.automaticallyControlPresentationContextLayout = false
}
self.wasDismissed = cancel
@ -1769,13 +1821,25 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
}
public func updateSubject(_ subject: Subject, count: Int32) {
let component = LimitSheetComponent(context: self.context, subject: subject, count: count, cancel: {}, action: {
return true
}, openPeer: self.openPeer, openStats: nil, openGift: nil)
let component = LimitSheetComponent(
context: self.context,
subject: subject,
count: count,
cancel: {},
action: { [weak self] in
return self?.action?() ?? true
},
openPeer: self.openPeer,
openStats: nil,
openGift: nil
)
self.updateComponent(component: AnyComponent(component), transition: .easeInOut(duration: 0.2))
self.animateSuccess()
}
public func animateSuccess() {
self.hapticFeedback.impact()
self.view.addSubview(ConfettiView(frame: self.view.bounds))
}
}
@ -1814,8 +1878,6 @@ private final class PeerShortcutComponent: Component {
private let avatarNode: AvatarNode
private let text = ComponentView<Empty>()
private let badge = ComponentView<Empty>()
private var component: PeerShortcutComponent?
private weak var state: EmptyComponentState?
@ -1869,29 +1931,6 @@ private final class PeerShortcutComponent: Component {
view.frame = textFrame
}
if let badge = component.badge {
let badgeSize = self.badge.update(
transition: .immediate,
component: AnyComponent(
BoostIconComponent(text: badge)
),
environment: {},
containerSize: availableSize
)
if let view = self.badge.view {
if view.superview == nil {
self.addSubview(view)
}
let badgeFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(size.width - badgeSize.width / 2.0), y: -5.0), size: badgeSize)
view.frame = badgeFrame
}
} else {
if let view = self.badge.view {
view.removeFromSuperview()
}
}
self.backgroundView.frame = CGRect(origin: .zero, size: size)
return size
@ -1908,13 +1947,18 @@ private final class PeerShortcutComponent: Component {
}
public final class BoostIconComponent: Component {
let hasIcon: Bool
let text: String
public init(text: String) {
public init(hasIcon: Bool, text: String) {
self.hasIcon = hasIcon
self.text = text
}
public static func ==(lhs: BoostIconComponent, rhs: BoostIconComponent) -> Bool {
if lhs.hasIcon != rhs.hasIcon {
return false
}
if lhs.text != rhs.text {
return false
}
@ -1961,11 +2005,11 @@ public final class BoostIconComponent: Component {
)
let spacing: CGFloat = 2.0
var totalWidth = textSize.width + spacing
var totalWidth = textSize.width
var iconSize = CGSize()
if let icon = self.badgeIcon.image {
if let icon = self.badgeIcon.image, component.hasIcon {
iconSize = CGSize(width: icon.size.width * 0.9, height: icon.size.height * 0.9)
totalWidth += icon.size.width
totalWidth += spacing + icon.size.width
}
let size = CGSize(width: totalWidth + 8.0, height: 19.0)
@ -1973,7 +2017,7 @@ public final class BoostIconComponent: Component {
let iconFrame = CGRect(x: floorToScreenPixels((size.width - totalWidth) / 2.0 + 1.0), y: 4.0 + UIScreenPixel, width: iconSize.width, height: iconSize.height)
self.badgeIcon.frame = iconFrame
let textFrame = CGRect(origin: CGPoint(x: iconFrame.maxX + spacing, y: 4.0), size: textSize)
let textFrame = CGRect(origin: CGPoint(x: component.hasIcon ? iconFrame.maxX + spacing : 5.0, y: 4.0), size: textSize)
if let view = self.badgeText.view {
if view.superview == nil {
@ -1997,3 +2041,64 @@ public final class BoostIconComponent: Component {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
final class BoostedTitleContent: CombinedComponent {
let text: NSAttributedString
let badge: String?
init(
text: NSAttributedString,
badge: String?
) {
self.text = text
self.badge = badge
}
static func ==(lhs: BoostedTitleContent, rhs: BoostedTitleContent) -> Bool {
if lhs.text != rhs.text {
return false
}
if lhs.badge != rhs.badge {
return false
}
return true
}
static var body: Body {
let text = Child(MultilineTextComponent.self)
let badge = Child(BoostIconComponent.self)
return { context in
let component = context.component
let height: CGFloat = 24.0
var totalWidth: CGFloat = 0.0
let text = text.update(
component: MultilineTextComponent(
text: .plain(component.text),
horizontalAlignment: .center
),
availableSize: CGSize(width: context.availableSize.width - 40.0, height: context.availableSize.height),
transition: .immediate
)
totalWidth += text.size.width
context.add(text
.position(CGPoint(x: text.size.width / 2.0, y: height / 2.0))
)
if let badgeText = component.badge {
let badge = badge.update(
component: BoostIconComponent(hasIcon: false, text: badgeText),
availableSize: CGSize(width: 24.0, height: 24.0),
transition: .immediate
)
totalWidth += badge.size.width + 4.0
context.add(badge
.position(CGPoint(x: totalWidth - badge.size.width / 2.0, y: height / 2.0))
)
}
return CGSize(width: totalWidth, height: height)
}
}
}

View File

@ -349,7 +349,6 @@ public class ReplaceBoostScreen: ViewController {
return
}
self.controller?.replaceBoosts?(self.selectedSlots)
self.controller?.dismiss(animated: true)
}
}
@ -369,7 +368,7 @@ public class ReplaceBoostScreen: ViewController {
}
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
if case .ended = recognizer.state, !self.footerView.inProgress {
self.controller?.dismiss(animated: true)
}
}
@ -950,10 +949,12 @@ private final class FooterView: UIView {
fatalError("init(coder:) has not been implemented")
}
private var currentLayout: (CGSize, UIEdgeInsets)?
fileprivate var inProgress = false
private var currentLayout: (CGSize, UIEdgeInsets, PresentationTheme, Int32)?
func update(size: CGSize, insets: UIEdgeInsets, theme: PresentationTheme, count: Int32) -> CGFloat {
let hadLayout = self.currentLayout != nil
self.currentLayout = (size, insets)
self.currentLayout = (size, insets, theme, count)
self.backgroundNode.updateColor(color: theme.rootController.tabBar.backgroundColor, transition: .immediate)
self.separatorView.backgroundColor = theme.rootController.tabBar.separatorColor
@ -996,11 +997,15 @@ private final class FooterView: UIView {
))
),
isEnabled: true,
displaysProgress: false,
displaysProgress: self.inProgress,
action: { [weak self] in
guard let self else {
guard let self, !self.inProgress else {
return
}
self.inProgress = true
if let (size, insets, theme, count) = self.currentLayout {
let _ = self.update(size: size, insets: insets, theme: theme, count: count)
}
self.action()
}
)

View File

@ -109,7 +109,7 @@ final class EmojiPickerItemNode: ListViewItemNode {
let insets: UIEdgeInsets
let separatorHeight = UIScreenPixel
let contentSize = CGSize(width: params.width, height: 200.0)
let contentSize = CGSize(width: params.width, height: params.availableHeight - 452.0)
insets = itemListNeighborsGroupedInsets(neighbors, params)
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: contentSize.height - 20.0), insets: insets)

View File

@ -189,7 +189,7 @@ private func peerNameColorScreenEntries(
state: PeerNameColorScreenState,
peer: EnginePeer?,
isPremium: Bool,
emojiContent: EmojiPagerContentComponent
emojiContent: EmojiPagerContentComponent?
) -> [PeerNameColorScreenEntry] {
var entries: [PeerNameColorScreenEntry] = []
@ -255,8 +255,10 @@ private func peerNameColorScreenEntries(
))
entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Account))
entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title))
entries.append(.backgroundEmoji(emojiContent, nameColor.color))
if let emojiContent {
entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title))
entries.append(.backgroundEmoji(emojiContent, nameColor.color))
}
}
return entries
@ -316,7 +318,7 @@ public func PeerNameColorScreen(
statePromise.get(),
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
)
|> mapToSignal { state, peer in
|> mapToSignal { state, peer -> Signal<EmojiPagerContentComponent?, NoError> in
var selectedEmojiId: Int64?
if let updatedBackgroundEmojiId = state.updatedBackgroundEmojiId {
selectedEmojiId = updatedBackgroundEmojiId
@ -351,6 +353,7 @@ public func PeerNameColorScreen(
selectedItems: Set(selectedItems),
backgroundIconColor: nameColor
)
|> map(Optional.init)
}
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
@ -359,7 +362,7 @@ public func PeerNameColorScreen(
statePromise.get(),
context.engine.stickers.availableReactions(),
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
emojiContent
.single(nil) |> then(emojiContent)
)
|> deliverOnMainQueue
|> map { presentationData, state, availableReactions, peer, emojiContent -> (ItemListControllerState, (ItemListNodeState, Any)) in
@ -475,7 +478,7 @@ public func PeerNameColorScreen(
}
)
emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
emojiContent?.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
performItemAction: { _, item, _, _, _, _ in
var selectedFileId: Int64?
if let fileId = item.itemFile?.fileId.id {
@ -565,7 +568,7 @@ public func PeerNameColorScreen(
entries: entries,
style: .blocks,
footerItem: footerItem,
animateChanges: true
animateChanges: false
)
return (controllerState, (listState, arguments))

View File

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

View File

@ -0,0 +1,273 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.877197 15.157974 cm
0.000000 0.000000 0.000000 scn
5.552186 8.359201 m
5.243867 8.359201 5.008486 8.634665 5.056572 8.939211 c
5.727019 13.185373 l
5.810456 13.713807 5.119398 13.988482 4.817303 13.546960 c
0.088512 6.635651 l
-0.139333 6.302646 0.099122 5.850563 0.502614 5.850563 c
2.581887 5.850563 l
2.890206 5.850563 3.125587 5.575099 3.077501 5.270554 c
2.407054 1.024391 l
2.323617 0.495958 3.014675 0.221282 3.316770 0.662805 c
8.045561 7.574114 l
8.273406 7.907119 8.034951 8.359201 7.631459 8.359201 c
5.552186 8.359201 l
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 16.877197 1.157974 cm
0.000000 0.000000 0.000000 scn
5.552186 8.359201 m
5.243867 8.359201 5.008486 8.634665 5.056572 8.939211 c
5.727019 13.185373 l
5.810456 13.713807 5.119398 13.988482 4.817303 13.546960 c
0.088512 6.635651 l
-0.139333 6.302646 0.099122 5.850563 0.502614 5.850563 c
2.581887 5.850563 l
2.890206 5.850563 3.125587 5.575099 3.077501 5.270554 c
2.407054 1.024391 l
2.323617 0.495958 3.014675 0.221282 3.316770 0.662805 c
8.045561 7.574114 l
8.273406 7.907119 8.034951 8.359201 7.631459 8.359201 c
5.552186 8.359201 l
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 20.000000 15.177917 cm
0.000000 0.000000 0.000000 scn
6.586899 4.235184 m
6.911034 4.559319 6.911034 5.084846 6.586899 5.408981 c
6.262764 5.733116 5.737236 5.733116 5.413101 5.408981 c
6.586899 4.235184 l
h
3.000000 1.822083 m
2.413101 1.235184 l
2.737236 0.911049 3.262764 0.911049 3.586899 1.235184 c
3.000000 1.822083 l
h
0.586899 5.408981 m
0.262763 5.733116 -0.262763 5.733116 -0.586899 5.408981 c
-0.911034 5.084846 -0.911034 4.559319 -0.586899 4.235184 c
0.586899 5.408981 l
h
5.413101 5.408981 m
2.413101 2.408981 l
3.586899 1.235184 l
6.586899 4.235184 l
5.413101 5.408981 l
h
3.586899 2.408981 m
0.586899 5.408981 l
-0.586899 4.235184 l
2.413101 1.235184 l
3.586899 2.408981 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 16.000000 15.339355 cm
0.000000 0.000000 0.000000 scn
0.000000 10.490644 m
-0.458396 10.490644 -0.830000 10.119040 -0.830000 9.660645 c
-0.830000 9.202249 -0.458396 8.830645 0.000000 8.830645 c
0.000000 10.490644 l
h
6.170000 1.660645 m
6.170000 1.202249 6.541604 0.830645 7.000000 0.830645 c
7.458396 0.830645 7.830000 1.202249 7.830000 1.660645 c
6.170000 1.660645 l
h
6.727516 8.295621 m
7.467052 8.672433 l
6.727516 8.295621 l
h
0.000000 8.830645 m
3.000000 8.830645 l
3.000000 10.490644 l
0.000000 10.490644 l
0.000000 8.830645 l
h
6.170000 5.660645 m
6.170000 1.660645 l
7.830000 1.660645 l
7.830000 5.660645 l
6.170000 5.660645 l
h
3.000000 8.830645 m
3.713761 8.830645 4.199165 8.829999 4.574407 8.799340 c
4.939959 8.769474 5.127283 8.715313 5.258164 8.648625 c
6.011788 10.127696 l
5.607891 10.333492 5.177792 10.415573 4.709584 10.453828 c
4.251065 10.491290 3.686370 10.490644 3.000000 10.490644 c
3.000000 8.830645 l
h
7.830000 5.660645 m
7.830000 6.347014 7.830646 6.911709 7.793183 7.370228 c
7.754929 7.838436 7.672848 8.268535 7.467052 8.672433 c
5.987981 7.918809 l
6.054668 7.787928 6.108829 7.600603 6.138696 7.235051 c
6.169354 6.859809 6.170000 6.374406 6.170000 5.660645 c
7.830000 5.660645 l
h
5.258164 8.648625 m
5.572395 8.488517 5.827872 8.233040 5.987981 7.918809 c
7.467052 8.672433 l
7.147793 9.299013 6.638368 9.808438 6.011788 10.127696 c
5.258164 8.648625 l
h
f
n
Q
q
-1.000000 -0.000000 -0.000000 -1.000000 10.000000 14.822083 cm
0.000000 0.000000 0.000000 scn
6.586899 4.235184 m
6.911034 4.559319 6.911034 5.084846 6.586899 5.408981 c
6.262764 5.733116 5.737236 5.733116 5.413101 5.408981 c
6.586899 4.235184 l
h
3.000000 1.822083 m
2.413101 1.235184 l
2.737236 0.911049 3.262764 0.911049 3.586899 1.235184 c
3.000000 1.822083 l
h
0.586899 5.408981 m
0.262763 5.733116 -0.262763 5.733116 -0.586899 5.408981 c
-0.911034 5.084846 -0.911034 4.559319 -0.586899 4.235184 c
0.586899 5.408981 l
h
5.413101 5.408981 m
2.413101 2.408981 l
3.586899 1.235184 l
6.586899 4.235184 l
5.413101 5.408981 l
h
3.586899 2.408981 m
0.586899 5.408981 l
-0.586899 4.235184 l
2.413101 1.235184 l
3.586899 2.408981 l
h
f
n
Q
q
-1.000000 -0.000000 -0.000000 -1.000000 14.000000 13.660645 cm
0.000000 0.000000 0.000000 scn
0.000000 9.490644 m
-0.458396 9.490644 -0.830000 9.119040 -0.830000 8.660645 c
-0.830000 8.202249 -0.458396 7.830645 0.000000 7.830645 c
0.000000 9.490644 l
h
6.170000 1.660645 m
6.170000 1.202248 6.541604 0.830645 7.000000 0.830645 c
7.458396 0.830645 7.830000 1.202248 7.830000 1.660645 c
6.170000 1.660645 l
h
6.727516 7.295621 m
7.467052 7.672433 l
6.727516 7.295621 l
h
0.000000 7.830645 m
3.000000 7.830645 l
3.000000 9.490644 l
0.000000 9.490644 l
0.000000 7.830645 l
h
6.170000 4.660645 m
6.170000 1.660645 l
7.830000 1.660645 l
7.830000 4.660645 l
6.170000 4.660645 l
h
3.000000 7.830645 m
3.713761 7.830645 4.199165 7.829999 4.574407 7.799341 c
4.939959 7.769474 5.127283 7.715313 5.258164 7.648625 c
6.011788 9.127696 l
5.607891 9.333492 5.177792 9.415573 4.709584 9.453828 c
4.251065 9.491290 3.686370 9.490644 3.000000 9.490644 c
3.000000 7.830645 l
h
7.830000 4.660645 m
7.830000 5.347014 7.830646 5.911709 7.793183 6.370228 c
7.754929 6.838436 7.672848 7.268535 7.467052 7.672433 c
5.987981 6.918809 l
6.054668 6.787928 6.108829 6.600603 6.138696 6.235051 c
6.169354 5.859809 6.170000 5.374406 6.170000 4.660645 c
7.830000 4.660645 l
h
5.258164 7.648625 m
5.572395 7.488517 5.827872 7.233039 5.987981 6.918809 c
7.467052 7.672433 l
7.147793 8.299013 6.638368 8.808438 6.011788 9.127696 c
5.258164 7.648625 l
h
f
n
Q
endstream
endobj
3 0 obj
5530
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000005620 00000 n
0000005643 00000 n
0000005816 00000 n
0000005890 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5949
%%EOF

View File

@ -1374,7 +1374,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
let undoButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - leftMargin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + leftMargin, height: contentHeight))
self.undoButtonNode.frame = undoButtonFrame
self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: undoButtonFrame.minX, height: contentHeight))
self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: self.undoButtonNode.supernode == nil ? panelFrame.width : undoButtonFrame.minX, height: contentHeight))
var textContentHeight = textSize.height
var textOffset: CGFloat = 0.0