Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-06-24 14:55:45 +02:00
commit b362a9b732
13 changed files with 225 additions and 81 deletions

View file

@ -1978,12 +1978,12 @@ ios_application(
extensions = select({
":disableExtensionsSetting": [],
"//conditions:default": [
#":ShareExtension",
#":NotificationContentExtension",
":ShareExtension",
":NotificationContentExtension",
":NotificationServiceExtension",
#":IntentsExtension",
#":WidgetExtension",
#":BroadcastUploadExtension",
":IntentsExtension",
":WidgetExtension",
":BroadcastUploadExtension",
],
}),
watch_application = select({
@ -2013,9 +2013,9 @@ xcodeproj(
"Debug": {
"//command_line_option:compilation_mode": "dbg",
},
#"Release": {
# "//command_line_option:compilation_mode": "opt",
#},
"Release": {
"//command_line_option:compilation_mode": "opt",
},
},
default_xcode_configuration = "Debug"

View file

@ -181,7 +181,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private var rawStorySubscriptions: EngineStorySubscriptions?
private var shouldFixStorySubscriptionOrder: Bool = false
private var fixedStorySubscriptionOrder: [EnginePeer.Id] = []
var orderedStorySubscriptions: EngineStorySubscriptions?
private(set) var orderedStorySubscriptions: EngineStorySubscriptions?
private var displayedStoriesTooltip: Bool = false
private var storyProgressDisposable: Disposable?
private var storySubscriptionsDisposable: Disposable?
@ -1853,11 +1854,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
var wasEmpty = true
if let rawStorySubscriptions = self.rawStorySubscriptions, !rawStorySubscriptions.items.isEmpty {
wasEmpty = false
}
self.rawStorySubscriptions = rawStorySubscriptions
var items: [EngineStorySubscriptions.Item] = []
if self.shouldFixStorySubscriptionOrder {
@ -1879,8 +1875,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
)
self.fixedStorySubscriptionOrder = items.map(\.peer.id)
let isEmpty = rawStorySubscriptions.items.isEmpty
let transition: ContainedViewLayoutTransition
if self.didAppear {
transition = .animated(duration: 0.4, curve: .spring)
@ -1888,9 +1882,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
transition = .immediate
}
let _ = wasEmpty
let _ = isEmpty
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = transition
self.requestLayout(transition: transition)
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
@ -1911,6 +1902,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
self.storiesReady.set(.single(true))
Queue.mainQueue().after(1.0, { [weak self] in
guard let self else {
return
}
self.maybeDisplayStoryTooltip()
})
})
self.storyProgressDisposable = (self.context.engine.messages.allStoriesUploadProgress()
|> deliverOnMainQueue).start(next: { [weak self] progress in
@ -1922,6 +1920,67 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
fileprivate func maybeDisplayStoryTooltip() {
let content = self.updateHeaderContent()
if content.secondaryContent != nil {
return
}
guard let chatListTitle = content.primaryContent?.chatListTitle else {
return
}
if chatListTitle.activity {
return
}
if self.displayedStoriesTooltip {
return
}
if let orderedStorySubscriptions = self.orderedStorySubscriptions, !orderedStorySubscriptions.items.isEmpty {
let _ = (ApplicationSpecificNotice.displayChatListStoriesTooltip(accountManager: self.context.sharedContext.accountManager)
|> deliverOnMainQueue).start(next: { [weak self] didDisplay in
guard let self else {
return
}
if didDisplay {
return
}
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View, !navigationBarView.storiesUnlocked, !self.displayedStoriesTooltip {
if let storyPeerListView = self.chatListHeaderView()?.storyPeerListView(), let (anchorView, anchorRect) = storyPeerListView.anchorForTooltip() {
self.displayedStoriesTooltip = true
let absoluteFrame = anchorView.convert(anchorRect, to: self.view)
//TODO:localize
let itemList = orderedStorySubscriptions.items.prefix(3).map(\.peer.compactDisplayTitle)
var itemListString: String = itemList.joined(separator: ", ")
if #available(iOS 13.0, *) {
let listFormatter = ListFormatter()
listFormatter.locale = localeWithStrings(self.presentationData.strings)
if let value = listFormatter.string(from: itemList) {
itemListString = value
}
}
let text: String = "Tap above to view updates\nfrom \(itemListString)"
let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, timeout: 30.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true, padding: 6.0, innerPadding: UIEdgeInsets(top: 2.0, left: 3.0, bottom: 2.0, right: 3.0))
self.present(tooltipController, in: .current, with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak self] in
guard let self else {
return nil
}
return (self.displayNode, absoluteFrame.insetBy(dx: 0.0, dy: 0.0).offsetBy(dx: 0.0, dy: 0.0))
}))
#if !DEBUG
let _ = ApplicationSpecificNotice.setDisplayChatListStoriesTooltip(accountManager: self.context.sharedContext.accountManager).start()
#endif
}
}
})
}
}
public override func displayNodeDidLoad() {
super.displayNodeDidLoad()
@ -2351,7 +2410,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
func updateHeaderContent(layout: ContainerViewLayout) -> (primaryContent: ChatListHeaderComponent.Content?, secondaryContent: ChatListHeaderComponent.Content?) {
func updateHeaderContent() -> (primaryContent: ChatListHeaderComponent.Content?, secondaryContent: ChatListHeaderComponent.Content?) {
var primaryContent: ChatListHeaderComponent.Content?
if let primaryContext = self.primaryContext {
var backTitle: String?
@ -5684,6 +5743,13 @@ private final class ChatListLocationContext {
}
self.parentController?.requestLayout(transition: .animated(duration: 0.45, curve: .spring))
Queue.mainQueue().after(1.0, { [weak self] in
guard let self else {
return
}
self.parentController?.maybeDisplayStoryTooltip()
})
}
private func updateForum(

View file

@ -1918,7 +1918,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
private func updateNavigationBar(layout: ContainerViewLayout, deferScrollApplication: Bool, transition: Transition) -> (navigationHeight: CGFloat, storiesInset: CGFloat) {
let headerContent = self.controller?.updateHeaderContent(layout: layout)
let headerContent = self.controller?.updateHeaderContent()
var tabsNode: ASDisplayNode?
var tabsNodeIsSearch = false
@ -2358,7 +2358,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
private func shouldStopScrolling(listView: ListView, velocity: CGFloat, isPrimary: Bool) -> Bool {
if abs(velocity) > 1.0 {
if abs(velocity) > 0.8 {
return false
}

View file

@ -2795,7 +2795,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
hasUnseen: displayStoryIndicator,
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
activeLineWidth: 2.0,
inactiveLineWidth: 1.0 + UIScreenPixel
inactiveLineWidth: 1.0 + UIScreenPixel,
counters: nil
)),
environment: {},
containerSize: indicatorFrame.size

View file

@ -201,8 +201,10 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
})]
}
var hasUnseenStories: Bool?
var storyStats: (total: Int, unseen: Int)?
if let storyData = storyData {
storyStats = (storyData.count, storyData.unseenCount)
let text: String
//TODO:localize
if storyData.unseenCount != 0 {
@ -219,12 +221,11 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
}
}
status = .custom(string: text, multiline: false, isActive: false, icon: nil)
hasUnseenStories = storyData.unseenCount != 0
}
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: isSearch ? .generalSearch : .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, selectionPosition: .left, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), additionalActions: additionalActions, index: nil, header: header, action: { _ in
interaction.openPeer(peer, .generic)
}, itemHighlighting: interaction.itemHighlighting, contextAction: itemContextAction, hasUnseenStories: hasUnseenStories, openStories: { peer, sourceNode in
}, itemHighlighting: interaction.itemHighlighting, contextAction: itemContextAction, storyStats: storyStats, openStories: { peer, sourceNode in
if case let .peer(peerValue, _) = peer, let peerValue {
interaction.openStories(peerValue, sourceNode)
}

View file

@ -489,7 +489,7 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
navigationBarComponentView.applyScroll(offset: offset, allowAvatarsExpansion: true, transition: Transition(transition))
navigationBarComponentView.applyScroll(offset: offset, allowAvatarsExpansion: false, transition: Transition(transition))
}
}

