mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Add close friends parameter
This commit is contained in:
parent
a0817a831b
commit
42a6978ffd
@ -1889,12 +1889,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
||||||
var chatListState = chatListState
|
var chatListState = chatListState
|
||||||
|
|
||||||
var peerStoryMapping: [EnginePeer.Id: Bool] = [:]
|
var peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState] = [:]
|
||||||
for item in rawStorySubscriptions.items {
|
for item in rawStorySubscriptions.items {
|
||||||
if item.peer.id == self.context.account.peerId {
|
if item.peer.id == self.context.account.peerId {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
peerStoryMapping[item.peer.id] = item.hasUnseen
|
peerStoryMapping[item.peer.id] = ChatListNodeState.StoryState(
|
||||||
|
hasUnseen: item.hasUnseen,
|
||||||
|
hasUnseenCloseFriends: item.hasUnseenCloseFriends
|
||||||
|
)
|
||||||
}
|
}
|
||||||
chatListState.peerStoryMapping = peerStoryMapping
|
chatListState.peerStoryMapping = peerStoryMapping
|
||||||
|
|
||||||
|
@ -65,6 +65,19 @@ public enum ChatListItemContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct StoryState: Equatable {
|
||||||
|
public var hasUnseen: Bool
|
||||||
|
public var hasUnseenCloseFriends: Bool
|
||||||
|
|
||||||
|
public init(
|
||||||
|
hasUnseen: Bool,
|
||||||
|
hasUnseenCloseFriends: Bool
|
||||||
|
) {
|
||||||
|
self.hasUnseen = hasUnseen
|
||||||
|
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct PeerData {
|
public struct PeerData {
|
||||||
public var messages: [EngineMessage]
|
public var messages: [EngineMessage]
|
||||||
public var peer: EngineRenderedPeer
|
public var peer: EngineRenderedPeer
|
||||||
@ -83,7 +96,7 @@ public enum ChatListItemContent {
|
|||||||
public var forumTopicData: EngineChatList.ForumTopicData?
|
public var forumTopicData: EngineChatList.ForumTopicData?
|
||||||
public var topForumTopicItems: [EngineChatList.ForumTopicData]
|
public var topForumTopicItems: [EngineChatList.ForumTopicData]
|
||||||
public var autoremoveTimeout: Int32?
|
public var autoremoveTimeout: Int32?
|
||||||
public var storyState: Bool?
|
public var storyState: StoryState?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
messages: [EngineMessage],
|
messages: [EngineMessage],
|
||||||
@ -103,7 +116,7 @@ public enum ChatListItemContent {
|
|||||||
forumTopicData: EngineChatList.ForumTopicData?,
|
forumTopicData: EngineChatList.ForumTopicData?,
|
||||||
topForumTopicItems: [EngineChatList.ForumTopicData],
|
topForumTopicItems: [EngineChatList.ForumTopicData],
|
||||||
autoremoveTimeout: Int32?,
|
autoremoveTimeout: Int32?,
|
||||||
storyState: Bool?
|
storyState: StoryState?
|
||||||
) {
|
) {
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
@ -2747,9 +2760,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + revealOffset, dy: 0.0)
|
let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + revealOffset, dy: 0.0)
|
||||||
|
|
||||||
var displayStoryIndicator: Bool?
|
var storyState: ChatListItemContent.StoryState?
|
||||||
if case let .peer(peerData) = item.content {
|
if case let .peer(peerData) = item.content {
|
||||||
displayStoryIndicator = peerData.storyState
|
storyState = peerData.storyState
|
||||||
}
|
}
|
||||||
|
|
||||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((itemHeight - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter))
|
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((itemHeight - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter))
|
||||||
@ -2764,7 +2777,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let storyIndicatorScale = avatarScale
|
let storyIndicatorScale = avatarScale
|
||||||
if displayStoryIndicator != nil {
|
if storyState != nil {
|
||||||
avatarScale *= (avatarFrame.width - 4.0 * 2.0) / avatarFrame.width
|
avatarScale *= (avatarFrame.width - 4.0 * 2.0) / avatarFrame.width
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2775,7 +2788,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.avatarNode.updateSize(size: avatarFrame.size)
|
strongSelf.avatarNode.updateSize(size: avatarFrame.size)
|
||||||
strongSelf.updateVideoVisibility()
|
strongSelf.updateVideoVisibility()
|
||||||
|
|
||||||
if let displayStoryIndicator {
|
if let storyState {
|
||||||
var indicatorTransition = Transition(transition)
|
var indicatorTransition = Transition(transition)
|
||||||
let avatarStoryIndicator: ComponentView<Empty>
|
let avatarStoryIndicator: ComponentView<Empty>
|
||||||
if let current = strongSelf.avatarStoryIndicator {
|
if let current = strongSelf.avatarStoryIndicator {
|
||||||
@ -2792,7 +2805,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let _ = avatarStoryIndicator.update(
|
let _ = avatarStoryIndicator.update(
|
||||||
transition: indicatorTransition,
|
transition: indicatorTransition,
|
||||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||||
hasUnseen: displayStoryIndicator,
|
hasUnseen: storyState.hasUnseen,
|
||||||
|
hasUnseenCloseFriendsItems: storyState.hasUnseenCloseFriends,
|
||||||
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
|
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
|
||||||
activeLineWidth: 2.0,
|
activeLineWidth: 2.0,
|
||||||
inactiveLineWidth: 1.0 + UIScreenPixel,
|
inactiveLineWidth: 1.0 + UIScreenPixel,
|
||||||
|
@ -218,6 +218,16 @@ private func areFoundPeerArraysEqual(_ lhs: [(EnginePeer, EnginePeer?)], _ rhs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ChatListNodeState: Equatable {
|
public struct ChatListNodeState: Equatable {
|
||||||
|
public struct StoryState: Equatable {
|
||||||
|
public var hasUnseen: Bool
|
||||||
|
public var hasUnseenCloseFriends: Bool
|
||||||
|
|
||||||
|
public init(hasUnseen: Bool, hasUnseenCloseFriends: Bool) {
|
||||||
|
self.hasUnseen = hasUnseen
|
||||||
|
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct ItemId: Hashable {
|
public struct ItemId: Hashable {
|
||||||
public var peerId: EnginePeer.Id
|
public var peerId: EnginePeer.Id
|
||||||
public var threadId: Int64?
|
public var threadId: Int64?
|
||||||
@ -241,7 +251,7 @@ public struct ChatListNodeState: Equatable {
|
|||||||
public var foundPeers: [(EnginePeer, EnginePeer?)]
|
public var foundPeers: [(EnginePeer, EnginePeer?)]
|
||||||
public var selectedPeerMap: [EnginePeer.Id: EnginePeer]
|
public var selectedPeerMap: [EnginePeer.Id: EnginePeer]
|
||||||
public var selectedThreadIds: Set<Int64>
|
public var selectedThreadIds: Set<Int64>
|
||||||
public var peerStoryMapping: [EnginePeer.Id: Bool]
|
public var peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState]
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
presentationData: ChatListPresentationData,
|
presentationData: ChatListPresentationData,
|
||||||
@ -257,7 +267,7 @@ public struct ChatListNodeState: Equatable {
|
|||||||
hiddenItemShouldBeTemporaryRevealed: Bool,
|
hiddenItemShouldBeTemporaryRevealed: Bool,
|
||||||
hiddenPsaPeerId: EnginePeer.Id?,
|
hiddenPsaPeerId: EnginePeer.Id?,
|
||||||
selectedThreadIds: Set<Int64>,
|
selectedThreadIds: Set<Int64>,
|
||||||
peerStoryMapping: [EnginePeer.Id: Bool]
|
peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState]
|
||||||
) {
|
) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.editing = editing
|
self.editing = editing
|
||||||
@ -396,7 +406,12 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
forumTopicData: forumTopicData,
|
forumTopicData: forumTopicData,
|
||||||
topForumTopicItems: topForumTopicItems,
|
topForumTopicItems: topForumTopicItems,
|
||||||
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
||||||
storyState: peerEntry.storyState
|
storyState: peerEntry.storyState.flatMap { storyState in
|
||||||
|
return ChatListItemContent.StoryState(
|
||||||
|
hasUnseen: storyState.hasUnseen,
|
||||||
|
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||||
|
)
|
||||||
|
}
|
||||||
)),
|
)),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
@ -742,7 +757,12 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
forumTopicData: forumTopicData,
|
forumTopicData: forumTopicData,
|
||||||
topForumTopicItems: topForumTopicItems,
|
topForumTopicItems: topForumTopicItems,
|
||||||
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
||||||
storyState: peerEntry.storyState
|
storyState: peerEntry.storyState.flatMap { storyState in
|
||||||
|
return ChatListItemContent.StoryState(
|
||||||
|
hasUnseen: storyState.hasUnseen,
|
||||||
|
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||||
|
)
|
||||||
|
}
|
||||||
)),
|
)),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
|
@ -111,7 +111,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
var forumTopicData: EngineChatList.ForumTopicData?
|
var forumTopicData: EngineChatList.ForumTopicData?
|
||||||
var topForumTopicItems: [EngineChatList.ForumTopicData]
|
var topForumTopicItems: [EngineChatList.ForumTopicData]
|
||||||
var revealed: Bool
|
var revealed: Bool
|
||||||
var storyState: Bool?
|
var storyState: ChatListNodeState.StoryState?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
index: EngineChatList.Item.Index,
|
index: EngineChatList.Item.Index,
|
||||||
@ -136,7 +136,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
forumTopicData: EngineChatList.ForumTopicData?,
|
forumTopicData: EngineChatList.ForumTopicData?,
|
||||||
topForumTopicItems: [EngineChatList.ForumTopicData],
|
topForumTopicItems: [EngineChatList.ForumTopicData],
|
||||||
revealed: Bool,
|
revealed: Bool,
|
||||||
storyState: Bool?
|
storyState: ChatListNodeState.StoryState?
|
||||||
) {
|
) {
|
||||||
self.index = index
|
self.index = index
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
@ -82,6 +82,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
|||||||
struct StoryData: Equatable {
|
struct StoryData: Equatable {
|
||||||
var count: Int
|
var count: Int
|
||||||
var unseenCount: Int
|
var unseenCount: Int
|
||||||
|
var hasUnseenCloseFriends: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
case search(PresentationTheme, PresentationStrings)
|
case search(PresentationTheme, PresentationStrings)
|
||||||
@ -201,9 +202,9 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
|||||||
})]
|
})]
|
||||||
}
|
}
|
||||||
|
|
||||||
var storyStats: (total: Int, unseen: Int)?
|
var storyStats: (total: Int, unseen: Int, hasUnseenCloseFriends: Bool)?
|
||||||
if let storyData = storyData {
|
if let storyData = storyData {
|
||||||
storyStats = (storyData.count, storyData.unseenCount)
|
storyStats = (storyData.count, storyData.unseenCount, storyData.hasUnseenCloseFriends)
|
||||||
|
|
||||||
let text: String
|
let text: String
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
@ -534,7 +535,7 @@ private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactLis
|
|||||||
let header: ListViewItemHeader? = ChatListSearchItemHeader(type: .text("HIDDEN STORIES", AnyHashable(0)), theme: theme, strings: strings)
|
let header: ListViewItemHeader? = ChatListSearchItemHeader(type: .text("HIDDEN STORIES", AnyHashable(0)), theme: theme, strings: strings)
|
||||||
|
|
||||||
for item in storySubscriptions.items {
|
for item in storySubscriptions.items {
|
||||||
entries.append(.peer(index, .peer(peer: item.peer._asPeer(), isGlobal: false, participantCount: nil), nil, header, .none, theme, strings, dateTimeFormat, sortOrder, displayOrder, false, true, ContactListNodeEntry.StoryData(count: item.storyCount, unseenCount: item.unseenCount)))
|
entries.append(.peer(index, .peer(peer: item.peer._asPeer(), isGlobal: false, participantCount: nil), nil, header, .none, theme, strings, dateTimeFormat, sortOrder, displayOrder, false, true, ContactListNodeEntry.StoryData(count: item.storyCount, unseenCount: item.unseenCount, hasUnseenCloseFriends: item.hasUnseenCloseFriends)))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
|
|||||||
let arrowAction: (() -> Void)?
|
let arrowAction: (() -> Void)?
|
||||||
let animationCache: AnimationCache?
|
let animationCache: AnimationCache?
|
||||||
let animationRenderer: MultiAnimationRenderer?
|
let animationRenderer: MultiAnimationRenderer?
|
||||||
let storyStats: (total: Int, unseen: Int)?
|
let storyStats: (total: Int, unseen: Int, hasUnseenCloseFriends: Bool)?
|
||||||
let openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)?
|
let openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)?
|
||||||
|
|
||||||
public let selectable: Bool
|
public let selectable: Bool
|
||||||
@ -217,7 +217,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
|
|||||||
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, arrowAction: (() -> Void)? = nil,
|
contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, arrowAction: (() -> Void)? = nil,
|
||||||
animationCache: AnimationCache? = nil,
|
animationCache: AnimationCache? = nil,
|
||||||
animationRenderer: MultiAnimationRenderer? = nil,
|
animationRenderer: MultiAnimationRenderer? = nil,
|
||||||
storyStats: (total: Int, unseen: Int)? = nil,
|
storyStats: (total: Int, unseen: Int, hasUnseenCloseFriends: Bool)? = nil,
|
||||||
openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)? = nil
|
openStories: ((ContactsPeerItemPeer, ASDisplayNode) -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
@ -1114,6 +1114,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
transition: indicatorTransition,
|
transition: indicatorTransition,
|
||||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||||
hasUnseen: storyStats.unseen != 0,
|
hasUnseen: storyStats.unseen != 0,
|
||||||
|
hasUnseenCloseFriendsItems: storyStats.hasUnseenCloseFriends,
|
||||||
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
|
isDarkTheme: item.presentationData.theme.overallDarkAppearance,
|
||||||
activeLineWidth: 1.0 + UIScreenPixel,
|
activeLineWidth: 1.0 + UIScreenPixel,
|
||||||
inactiveLineWidth: 1.0 + UIScreenPixel,
|
inactiveLineWidth: 1.0 + UIScreenPixel,
|
||||||
|
@ -124,6 +124,7 @@ public enum Stories {
|
|||||||
case isPinned
|
case isPinned
|
||||||
case isExpired
|
case isExpired
|
||||||
case isPublic
|
case isPublic
|
||||||
|
case isCloseFriends
|
||||||
}
|
}
|
||||||
|
|
||||||
public let id: Int32
|
public let id: Int32
|
||||||
@ -137,6 +138,7 @@ public enum Stories {
|
|||||||
public let isPinned: Bool
|
public let isPinned: Bool
|
||||||
public let isExpired: Bool
|
public let isExpired: Bool
|
||||||
public let isPublic: Bool
|
public let isPublic: Bool
|
||||||
|
public let isCloseFriends: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
id: Int32,
|
id: Int32,
|
||||||
@ -149,7 +151,8 @@ public enum Stories {
|
|||||||
privacy: Privacy?,
|
privacy: Privacy?,
|
||||||
isPinned: Bool,
|
isPinned: Bool,
|
||||||
isExpired: Bool,
|
isExpired: Bool,
|
||||||
isPublic: Bool
|
isPublic: Bool,
|
||||||
|
isCloseFriends: Bool
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
@ -162,6 +165,7 @@ public enum Stories {
|
|||||||
self.isPinned = isPinned
|
self.isPinned = isPinned
|
||||||
self.isExpired = isExpired
|
self.isExpired = isExpired
|
||||||
self.isPublic = isPublic
|
self.isPublic = isPublic
|
||||||
|
self.isCloseFriends = isCloseFriends
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
@ -184,6 +188,7 @@ public enum Stories {
|
|||||||
self.isPinned = try container.decodeIfPresent(Bool.self, forKey: .isPinned) ?? false
|
self.isPinned = try container.decodeIfPresent(Bool.self, forKey: .isPinned) ?? false
|
||||||
self.isExpired = try container.decodeIfPresent(Bool.self, forKey: .isExpired) ?? false
|
self.isExpired = try container.decodeIfPresent(Bool.self, forKey: .isExpired) ?? false
|
||||||
self.isPublic = try container.decodeIfPresent(Bool.self, forKey: .isPublic) ?? false
|
self.isPublic = try container.decodeIfPresent(Bool.self, forKey: .isPublic) ?? false
|
||||||
|
self.isCloseFriends = try container.decodeIfPresent(Bool.self, forKey: .isCloseFriends) ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
@ -207,6 +212,7 @@ public enum Stories {
|
|||||||
try container.encode(self.isPinned, forKey: .isPinned)
|
try container.encode(self.isPinned, forKey: .isPinned)
|
||||||
try container.encode(self.isExpired, forKey: .isExpired)
|
try container.encode(self.isExpired, forKey: .isExpired)
|
||||||
try container.encode(self.isPublic, forKey: .isPublic)
|
try container.encode(self.isPublic, forKey: .isPublic)
|
||||||
|
try container.encode(self.isCloseFriends, forKey: .isCloseFriends)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
@ -251,6 +257,9 @@ public enum Stories {
|
|||||||
if lhs.isPublic != rhs.isPublic {
|
if lhs.isPublic != rhs.isPublic {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isCloseFriends != rhs.isCloseFriends {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -456,6 +465,7 @@ public final class EngineStorySubscriptions: Equatable {
|
|||||||
public final class Item: Equatable {
|
public final class Item: Equatable {
|
||||||
public let peer: EnginePeer
|
public let peer: EnginePeer
|
||||||
public let hasUnseen: Bool
|
public let hasUnseen: Bool
|
||||||
|
public let hasUnseenCloseFriends: Bool
|
||||||
public let storyCount: Int
|
public let storyCount: Int
|
||||||
public let unseenCount: Int
|
public let unseenCount: Int
|
||||||
public let lastTimestamp: Int32
|
public let lastTimestamp: Int32
|
||||||
@ -463,12 +473,14 @@ public final class EngineStorySubscriptions: Equatable {
|
|||||||
public init(
|
public init(
|
||||||
peer: EnginePeer,
|
peer: EnginePeer,
|
||||||
hasUnseen: Bool,
|
hasUnseen: Bool,
|
||||||
|
hasUnseenCloseFriends: Bool,
|
||||||
storyCount: Int,
|
storyCount: Int,
|
||||||
unseenCount: Int,
|
unseenCount: Int,
|
||||||
lastTimestamp: Int32
|
lastTimestamp: Int32
|
||||||
) {
|
) {
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.hasUnseen = hasUnseen
|
self.hasUnseen = hasUnseen
|
||||||
|
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||||
self.storyCount = storyCount
|
self.storyCount = storyCount
|
||||||
self.unseenCount = unseenCount
|
self.unseenCount = unseenCount
|
||||||
self.lastTimestamp = lastTimestamp
|
self.lastTimestamp = lastTimestamp
|
||||||
@ -484,6 +496,9 @@ public final class EngineStorySubscriptions: Equatable {
|
|||||||
if lhs.hasUnseen != rhs.hasUnseen {
|
if lhs.hasUnseen != rhs.hasUnseen {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasUnseenCloseFriends != rhs.hasUnseenCloseFriends {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.storyCount != rhs.storyCount {
|
if lhs.storyCount != rhs.storyCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -807,7 +822,8 @@ func _internal_uploadStoryImpl(postbox: Postbox, network: Network, accountPeerId
|
|||||||
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
||||||
items.append(StoryItemsTableEntry(value: entry, id: item.id))
|
items.append(StoryItemsTableEntry(value: entry, id: item.id))
|
||||||
@ -954,7 +970,8 @@ func _internal_editStoryPrivacy(account: Account, id: Int32, privacy: EngineStor
|
|||||||
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
||||||
transaction.setStory(id: storyId, value: entry)
|
transaction.setStory(id: storyId, value: entry)
|
||||||
@ -975,7 +992,8 @@ func _internal_editStoryPrivacy(account: Account, id: Int32, privacy: EngineStor
|
|||||||
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
privacy: Stories.Item.Privacy(base: privacy.base, additionallyIncludePeers: privacy.additionallyIncludePeers),
|
||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
||||||
items[index] = StoryItemsTableEntry(value: entry, id: item.id)
|
items[index] = StoryItemsTableEntry(value: entry, id: item.id)
|
||||||
@ -1105,7 +1123,8 @@ func _internal_updateStoriesArePinned(account: Account, ids: [Int32: EngineStory
|
|||||||
privacy: item.privacy,
|
privacy: item.privacy,
|
||||||
isPinned: isPinned,
|
isPinned: isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
if let entry = CodableEntry(Stories.StoredItem.item(updatedItem)) {
|
||||||
items[index] = StoryItemsTableEntry(value: entry, id: item.id)
|
items[index] = StoryItemsTableEntry(value: entry, id: item.id)
|
||||||
@ -1125,7 +1144,8 @@ func _internal_updateStoriesArePinned(account: Account, ids: [Int32: EngineStory
|
|||||||
privacy: item.privacy,
|
privacy: item.privacy,
|
||||||
isPinned: isPinned,
|
isPinned: isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
updatedItems.append(updatedItem)
|
updatedItems.append(updatedItem)
|
||||||
}
|
}
|
||||||
@ -1220,6 +1240,7 @@ extension Stories.StoredItem {
|
|||||||
let isPinned = (flags & (1 << 5)) != 0
|
let isPinned = (flags & (1 << 5)) != 0
|
||||||
let isExpired = (flags & (1 << 6)) != 0
|
let isExpired = (flags & (1 << 6)) != 0
|
||||||
let isPublic = (flags & (1 << 7)) != 0
|
let isPublic = (flags & (1 << 7)) != 0
|
||||||
|
let isCloseFriends = (flags & (1 << 8)) != 0
|
||||||
|
|
||||||
let item = Stories.Item(
|
let item = Stories.Item(
|
||||||
id: id,
|
id: id,
|
||||||
@ -1232,7 +1253,8 @@ extension Stories.StoredItem {
|
|||||||
privacy: parsedPrivacy,
|
privacy: parsedPrivacy,
|
||||||
isPinned: isPinned,
|
isPinned: isPinned,
|
||||||
isExpired: isExpired,
|
isExpired: isExpired,
|
||||||
isPublic: isPublic
|
isPublic: isPublic,
|
||||||
|
isCloseFriends: isCloseFriends
|
||||||
)
|
)
|
||||||
self = .item(item)
|
self = .item(item)
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,8 +43,9 @@ public final class EngineStoryItem: Equatable {
|
|||||||
public let isExpired: Bool
|
public let isExpired: Bool
|
||||||
public let isPublic: Bool
|
public let isPublic: Bool
|
||||||
public let isPending: Bool
|
public let isPending: Bool
|
||||||
|
public let isCloseFriends: Bool
|
||||||
|
|
||||||
public init(id: Int32, timestamp: Int32, expirationTimestamp: Int32, media: EngineMedia, text: String, entities: [MessageTextEntity], views: Views?, privacy: EngineStoryPrivacy?, isPinned: Bool, isExpired: Bool, isPublic: Bool, isPending: Bool) {
|
public init(id: Int32, timestamp: Int32, expirationTimestamp: Int32, media: EngineMedia, text: String, entities: [MessageTextEntity], views: Views?, privacy: EngineStoryPrivacy?, isPinned: Bool, isExpired: Bool, isPublic: Bool, isPending: Bool, isCloseFriends: Bool) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
self.expirationTimestamp = expirationTimestamp
|
self.expirationTimestamp = expirationTimestamp
|
||||||
@ -57,6 +58,7 @@ public final class EngineStoryItem: Equatable {
|
|||||||
self.isExpired = isExpired
|
self.isExpired = isExpired
|
||||||
self.isPublic = isPublic
|
self.isPublic = isPublic
|
||||||
self.isPending = isPending
|
self.isPending = isPending
|
||||||
|
self.isCloseFriends = isCloseFriends
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: EngineStoryItem, rhs: EngineStoryItem) -> Bool {
|
public static func ==(lhs: EngineStoryItem, rhs: EngineStoryItem) -> Bool {
|
||||||
@ -96,6 +98,9 @@ public final class EngineStoryItem: Equatable {
|
|||||||
if lhs.isPending != rhs.isPending {
|
if lhs.isPending != rhs.isPending {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isCloseFriends != rhs.isCloseFriends {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +128,8 @@ extension EngineStoryItem {
|
|||||||
},
|
},
|
||||||
isPinned: self.isPinned,
|
isPinned: self.isPinned,
|
||||||
isExpired: self.isExpired,
|
isExpired: self.isExpired,
|
||||||
isPublic: self.isPublic
|
isPublic: self.isPublic,
|
||||||
|
isCloseFriends: self.isCloseFriends
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +486,8 @@ public final class PeerStoryListContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
items.append(mappedItem)
|
items.append(mappedItem)
|
||||||
}
|
}
|
||||||
@ -585,7 +592,8 @@ public final class PeerStoryListContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
storyItems.append(mappedItem)
|
storyItems.append(mappedItem)
|
||||||
}
|
}
|
||||||
@ -717,7 +725,8 @@ public final class PeerStoryListContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
finalUpdatedState = updatedState
|
finalUpdatedState = updatedState
|
||||||
}
|
}
|
||||||
@ -754,7 +763,8 @@ public final class PeerStoryListContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
))
|
))
|
||||||
updatedState.items.sort(by: { lhs, rhs in
|
updatedState.items.sort(by: { lhs, rhs in
|
||||||
return lhs.timestamp > rhs.timestamp
|
return lhs.timestamp > rhs.timestamp
|
||||||
@ -900,7 +910,8 @@ public final class PeerExpiringStoryListContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
items.append(.item(mappedItem))
|
items.append(.item(mappedItem))
|
||||||
}
|
}
|
||||||
@ -1035,6 +1046,15 @@ public final class PeerExpiringStoryListContext {
|
|||||||
return timestamp
|
return timestamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var isCloseFriends: Bool {
|
||||||
|
switch self {
|
||||||
|
case let .item(item):
|
||||||
|
return item.isCloseFriends
|
||||||
|
case .placeholder:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class State: Equatable {
|
public final class State: Equatable {
|
||||||
@ -1046,6 +1066,10 @@ public final class PeerExpiringStoryListContext {
|
|||||||
return self.items.contains(where: { $0.id > self.maxReadId })
|
return self.items.contains(where: { $0.id > self.maxReadId })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var hasUnseenCloseFriends: Bool {
|
||||||
|
return self.items.contains(where: { $0.id > self.maxReadId && $0.isCloseFriends })
|
||||||
|
}
|
||||||
|
|
||||||
public init(items: [Item], isCached: Bool, maxReadId: Int32) {
|
public init(items: [Item], isCached: Bool, maxReadId: Int32) {
|
||||||
self.items = items
|
self.items = items
|
||||||
self.isCached = isCached
|
self.isCached = isCached
|
||||||
|
@ -679,6 +679,7 @@ public extension TelegramEngine {
|
|||||||
var accountItem: EngineStorySubscriptions.Item = EngineStorySubscriptions.Item(
|
var accountItem: EngineStorySubscriptions.Item = EngineStorySubscriptions.Item(
|
||||||
peer: EnginePeer(accountPeer),
|
peer: EnginePeer(accountPeer),
|
||||||
hasUnseen: false,
|
hasUnseen: false,
|
||||||
|
hasUnseenCloseFriends: false,
|
||||||
storyCount: 0,
|
storyCount: 0,
|
||||||
unseenCount: 0,
|
unseenCount: 0,
|
||||||
lastTimestamp: 0
|
lastTimestamp: 0
|
||||||
@ -693,6 +694,7 @@ public extension TelegramEngine {
|
|||||||
if let lastEntry = itemsView.items.last?.value.get(Stories.StoredItem.self) {
|
if let lastEntry = itemsView.items.last?.value.get(Stories.StoredItem.self) {
|
||||||
let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self)
|
let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self)
|
||||||
var hasUnseen = false
|
var hasUnseen = false
|
||||||
|
var hasUnseenCloseFriends = false
|
||||||
var unseenCount = 0
|
var unseenCount = 0
|
||||||
if let peerState = peerState {
|
if let peerState = peerState {
|
||||||
hasUnseen = peerState.maxReadId < lastEntry.id
|
hasUnseen = peerState.maxReadId < lastEntry.id
|
||||||
@ -700,6 +702,12 @@ public extension TelegramEngine {
|
|||||||
for item in itemsView.items {
|
for item in itemsView.items {
|
||||||
if item.id > peerState.maxReadId {
|
if item.id > peerState.maxReadId {
|
||||||
unseenCount += 1
|
unseenCount += 1
|
||||||
|
|
||||||
|
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
|
||||||
|
if item.isCloseFriends {
|
||||||
|
hasUnseenCloseFriends = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -707,6 +715,7 @@ public extension TelegramEngine {
|
|||||||
let item = EngineStorySubscriptions.Item(
|
let item = EngineStorySubscriptions.Item(
|
||||||
peer: EnginePeer(accountPeer),
|
peer: EnginePeer(accountPeer),
|
||||||
hasUnseen: hasUnseen,
|
hasUnseen: hasUnseen,
|
||||||
|
hasUnseenCloseFriends: hasUnseenCloseFriends,
|
||||||
storyCount: itemsView.items.count,
|
storyCount: itemsView.items.count,
|
||||||
unseenCount: unseenCount,
|
unseenCount: unseenCount,
|
||||||
lastTimestamp: lastEntry.timestamp
|
lastTimestamp: lastEntry.timestamp
|
||||||
@ -735,6 +744,7 @@ public extension TelegramEngine {
|
|||||||
|
|
||||||
let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self)
|
let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self)
|
||||||
var hasUnseen = false
|
var hasUnseen = false
|
||||||
|
var hasUnseenCloseFriends = false
|
||||||
var unseenCount = 0
|
var unseenCount = 0
|
||||||
if let peerState = peerState {
|
if let peerState = peerState {
|
||||||
hasUnseen = peerState.maxReadId < lastEntry.id
|
hasUnseen = peerState.maxReadId < lastEntry.id
|
||||||
@ -742,6 +752,12 @@ public extension TelegramEngine {
|
|||||||
for item in itemsView.items {
|
for item in itemsView.items {
|
||||||
if item.id > peerState.maxReadId {
|
if item.id > peerState.maxReadId {
|
||||||
unseenCount += 1
|
unseenCount += 1
|
||||||
|
|
||||||
|
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
|
||||||
|
if item.isCloseFriends {
|
||||||
|
hasUnseenCloseFriends = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -749,6 +765,7 @@ public extension TelegramEngine {
|
|||||||
let item = EngineStorySubscriptions.Item(
|
let item = EngineStorySubscriptions.Item(
|
||||||
peer: EnginePeer(peer),
|
peer: EnginePeer(peer),
|
||||||
hasUnseen: hasUnseen,
|
hasUnseen: hasUnseen,
|
||||||
|
hasUnseenCloseFriends: hasUnseenCloseFriends,
|
||||||
storyCount: itemsView.items.count,
|
storyCount: itemsView.items.count,
|
||||||
unseenCount: unseenCount,
|
unseenCount: unseenCount,
|
||||||
lastTimestamp: lastEntry.timestamp
|
lastTimestamp: lastEntry.timestamp
|
||||||
@ -935,7 +952,8 @@ public extension TelegramEngine {
|
|||||||
privacy: item.privacy,
|
privacy: item.privacy,
|
||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic
|
isPublic: item.isPublic,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
))
|
))
|
||||||
if let entry = CodableEntry(updatedItem) {
|
if let entry = CodableEntry(updatedItem) {
|
||||||
currentItems[i] = StoryItemsTableEntry(value: entry, id: updatedItem.id)
|
currentItems[i] = StoryItemsTableEntry(value: entry, id: updatedItem.id)
|
||||||
|
@ -30,7 +30,7 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
|
|||||||
private var avatarVideoNode: AvatarVideoNode?
|
private var avatarVideoNode: AvatarVideoNode?
|
||||||
|
|
||||||
public private(set) var avatarStoryView: ComponentView<Empty>?
|
public private(set) var avatarStoryView: ComponentView<Empty>?
|
||||||
public var hasUnseenStories: Bool?
|
public var storyData: (hasUnseen: Bool, hasUnseenCloseFriends: Bool)?
|
||||||
|
|
||||||
public let statusView: ComponentView<Empty>
|
public let statusView: ComponentView<Empty>
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
|
|||||||
self.avatarNode.frame = self.containerNode.bounds
|
self.avatarNode.frame = self.containerNode.bounds
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
self.hasUnseenStories = true
|
//self.hasUnseenStories = true
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) {
|
public func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) {
|
||||||
if let hasUnseenStories = self.hasUnseenStories {
|
if let storyData = self.storyData {
|
||||||
let avatarStoryView: ComponentView<Empty>
|
let avatarStoryView: ComponentView<Empty>
|
||||||
if let current = self.avatarStoryView {
|
if let current = self.avatarStoryView {
|
||||||
avatarStoryView = current
|
avatarStoryView = current
|
||||||
@ -212,7 +212,8 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
|
|||||||
let _ = avatarStoryView.update(
|
let _ = avatarStoryView.update(
|
||||||
transition: Transition(transition),
|
transition: Transition(transition),
|
||||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||||
hasUnseen: hasUnseenStories,
|
hasUnseen: storyData.hasUnseen,
|
||||||
|
hasUnseenCloseFriendsItems: storyData.hasUnseenCloseFriends,
|
||||||
isDarkTheme: theme.overallDarkAppearance,
|
isDarkTheme: theme.overallDarkAppearance,
|
||||||
activeLineWidth: 1.0,
|
activeLineWidth: 1.0,
|
||||||
inactiveLineWidth: 1.0,
|
inactiveLineWidth: 1.0,
|
||||||
|
@ -16,6 +16,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public let hasUnseen: Bool
|
public let hasUnseen: Bool
|
||||||
|
public let hasUnseenCloseFriendsItems: Bool
|
||||||
public let isDarkTheme: Bool
|
public let isDarkTheme: Bool
|
||||||
public let activeLineWidth: CGFloat
|
public let activeLineWidth: CGFloat
|
||||||
public let inactiveLineWidth: CGFloat
|
public let inactiveLineWidth: CGFloat
|
||||||
@ -23,12 +24,14 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
hasUnseen: Bool,
|
hasUnseen: Bool,
|
||||||
|
hasUnseenCloseFriendsItems: Bool,
|
||||||
isDarkTheme: Bool,
|
isDarkTheme: Bool,
|
||||||
activeLineWidth: CGFloat,
|
activeLineWidth: CGFloat,
|
||||||
inactiveLineWidth: CGFloat,
|
inactiveLineWidth: CGFloat,
|
||||||
counters: Counters?
|
counters: Counters?
|
||||||
) {
|
) {
|
||||||
self.hasUnseen = hasUnseen
|
self.hasUnseen = hasUnseen
|
||||||
|
self.hasUnseenCloseFriendsItems = hasUnseenCloseFriendsItems
|
||||||
self.isDarkTheme = isDarkTheme
|
self.isDarkTheme = isDarkTheme
|
||||||
self.activeLineWidth = activeLineWidth
|
self.activeLineWidth = activeLineWidth
|
||||||
self.inactiveLineWidth = inactiveLineWidth
|
self.inactiveLineWidth = inactiveLineWidth
|
||||||
@ -39,6 +42,9 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
if lhs.hasUnseen != rhs.hasUnseen {
|
if lhs.hasUnseen != rhs.hasUnseen {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasUnseenCloseFriendsItems != rhs.hasUnseenCloseFriendsItems {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.isDarkTheme != rhs.isDarkTheme {
|
if lhs.isDarkTheme != rhs.isDarkTheme {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -91,6 +97,27 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
self.indicatorView.image = generateImage(CGSize(width: imageDiameter, height: imageDiameter), rotatedContext: { size, context in
|
self.indicatorView.image = generateImage(CGSize(width: imageDiameter, height: imageDiameter), rotatedContext: { size, context in
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
let activeColors: [CGColor]
|
||||||
|
let inactiveColors: [CGColor]
|
||||||
|
|
||||||
|
if component.hasUnseenCloseFriendsItems {
|
||||||
|
activeColors = [
|
||||||
|
UIColor(rgb: 0x7CD636).cgColor,
|
||||||
|
UIColor(rgb: 0x26B470).cgColor
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
activeColors = [
|
||||||
|
UIColor(rgb: 0x34C76F).cgColor,
|
||||||
|
UIColor(rgb: 0x3DA1FD).cgColor
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if component.isDarkTheme {
|
||||||
|
inactiveColors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
|
||||||
|
} else {
|
||||||
|
inactiveColors = [UIColor(rgb: 0xD8D8E1).cgColor, UIColor(rgb: 0xD8D8E1).cgColor]
|
||||||
|
}
|
||||||
|
|
||||||
context.setLineWidth(lineWidth)
|
context.setLineWidth(lineWidth)
|
||||||
|
|
||||||
if let counters = component.counters, counters.totalCount > 1 {
|
if let counters = component.counters, counters.totalCount > 1 {
|
||||||
@ -127,13 +154,9 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
var locations: [CGFloat] = [1.0, 0.0]
|
var locations: [CGFloat] = [1.0, 0.0]
|
||||||
let colors: [CGColor]
|
let colors: [CGColor]
|
||||||
if pass == 1 {
|
if pass == 1 {
|
||||||
colors = [UIColor(rgb: 0x34C76F).cgColor, UIColor(rgb: 0x3DA1FD).cgColor]
|
colors = activeColors
|
||||||
} else {
|
} else {
|
||||||
if component.isDarkTheme {
|
colors = inactiveColors
|
||||||
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
|
|
||||||
} else {
|
|
||||||
colors = [UIColor(rgb: 0xD8D8E1).cgColor, UIColor(rgb: 0xD8D8E1).cgColor]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
|
@ -138,7 +138,8 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
isPinned: item.isPinned,
|
isPinned: item.isPinned,
|
||||||
isExpired: item.isExpired,
|
isExpired: item.isExpired,
|
||||||
isPublic: item.isPublic,
|
isPublic: item.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: item.isCloseFriends
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if peerId == context.account.peerId, let stateView = views.views[PostboxViewKey.storiesState(key: .local)] as? StoryStatesView, let localState = stateView.value?.get(Stories.LocalState.self) {
|
if peerId == context.account.peerId, let stateView = views.views[PostboxViewKey.storiesState(key: .local)] as? StoryStatesView, let localState = stateView.value?.get(Stories.LocalState.self) {
|
||||||
@ -155,7 +156,8 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
isPinned: item.pin,
|
isPinned: item.pin,
|
||||||
isExpired: false,
|
isExpired: false,
|
||||||
isPublic: false,
|
isPublic: false,
|
||||||
isPending: true
|
isPending: true,
|
||||||
|
isCloseFriends: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,6 +436,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
items: [EngineStorySubscriptions.Item(
|
items: [EngineStorySubscriptions.Item(
|
||||||
peer: peer,
|
peer: peer,
|
||||||
hasUnseen: state.hasUnseen,
|
hasUnseen: state.hasUnseen,
|
||||||
|
hasUnseenCloseFriends: state.hasUnseenCloseFriends,
|
||||||
storyCount: state.items.count,
|
storyCount: state.items.count,
|
||||||
unseenCount: 0,
|
unseenCount: 0,
|
||||||
lastTimestamp: state.items.last?.timestamp ?? 0
|
lastTimestamp: state.items.last?.timestamp ?? 0
|
||||||
@ -953,7 +956,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
|||||||
isPinned: itemValue.isPinned,
|
isPinned: itemValue.isPinned,
|
||||||
isExpired: itemValue.isExpired,
|
isExpired: itemValue.isExpired,
|
||||||
isPublic: itemValue.isPublic,
|
isPublic: itemValue.isPublic,
|
||||||
isPending: false
|
isPending: false,
|
||||||
|
isCloseFriends: itemValue.isCloseFriends
|
||||||
)
|
)
|
||||||
|
|
||||||
let stateValue = StoryContentContextState(
|
let stateValue = StoryContentContextState(
|
||||||
|
@ -603,6 +603,8 @@ public final class StoryPeerListComponent: Component {
|
|||||||
var hasUnseen = false
|
var hasUnseen = false
|
||||||
hasUnseen = itemSet.hasUnseen
|
hasUnseen = itemSet.hasUnseen
|
||||||
|
|
||||||
|
var hasUnseenCloseFriendsItems = itemSet.hasUnseenCloseFriends
|
||||||
|
|
||||||
var hasItems = true
|
var hasItems = true
|
||||||
var itemRingAnimation: StoryPeerListItemComponent.RingAnimation?
|
var itemRingAnimation: StoryPeerListItemComponent.RingAnimation?
|
||||||
if peer.id == component.context.account.peerId {
|
if peer.id == component.context.account.peerId {
|
||||||
@ -614,6 +616,8 @@ public final class StoryPeerListComponent: Component {
|
|||||||
if let uploadProgress = component.uploadProgress {
|
if let uploadProgress = component.uploadProgress {
|
||||||
itemRingAnimation = .progress(uploadProgress)
|
itemRingAnimation = .progress(uploadProgress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasUnseenCloseFriendsItems = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let measuredItem = calculateItem(i)
|
let measuredItem = calculateItem(i)
|
||||||
@ -655,6 +659,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
peer: peer,
|
peer: peer,
|
||||||
hasUnseen: hasUnseen,
|
hasUnseen: hasUnseen,
|
||||||
|
hasUnseenCloseFriendsItems: hasUnseenCloseFriendsItems,
|
||||||
hasItems: hasItems,
|
hasItems: hasItems,
|
||||||
ringAnimation: itemRingAnimation,
|
ringAnimation: itemRingAnimation,
|
||||||
collapseFraction: isReallyVisible ? (1.0 - collapsedState.maxFraction) : 0.0,
|
collapseFraction: isReallyVisible ? (1.0 - collapsedState.maxFraction) : 0.0,
|
||||||
|
@ -266,6 +266,7 @@ public final class StoryPeerListItemComponent: Component {
|
|||||||
public let strings: PresentationStrings
|
public let strings: PresentationStrings
|
||||||
public let peer: EnginePeer
|
public let peer: EnginePeer
|
||||||
public let hasUnseen: Bool
|
public let hasUnseen: Bool
|
||||||
|
public let hasUnseenCloseFriendsItems: Bool
|
||||||
public let hasItems: Bool
|
public let hasItems: Bool
|
||||||
public let ringAnimation: RingAnimation?
|
public let ringAnimation: RingAnimation?
|
||||||
public let collapseFraction: CGFloat
|
public let collapseFraction: CGFloat
|
||||||
@ -283,6 +284,7 @@ public final class StoryPeerListItemComponent: Component {
|
|||||||
strings: PresentationStrings,
|
strings: PresentationStrings,
|
||||||
peer: EnginePeer,
|
peer: EnginePeer,
|
||||||
hasUnseen: Bool,
|
hasUnseen: Bool,
|
||||||
|
hasUnseenCloseFriendsItems: Bool,
|
||||||
hasItems: Bool,
|
hasItems: Bool,
|
||||||
ringAnimation: RingAnimation?,
|
ringAnimation: RingAnimation?,
|
||||||
collapseFraction: CGFloat,
|
collapseFraction: CGFloat,
|
||||||
@ -299,6 +301,7 @@ public final class StoryPeerListItemComponent: Component {
|
|||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.hasUnseen = hasUnseen
|
self.hasUnseen = hasUnseen
|
||||||
|
self.hasUnseenCloseFriendsItems = hasUnseenCloseFriendsItems
|
||||||
self.hasItems = hasItems
|
self.hasItems = hasItems
|
||||||
self.ringAnimation = ringAnimation
|
self.ringAnimation = ringAnimation
|
||||||
self.collapseFraction = collapseFraction
|
self.collapseFraction = collapseFraction
|
||||||
@ -327,6 +330,9 @@ public final class StoryPeerListItemComponent: Component {
|
|||||||
if lhs.hasUnseen != rhs.hasUnseen {
|
if lhs.hasUnseen != rhs.hasUnseen {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasUnseenCloseFriendsItems != rhs.hasUnseenCloseFriendsItems {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.hasItems != rhs.hasItems {
|
if lhs.hasItems != rhs.hasItems {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -646,7 +652,17 @@ public final class StoryPeerListItemComponent: Component {
|
|||||||
let colors: [CGColor]
|
let colors: [CGColor]
|
||||||
|
|
||||||
if component.hasUnseen || component.ringAnimation != nil {
|
if component.hasUnseen || component.ringAnimation != nil {
|
||||||
colors = [UIColor(rgb: 0x34C76F).cgColor, UIColor(rgb: 0x3DA1FD).cgColor]
|
if component.hasUnseenCloseFriendsItems {
|
||||||
|
colors = [
|
||||||
|
UIColor(rgb: 0x7CD636).cgColor,
|
||||||
|
UIColor(rgb: 0x26B470).cgColor
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
colors = [
|
||||||
|
UIColor(rgb: 0x34C76F).cgColor,
|
||||||
|
UIColor(rgb: 0x3DA1FD).cgColor
|
||||||
|
]
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if component.theme.overallDarkAppearance {
|
if component.theme.overallDarkAppearance {
|
||||||
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
|
colors = [UIColor(rgb: 0x48484A).cgColor, UIColor(rgb: 0x48484A).cgColor]
|
||||||
|
@ -421,7 +421,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private let playbackStartDisposable = MetaDisposable()
|
private let playbackStartDisposable = MetaDisposable()
|
||||||
|
|
||||||
var hasUnseenStories: Bool?
|
var storyData: (hasUnseen: Bool, hasUnseenCloseFriends: Bool)?
|
||||||
|
|
||||||
init(context: AccountContext) {
|
init(context: AccountContext) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -455,7 +455,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) {
|
func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) {
|
||||||
if let hasUnseenStories = self.hasUnseenStories {
|
if let storyData = self.storyData {
|
||||||
let avatarStoryView: ComponentView<Empty>
|
let avatarStoryView: ComponentView<Empty>
|
||||||
if let current = self.avatarStoryView {
|
if let current = self.avatarStoryView {
|
||||||
avatarStoryView = current
|
avatarStoryView = current
|
||||||
@ -467,7 +467,8 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
let _ = avatarStoryView.update(
|
let _ = avatarStoryView.update(
|
||||||
transition: Transition(transition),
|
transition: Transition(transition),
|
||||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||||
hasUnseen: hasUnseenStories,
|
hasUnseen: storyData.hasUnseen,
|
||||||
|
hasUnseenCloseFriendsItems: storyData.hasUnseenCloseFriends,
|
||||||
isDarkTheme: theme.overallDarkAppearance,
|
isDarkTheme: theme.overallDarkAppearance,
|
||||||
activeLineWidth: 3.0,
|
activeLineWidth: 3.0,
|
||||||
inactiveLineWidth: 2.0,
|
inactiveLineWidth: 2.0,
|
||||||
|
@ -3879,10 +3879,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
self.expiringStoryListState = state
|
self.expiringStoryListState = state
|
||||||
if state.items.isEmpty {
|
if state.items.isEmpty {
|
||||||
self.headerNode.avatarListNode.avatarContainerNode.hasUnseenStories = nil
|
self.headerNode.avatarListNode.avatarContainerNode.storyData = nil
|
||||||
self.headerNode.avatarListNode.listContainerNode.storyParams = nil
|
self.headerNode.avatarListNode.listContainerNode.storyParams = nil
|
||||||
} else {
|
} else {
|
||||||
self.headerNode.avatarListNode.avatarContainerNode.hasUnseenStories = state.hasUnseen
|
self.headerNode.avatarListNode.avatarContainerNode.storyData = (state.hasUnseen, state.hasUnseenCloseFriends)
|
||||||
self.headerNode.avatarListNode.listContainerNode.storyParams = (peer, state.items.prefix(3).compactMap { item -> EngineStoryItem? in
|
self.headerNode.avatarListNode.listContainerNode.storyParams = (peer, state.items.prefix(3).compactMap { item -> EngineStoryItem? in
|
||||||
switch item {
|
switch item {
|
||||||
case let .item(item):
|
case let .item(item):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user