View file

@ -180,7 +180,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
let arrowAction: (() -> Void)?
let animationCache: AnimationCache?
let animationRenderer: MultiAnimationRenderer?
let hasUnseenStories: Bool?
let storyStats: (total: Int, unseen: Int)?
let openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)?
public let selectable: Bool
@ -217,7 +217,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, arrowAction: (() -> Void)? = nil,
animationCache: AnimationCache? = nil,
animationRenderer: MultiAnimationRenderer? = nil,
hasUnseenStories: Bool? = nil,
storyStats: (total: Int, unseen: Int)? = nil,
openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)? = nil
) {
self.presentationData = presentationData
@ -248,7 +248,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
self.arrowAction = arrowAction
self.animationCache = animationCache
self.animationRenderer = animationRenderer
self.hasUnseenStories = hasUnseenStories
self.storyStats = storyStats
self.openStories = openStories
if let index = index {
@ -1088,7 +1088,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
var avatarScale: CGFloat = 1.0
if item.hasUnseenStories != nil {
if item.storyStats != nil {
avatarScale *= (avatarFrame.width - 2.0 * 2.0) / avatarFrame.width
}
@ -1096,7 +1096,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
let storyIndicatorScale: CGFloat = 1.0
if let displayStoryIndicator = item.hasUnseenStories {
if let storyStats = item.storyStats {
var indicatorTransition = Transition(transition)
let avatarStoryIndicator: ComponentView<Empty>
if let current = strongSelf.avatarStoryIndicator {
@ -1113,10 +1113,11 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
let _ = avatarStoryIndicator.update(
transition: indicatorTransition,
component: AnyComponent(AvatarStoryIndicatorComponent(
hasUnseen: displayStoryIndicator,
hasUnseen: storyStats.unseen != 0,
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
activeLineWidth: 1.0 + UIScreenPixel,
inactiveLineWidth: 1.0 + UIScreenPixel
inactiveLineWidth: 1.0 + UIScreenPixel,
counters: AvatarStoryIndicatorComponent.Counters(totalCount: storyStats.total, unseenCount: storyStats.unseen)
)),
environment: {},
containerSize: indicatorFrame.size

View file

@ -173,6 +173,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case chatWallpaperLightPreviewTip = 39
case chatWallpaperDarkPreviewTip = 40
case displayChatListContacts = 41
case displayChatListStoriesTooltip = 42
var key: ValueBoxKey {
let v = ValueBoxKey(length: 4)
@ -394,6 +395,10 @@ private struct ApplicationSpecificNoticeKeys {
static func displayChatListContacts() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.displayChatListContacts.key)
}
static func displayChatListStoriesTooltip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.displayChatListStoriesTooltip.key)
}
}
public struct ApplicationSpecificNotice {
@ -1445,6 +1450,26 @@ public struct ApplicationSpecificNotice {
|> ignoreValues
}
public static func displayChatListStoriesTooltip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Bool, NoError> {
return accountManager.noticeEntry(key: ApplicationSpecificNoticeKeys.displayChatListStoriesTooltip())
|> map { view -> Bool in
if let _ = view.value?.get(ApplicationSpecificBoolNotice.self) {
return true
} else {
return false
}
}
}
public static func setDisplayChatListStoriesTooltip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Never, NoError> {
return accountManager.transaction { transaction -> Void in
if let entry = CodableEntry(ApplicationSpecificBoolNotice()) {
transaction.setNotice(ApplicationSpecificNoticeKeys.displayChatListStoriesTooltip(), entry)
}
}
|> ignoreValues
}
public static func reset(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
}

View file

@ -215,7 +215,8 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
hasUnseen: hasUnseenStories,
isDarkTheme: theme.overallDarkAppearance,
activeLineWidth: 1.0,
inactiveLineWidth: 1.0
inactiveLineWidth: 1.0,
counters: nil
)),
environment: {},
containerSize: self.avatarNode.bounds.insetBy(dx: 2.0, dy: 2.0).size

View file

@ -298,28 +298,6 @@ public final class ChatListNavigationBar: Component {
self.addSubview(searchContentNode.view)
}
/*let clippedStoriesOverscrollOffset = -min(0.0, clippedScrollOffset)
let clippedStoriesOffset = max(0.0, min(clippedScrollOffset, defaultStoriesOffsetDistance))
var storiesOffsetFraction: CGFloat
var storiesUnlockedOffsetFraction: CGFloat
if !component.isSearchActive, component.secondaryTransition == 0.0, let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty, allowAvatarsExpansion {
if component.storiesUnlocked {
storiesOffsetFraction = clippedStoriesOffset / defaultStoriesOffsetDistance
storiesUnlockedOffsetFraction = 1.0
} else {
storiesOffsetFraction = 1.0 - (clippedStoriesOverscrollOffset / defaultStoriesOffsetDistance)
storiesUnlockedOffsetFraction = 1.0
}
} else {
storiesOffsetFraction = 1.0
storiesUnlockedOffsetFraction = 1.0
}
if self.applyScrollFractionAnimator != nil {
storiesOffsetFraction = self.applyScrollFraction * storiesOffsetFraction + (1.0 - self.applyScrollFraction) * self.storiesOffsetStartFraction
storiesUnlockedOffsetFraction = self.applyScrollUnlockedFraction * storiesUnlockedOffsetFraction + (1.0 - self.applyScrollUnlockedFraction) * self.storiesUnlockedStartFraction
}*/
let searchSize = CGSize(width: currentLayout.size.width, height: navigationBarSearchContentHeight)
var searchFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height - searchSize.height), size: searchSize)
if component.tabsNode != nil {
@ -338,9 +316,6 @@ public final class ChatListNavigationBar: Component {
searchContentNode.updateLayout(size: searchSize, leftInset: component.sideInset, rightInset: component.sideInset, transition: transition.containedViewLayoutTransition)
let headerTransition = transition
/*if self.applyScrollFractionAnimator != nil {
headerTransition = .immediate
}*/
let storiesOffsetFraction: CGFloat
let storiesUnlocked: Bool
@ -362,9 +337,9 @@ public final class ChatListNavigationBar: Component {
if allowAvatarsExpansion && transition.animation.isImmediate {
if self.storiesUnlocked != storiesUnlocked {
if storiesUnlocked {
HapticFeedback().impact()
HapticFeedback().impact(.veryLight)
} else {
HapticFeedback().tap()
HapticFeedback().impact(.veryLight)
}
}
}

View file

@ -5,21 +5,34 @@ import ComponentFlow
import TelegramPresentationData
public final class AvatarStoryIndicatorComponent: Component {
public struct Counters: Equatable {
public var totalCount: Int
public var unseenCount: Int
public init(totalCount: Int, unseenCount: Int) {
self.totalCount = totalCount
self.unseenCount = unseenCount
}
}
public let hasUnseen: Bool
public let isDarkTheme: Bool
public let activeLineWidth: CGFloat
public let inactiveLineWidth: CGFloat
public let counters: Counters?
public init(
hasUnseen: Bool,
isDarkTheme: Bool,
activeLineWidth: CGFloat,
inactiveLineWidth: CGFloat
inactiveLineWidth: CGFloat,
counters: Counters?
) {
self.hasUnseen = hasUnseen
self.isDarkTheme = isDarkTheme
self.activeLineWidth = activeLineWidth
self.inactiveLineWidth = inactiveLineWidth
self.counters = counters
}
public static func ==(lhs: AvatarStoryIndicatorComponent, rhs: AvatarStoryIndicatorComponent) -> Bool {
@ -35,6 +48,9 @@ public final class AvatarStoryIndicatorComponent: Component {
if lhs.inactiveLineWidth != rhs.inactiveLineWidth {
return false
}
if lhs.counters != rhs.counters {
return false
}
return true
}
@ -76,26 +92,79 @@ public final class AvatarStoryIndicatorComponent: Component {
context.clear(CGRect(origin: CGPoint(), size: size))
context.setLineWidth(lineWidth)
context.addEllipse(in: CGRect(origin: CGPoint(x: size.width * 0.5 - diameter * 0.5, y: size.height * 0.5 - diameter * 0.5), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
context.replacePathWithStrokedPath()
context.clip()
var locations: [CGFloat] = [1.0, 0.0]
let colors: [CGColor]
if component.hasUnseen {
colors = [UIColor(rgb: 0x34C76F).cgColor, UIColor(rgb: 0x3DA1FD).cgColor]
} else {
if component.isDarkTheme {
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
} else {
colors = [UIColor(rgb: 0xD8D8E1).cgColor, UIColor(rgb: 0xD8D8E1).cgColor]
if let counters = component.counters, counters.totalCount > 1 {
let center = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
let radius = (diameter - lineWidth) * 0.5
let spacing: CGFloat = 2.0
let angularSpacing: CGFloat = spacing / radius
let circleLength = CGFloat.pi * 2.0 * radius
let segmentLength = (circleLength - spacing * CGFloat(counters.totalCount)) / CGFloat(counters.totalCount)
let segmentAngle = segmentLength / radius
for pass in 0 ..< 2 {
context.resetClip()
let startIndex: Int
let endIndex: Int
if pass == 0 {
startIndex = 0
endIndex = counters.totalCount - counters.unseenCount
} else {
startIndex = counters.totalCount - counters.unseenCount
endIndex = counters.totalCount
}
if startIndex < endIndex {
for i in startIndex ..< endIndex {
let startAngle = CGFloat(i) * (angularSpacing + segmentAngle) - CGFloat.pi * 0.5 + angularSpacing * 0.5
context.move(to: CGPoint(x: center.x + cos(startAngle) * radius, y: center.y + sin(startAngle) * radius))
context.addArc(center: center, radius: radius, startAngle: startAngle, endAngle: startAngle + segmentAngle, clockwise: false)
}
context.replacePathWithStrokedPath()
context.clip()
var locations: [CGFloat] = [1.0, 0.0]
let colors: [CGColor]
if pass == 1 {
colors = [UIColor(rgb: 0x34C76F).cgColor, UIColor(rgb: 0x3DA1FD).cgColor]
} else {
if component.isDarkTheme {
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
} else {
colors = [UIColor(rgb: 0xD8D8E1).cgColor, UIColor(rgb: 0xD8D8E1).cgColor]
}
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
}
}
} else {
context.addEllipse(in: CGRect(origin: CGPoint(x: size.width * 0.5 - diameter * 0.5, y: size.height * 0.5 - diameter * 0.5), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
context.replacePathWithStrokedPath()
context.clip()
var locations: [CGFloat] = [1.0, 0.0]
let colors: [CGColor]
if component.hasUnseen {
colors = [UIColor(rgb: 0x34C76F).cgColor, UIColor(rgb: 0x3DA1FD).cgColor]
} else {
if component.isDarkTheme {
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
} else {
colors = [UIColor(rgb: 0xD8D8E1).cgColor, UIColor(rgb: 0xD8D8E1).cgColor]
}
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
})
transition.setFrame(view: self.indicatorView, frame: CGRect(origin: CGPoint(x: (availableSize.width - imageDiameter) * 0.5, y: (availableSize.height - imageDiameter) * 0.5), size: CGSize(width: imageDiameter, height: imageDiameter)))

View file

@ -323,6 +323,10 @@ public final class StoryPeerListComponent: Component {
})
}
public func anchorForTooltip() -> (UIView, CGRect)? {
return (self.collapsedButton, self.collapsedButton.bounds)
}
public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? {
if self.collapsedButton.isUserInteractionEnabled {
return nil

View file

@ -470,7 +470,8 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
hasUnseen: hasUnseenStories,
isDarkTheme: theme.overallDarkAppearance,
activeLineWidth: 3.0,
inactiveLineWidth: 2.0
inactiveLineWidth: 2.0,
counters: nil
)),
environment: {},
containerSize: self.avatarNode.bounds.size