This commit is contained in:
Isaac 2025-10-26 22:05:58 +04:00
parent fcdfd8e00f
commit c880397eca
17 changed files with 194 additions and 58 deletions

View File

@ -1338,9 +1338,9 @@ public final class Transaction {
self.postbox!.setStoryItems(peerId: peerId, items: items)
}
public func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32) {
public func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32, hasLiveItems: Bool) {
assert(!self.disposed)
self.postbox!.setStoryItemsInexactMaxId(peerId: peerId, id: id)
self.postbox!.setStoryItemsInexactMaxId(peerId: peerId, id: id, hasLiveItems: hasLiveItems)
}
public func clearStoryItemsInexactMaxId(peerId: PeerId) {
@ -2451,10 +2451,10 @@ final class PostboxImpl {
}
}
fileprivate func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32) {
fileprivate func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32, hasLiveItems: Bool) {
if let value = self.storyTopItemsTable.get(peerId: peerId), value.id >= id {
} else {
self.storyTopItemsTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: id, isExact: false), events: &self.currentStoryTopItemEvents)
self.storyTopItemsTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: id, isExact: false, hasLiveItems: hasLiveItems), events: &self.currentStoryTopItemEvents)
}
}

View File

@ -48,6 +48,7 @@ final class StoryTopItemsTable: Table {
struct Entry {
var id: Int32
var isExact: Bool
var hasLiveItems: Bool
}
enum Event {
@ -78,10 +79,12 @@ final class StoryTopItemsTable: Table {
}
var maxId: Int32 = 0
buffer.read(&maxId, offset: 0, length: 4)
var isExact: Int8 = 0
buffer.read(&isExact, offset: 0, length: 1)
var flags: Int8 = 0
buffer.read(&flags, offset: 0, length: 1)
let isExact = (flags & (1 << 0)) != 0
let hasLiveItems = (flags & (1 << 1)) != 0
return Entry(id: maxId, isExact: isExact != 0)
return Entry(id: maxId, isExact: isExact, hasLiveItems: hasLiveItems)
} else {
return nil
}
@ -95,8 +98,14 @@ final class StoryTopItemsTable: Table {
buffer.write(&version, length: 1)
var maxId = entry.id
buffer.write(&maxId, length: 4)
var isExact: Int8 = entry.isExact ? 1 : 0
buffer.write(&isExact, length: 1)
var flags: Int8 = 0
if entry.isExact {
flags |= 1 << 0
}
if entry.hasLiveItems {
flags |= 1 << 1
}
buffer.write(&flags, length: 1)
self.valueBox.set(self.table, key: self.key(Key(peerId: peerId)), value: buffer.readBufferNoCopy())
} else {
@ -382,6 +391,8 @@ final class StoryItemsTable: Table {
self.valueBox.remove(self.table, key: key, secure: true)
}
var hasLiveItems = false
let buffer = WriteBuffer()
for entry in entries {
buffer.reset()
@ -401,6 +412,7 @@ final class StoryItemsTable: Table {
flags |= (1 << 0)
}
if entry.isLiveStream {
hasLiveItems = true
flags |= (1 << 1)
}
buffer.write(&flags, length: 1)
@ -410,7 +422,7 @@ final class StoryItemsTable: Table {
events.append(.replace(peerId: peerId))
topItemTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: entries.last?.id ?? 0, isExact: true), events: &topItemEvents)
topItemTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: entries.last?.id ?? 0, isExact: true, hasLiveItems: hasLiveItems), events: &topItemEvents)
}
override func clearMemoryCache() {

View File

@ -196,7 +196,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-531931925] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsMentions($0) }
dict[-566281095] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsRecent($0) }
dict[106343499] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsSearch($0) }
dict[-26717355] = { return Api.Chat.parse_channel($0) }
dict[473084188] = { return Api.Chat.parse_channel($0) }
dict[399807445] = { return Api.Chat.parse_channelForbidden($0) }
dict[1103884886] = { return Api.Chat.parse_chat($0) }
dict[693512293] = { return Api.Chat.parse_chatEmpty($0) }
@ -857,6 +857,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1140172836] = { return Api.RecentMeUrl.parse_recentMeUrlStickerSet($0) }
dict[1189204285] = { return Api.RecentMeUrl.parse_recentMeUrlUnknown($0) }
dict[-1188296222] = { return Api.RecentMeUrl.parse_recentMeUrlUser($0) }
dict[1897752877] = { return Api.RecentStory.parse_recentStory($0) }
dict[1218642516] = { return Api.ReplyMarkup.parse_replyInlineMarkup($0) }
dict[-2035021048] = { return Api.ReplyMarkup.parse_replyKeyboardForceReply($0) }
dict[-1606526075] = { return Api.ReplyMarkup.parse_replyKeyboardHide($0) }
@ -1208,7 +1209,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1886646706] = { return Api.UrlAuthResult.parse_urlAuthResultAccepted($0) }
dict[-1445536993] = { return Api.UrlAuthResult.parse_urlAuthResultDefault($0) }
dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
dict[34280482] = { return Api.User.parse_user($0) }
dict[829899656] = { return Api.User.parse_user($0) }
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
dict[-1607745218] = { return Api.UserFull.parse_userFull($0) }
dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
@ -2126,6 +2127,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.RecentMeUrl:
_1.serialize(buffer, boxed)
case let _1 as Api.RecentStory:
_1.serialize(buffer, boxed)
case let _1 as Api.ReplyMarkup:
_1.serialize(buffer, boxed)
case let _1 as Api.ReportReason:

View File

@ -174,6 +174,46 @@ public extension Api {
}
}
public extension Api {
enum RecentStory: TypeConstructorDescription {
case recentStory(flags: Int32, maxId: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .recentStory(let flags, let maxId):
if boxed {
buffer.appendInt32(1897752877)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .recentStory(let flags, let maxId):
return ("recentStory", [("flags", flags as Any), ("maxId", maxId as Any)])
}
}
public static func parse_recentStory(_ reader: BufferReader) -> RecentStory? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
if _c1 && _c2 {
return Api.RecentStory.recentStory(flags: _1!, maxId: _2)
}
else {
return nil
}
}
}
}
public extension Api {
enum ReplyMarkup: TypeConstructorDescription {
case replyInlineMarkup(rows: [Api.KeyboardButtonRow])

View File

@ -452,14 +452,14 @@ public extension Api {
}
public extension Api {
enum User: TypeConstructorDescription {
case user(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?, botActiveUsers: Int32?, botVerificationIcon: Int64?, sendPaidMessagesStars: Int64?)
case user(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?, usernames: [Api.Username]?, storiesMaxId: Api.RecentStory?, color: Api.PeerColor?, profileColor: Api.PeerColor?, botActiveUsers: Int32?, botVerificationIcon: Int64?, sendPaidMessagesStars: Int64?)
case userEmpty(id: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames, let storiesMaxId, let color, let profileColor, let botActiveUsers, let botVerificationIcon, let sendPaidMessagesStars):
if boxed {
buffer.appendInt32(34280482)
buffer.appendInt32(829899656)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(flags2, buffer: buffer, boxed: false)
@ -485,7 +485,7 @@ public extension Api {
for item in usernames! {
item.serialize(buffer, true)
}}
if Int(flags2) & Int(1 << 5) != 0 {serializeInt32(storiesMaxId!, buffer: buffer, boxed: false)}
if Int(flags2) & Int(1 << 5) != 0 {storiesMaxId!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 8) != 0 {color!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 9) != 0 {profileColor!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 12) != 0 {serializeInt32(botActiveUsers!, buffer: buffer, boxed: false)}
@ -553,8 +553,10 @@ public extension Api {
if Int(_2!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self)
} }
var _17: Int32?
if Int(_2!) & Int(1 << 5) != 0 {_17 = reader.readInt32() }
var _17: Api.RecentStory?
if Int(_2!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_17 = Api.parse(reader, signature: signature) as? Api.RecentStory
} }
var _18: Api.PeerColor?
if Int(_2!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
_18 = Api.parse(reader, signature: signature) as? Api.PeerColor

View File

@ -11816,19 +11816,19 @@ public extension Api.functions.stories {
}
}
public extension Api.functions.stories {
static func getPeerMaxIDs(id: [Api.InputPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
static func getPeerMaxIDs(id: [Api.InputPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.RecentStory]>) {
let buffer = Buffer()
buffer.appendInt32(1398375363)
buffer.appendInt32(2018087280)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(id.count))
for item in id {
item.serialize(buffer, true)
}
return (FunctionDescription(name: "stories.getPeerMaxIDs", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in
return (FunctionDescription(name: "stories.getPeerMaxIDs", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.RecentStory]? in
let reader = BufferReader(buffer)
var result: [Int32]?
var result: [Api.RecentStory]?
if let _ = reader.readInt32() {
result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.RecentStory.self)
}
return result
})

View File

@ -534,7 +534,7 @@ public extension Api {
}
public extension Api {
indirect enum Chat: TypeConstructorDescription {
case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?, emojiStatus: Api.EmojiStatus?, level: Int32?, subscriptionUntilDate: Int32?, botVerificationIcon: Int64?, sendPaidMessagesStars: Int64?, linkedMonoforumId: Int64?)
case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?, storiesMaxId: Api.RecentStory?, color: Api.PeerColor?, profileColor: Api.PeerColor?, emojiStatus: Api.EmojiStatus?, level: Int32?, subscriptionUntilDate: Int32?, botVerificationIcon: Int64?, sendPaidMessagesStars: Int64?, linkedMonoforumId: Int64?)
case channelForbidden(flags: Int32, id: Int64, accessHash: Int64, title: String, untilDate: Int32?)
case chat(flags: Int32, id: Int64, title: String, photo: Api.ChatPhoto, participantsCount: Int32, date: Int32, version: Int32, migratedTo: Api.InputChannel?, adminRights: Api.ChatAdminRights?, defaultBannedRights: Api.ChatBannedRights?)
case chatEmpty(id: Int64)
@ -544,7 +544,7 @@ public extension Api {
switch self {
case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames, let storiesMaxId, let color, let profileColor, let emojiStatus, let level, let subscriptionUntilDate, let botVerificationIcon, let sendPaidMessagesStars, let linkedMonoforumId):
if boxed {
buffer.appendInt32(-26717355)
buffer.appendInt32(473084188)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(flags2, buffer: buffer, boxed: false)
@ -568,7 +568,7 @@ public extension Api {
for item in usernames! {
item.serialize(buffer, true)
}}
if Int(flags2) & Int(1 << 4) != 0 {serializeInt32(storiesMaxId!, buffer: buffer, boxed: false)}
if Int(flags2) & Int(1 << 4) != 0 {storiesMaxId!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 7) != 0 {color!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 8) != 0 {profileColor!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 9) != 0 {emojiStatus!.serialize(buffer, true)}
@ -675,8 +675,10 @@ public extension Api {
if Int(_2!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self)
} }
var _15: Int32?
if Int(_2!) & Int(1 << 4) != 0 {_15 = reader.readInt32() }
var _15: Api.RecentStory?
if Int(_2!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_15 = Api.parse(reader, signature: signature) as? Api.RecentStory
} }
var _16: Api.PeerColor?
if Int(_2!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() {
_16 = Api.parse(reader, signature: signature) as? Api.PeerColor

View File

@ -1431,7 +1431,7 @@ public final class AccountViewTracker {
}
startIndex += batchCount
requests.append(account.network.request(Api.functions.stories.getPeerMaxIDs(id: slice.map(\.1)))
|> `catch` { _ -> Signal<[Int32], NoError> in
|> `catch` { _ -> Signal<[Api.RecentStory], NoError> in
return .single([])
}
|> mapToSignal { result -> Signal<Never, NoError> in
@ -1439,10 +1439,13 @@ public final class AccountViewTracker {
for i in 0 ..< result.count {
if i < slice.count {
let value = result[i]
if value <= 0 {
transaction.clearStoryItemsInexactMaxId(peerId: slice[i].0)
switch value {
case let .recentStory(flags, maxId):
if let maxId {
transaction.setStoryItemsInexactMaxId(peerId: slice[i].0, id: maxId, hasLiveItems: (flags & (1 << 0)) != 0)
} else {
transaction.setStoryItemsInexactMaxId(peerId: slice[i].0, id: value)
transaction.clearStoryItemsInexactMaxId(peerId: slice[i].0)
}
}
}
}

View File

@ -3703,6 +3703,7 @@ public final class GroupCallMessagesContext {
}
public let id: Id
public let stableId: Int
public let author: EnginePeer?
public let text: String
public let entities: [MessageTextEntity]
@ -3710,8 +3711,9 @@ public final class GroupCallMessagesContext {
public let lifetime: Int32
public let paidStars: Int64?
public init(id: Id, author: EnginePeer?, text: String, entities: [MessageTextEntity], date: Int32, lifetime: Int32, paidStars: Int64?) {
public init(id: Id, stableId: Int, author: EnginePeer?, text: String, entities: [MessageTextEntity], date: Int32, lifetime: Int32, paidStars: Int64?) {
self.id = id
self.stableId = stableId
self.author = author
self.text = text
self.entities = entities
@ -3723,6 +3725,7 @@ public final class GroupCallMessagesContext {
public func withId(_ id: Id) -> Message {
return Message(
id: id,
stableId: self.stableId,
author: self.author,
text: self.text,
entities: self.entities,
@ -3733,11 +3736,14 @@ public final class GroupCallMessagesContext {
}
public static func ==(lhs: Message, rhs: Message) -> Bool {
if lhs === rhs {
return true
}
if lhs.id != rhs.id {
return false
}
if lhs === rhs {
return true
if lhs.stableId != rhs.stableId {
return false
}
if lhs.author != rhs.author {
return false
@ -3837,6 +3843,7 @@ public final class GroupCallMessagesContext {
let sendMessageDisposables = DisposableSet()
var processedIds = Set<Int64>()
var nextStableId: Int = 0
private var messageLifeTimer: SwiftSignalKit.Timer?
@ -3881,6 +3888,11 @@ public final class GroupCallMessagesContext {
if !addedMessages.isEmpty || !addedOpaqueMessages.isEmpty {
let messageLifetime = self.messageLifetime
let isLiveStream = self.isLiveStream
let allocatedStableIds = (0 ..< (addedOpaqueMessages.count + addedMessages.count)).map { _ in
let value = self.nextStableId
self.nextStableId += 1
return value
}
let _ = (self.account.postbox.transaction { transaction -> [Message] in
var messages: [Message] = []
@ -3907,8 +3919,13 @@ public final class GroupCallMessagesContext {
guard let (randomId, text, entities) = deserializeGroupCallMessage(data: decryptedMessage) else {
continue
}
if allocatedStableIds.count <= messages.count {
assertionFailure()
break
}
messages.append(Message(
id: Message.Id(space: .remote, id: randomId),
stableId: allocatedStableIds[messages.count],
author: transaction.getPeer(addedOpaqueMessage.authorId).flatMap(EnginePeer.init),
text: text,
entities: entities,
@ -3930,16 +3947,21 @@ public final class GroupCallMessagesContext {
lifetime = self.messageLifetime
}
let message = Message(
if allocatedStableIds.count <= messages.count {
assertionFailure()
break
}
messages.append(Message(
id: Message.Id(space: .remote, id: Int64(addedMessage.messageId)),
stableId: allocatedStableIds[messages.count],
author: transaction.getPeer(addedMessage.authorId).flatMap(EnginePeer.init),
text: addedMessage.text,
entities: addedMessage.entities,
date: addedMessage.timestamp,
lifetime: lifetime,
paidStars: addedMessage.paidMessageStars
)
messages.append(message)
))
}
}
return messages
@ -3973,6 +3995,12 @@ public final class GroupCallMessagesContext {
}
}
}
state.messages.sort(by: { lhs, rhs in
if lhs.date != rhs.date {
return lhs.date < rhs.date
}
return lhs.stableId < rhs.stableId
})
self.state = state
self.didInitializeTopStars = true
@ -4203,8 +4231,11 @@ public final class GroupCallMessagesContext {
}
var state = self.state
let stableId = self.nextStableId
self.nextStableId += 1
let message = Message(
id: Message.Id(space: .local, id: randomId),
stableId: stableId,
author: fromPeer.flatMap(EnginePeer.init),
text: text,
entities: entities,
@ -4403,6 +4434,7 @@ public final class GroupCallMessagesContext {
state.messages.remove(at: index)
state.messages.append(Message(
id: message.id,
stableId: message.stableId,
author: message.author,
text: message.text,
entities: message.entities,
@ -4411,8 +4443,11 @@ public final class GroupCallMessagesContext {
paidStars: totalAmount
))
} else {
let stableId = self.nextStableId
self.nextStableId += 1
state.messages.append(Message(
id: Message.Id(space: .local, id: pendingSendStarsValue.messageId),
stableId: stableId,
author: fromPeer.flatMap(EnginePeer.init),
text: "",
entities: [],
@ -4426,6 +4461,7 @@ public final class GroupCallMessagesContext {
state.pinnedMessages.remove(at: index)
state.pinnedMessages.append(Message(
id: message.id,
stableId: message.stableId,
author: message.author,
text: message.text,
entities: message.entities,
@ -4434,8 +4470,11 @@ public final class GroupCallMessagesContext {
paidStars: totalAmount
))
} else {
let stableId = self.nextStableId
self.nextStableId += 1
state.pinnedMessages.append(Message(
id: Message.Id(space: .local, id: pendingSendStarsValue.messageId),
stableId: stableId,
author: fromPeer.flatMap(EnginePeer.init),
text: "",
entities: [],

View File

@ -55,8 +55,17 @@ func updatePeers(transaction: Transaction, accountPeerId: PeerId, peers: Accumul
let isMin = (flags & (1 << 20)) != 0
let storiesUnavailable = (flags2 & (1 << 4)) != 0
if let storiesMaxId = storiesMaxId {
transaction.setStoryItemsInexactMaxId(peerId: user.peerId, id: storiesMaxId)
if let storiesMaxId {
switch storiesMaxId {
case let .recentStory(flags, maxId):
if let maxId {
transaction.setStoryItemsInexactMaxId(peerId: user.peerId, id: maxId, hasLiveItems: (flags & (1 << 0)) != 0)
} else {
if !isMin && storiesUnavailable {
transaction.clearStoryItemsInexactMaxId(peerId: user.peerId)
}
}
}
} else if !isMin && storiesUnavailable {
transaction.clearStoryItemsInexactMaxId(peerId: user.peerId)
}
@ -76,8 +85,17 @@ func updatePeers(transaction: Transaction, accountPeerId: PeerId, peers: Accumul
let isMin = (flags & (1 << 12)) != 0
let storiesUnavailable = (flags2 & (1 << 3)) != 0
if let storiesMaxId = storiesMaxId {
transaction.setStoryItemsInexactMaxId(peerId: chat.peerId, id: storiesMaxId)
if let storiesMaxId {
switch storiesMaxId {
case let .recentStory(flags, maxId):
if let maxId {
transaction.setStoryItemsInexactMaxId(peerId: chat.peerId, id: maxId, hasLiveItems: (flags & (1 << 0)) != 0)
} else {
if !isMin && storiesUnavailable {
transaction.clearStoryItemsInexactMaxId(peerId: chat.peerId)
}
}
}
} else if !isMin && storiesUnavailable {
transaction.clearStoryItemsInexactMaxId(peerId: chat.peerId)
}

View File

@ -993,7 +993,8 @@ private final class AdminUserActionsSheetComponent: Component {
maximumNumberOfLines: 0
)),
footer: nil,
items: optionsSectionItems
items: optionsSectionItems,
isModal: true
)),
environment: {},
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 100000.0)

View File

@ -424,8 +424,11 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
let (title, _) = titleAndColorForAction(action, theme: interfaceState.theme, strings: interfaceState.strings)
var isAccent = false
if case .join = self.action {
switch self.action {
case .join, .joinGroup, .applyToJoin:
isAccent = true
default:
break
}
centerAction = (title, isAccent)
}

View File

@ -1959,6 +1959,7 @@ private final class ChatSendStarsScreenComponent: Component {
space: .local,
id: 1
),
stableId: 0,
author: liveStreamMessage.myPeer,
text: liveStreamMessage.text.string,
entities: entities,
@ -1972,6 +1973,7 @@ private final class ChatSendStarsScreenComponent: Component {
space: .local,
id: 1
),
stableId: 0,
author: reactData.myPeer,
text: "",
entities: [],

View File

@ -409,22 +409,37 @@ public class GlassBackgroundView: UIView {
let innerBackgroundRadius = min(innerBackgroundFrame.width, innerBackgroundFrame.height) * 0.5
let innerBackgroundView: UIView
var innerBackgroundTransition = transition
var animateIn = false
if let current = self.innerBackgroundView {
innerBackgroundView = current
} else {
innerBackgroundView = UIView()
innerBackgroundTransition = innerBackgroundTransition.withAnimation(.none)
self.innerBackgroundView = innerBackgroundView
self.contentView.insertSubview(innerBackgroundView, at: 0)
innerBackgroundView.frame = innerBackgroundFrame
innerBackgroundView.layer.cornerRadius = innerBackgroundRadius
animateIn = true
}
innerBackgroundView.backgroundColor = innerColor
transition.setFrame(view: innerBackgroundView, frame: innerBackgroundFrame)
transition.setCornerRadius(layer: innerBackgroundView.layer, cornerRadius: innerBackgroundRadius)
innerBackgroundTransition.setFrame(view: innerBackgroundView, frame: innerBackgroundFrame)
innerBackgroundTransition.setCornerRadius(layer: innerBackgroundView.layer, cornerRadius: innerBackgroundRadius)
if animateIn {
transition.animateAlpha(view: innerBackgroundView, from: 0.0, to: 1.0)
transition.animateScale(view: innerBackgroundView, from: 0.001, to: 1.0)
}
} else if let innerBackgroundView = self.innerBackgroundView {
self.innerBackgroundView = nil
transition.setAlpha(view: innerBackgroundView, alpha: 0.0, completion: { [weak innerBackgroundView] _ in
innerBackgroundView?.removeFromSuperview()
})
transition.setScale(view: innerBackgroundView, scale: 0.001)
innerBackgroundView.removeFromSuperview()
}

View File

@ -218,6 +218,13 @@ public final class GlassControlPanelComponent: Component {
if let leftItemFrame {
centralLeftInset = leftItemFrame.maxX + minSpacing
}
if centralRightInset <= 48.0 && centralLeftInset <= 48.0 {
let maxInset = max(centralRightInset, centralLeftInset)
centralLeftInset = maxInset
centralRightInset = maxInset
}
maxCentralItemSize.width = max(1.0, availableSize.width - centralLeftInset - centralRightInset)
let centralItemSize = centralItemComponent.update(

View File

@ -331,15 +331,9 @@ public final class ListSectionComponent: Component {
case legacy
}
public enum BackgroundColor {
case base
case modal
}
public let theme: PresentationTheme
public let style: Style
public let background: Background
public let backgroundColor: BackgroundColor
public let header: AnyComponent<Empty>?
public let footer: AnyComponent<Empty>?
public let items: [AnyComponentWithIdentity<Empty>]
@ -351,7 +345,6 @@ public final class ListSectionComponent: Component {
theme: PresentationTheme,
style: Style = .legacy,
background: Background = .all,
backgroundColor: BackgroundColor = .base,
header: AnyComponent<Empty>?,
footer: AnyComponent<Empty>?,
items: [AnyComponentWithIdentity<Empty>],
@ -362,7 +355,6 @@ public final class ListSectionComponent: Component {
self.theme = theme
self.style = style
self.background = background
self.backgroundColor = backgroundColor
self.header = header
self.footer = footer
self.items = items
@ -381,9 +373,6 @@ public final class ListSectionComponent: Component {
if lhs.background != rhs.background {
return false
}
if lhs.backgroundColor != rhs.backgroundColor {
return false
}
if lhs.header != rhs.header {
return false
}

View File

@ -798,7 +798,7 @@ final class StoryContentLiveChatComponent: Component {
if let messagesState = self.messagesState {
for message in messagesState.messages.reversed() {
let messageId = message.id
listItems.append(AnyComponentWithIdentity(id: message.id, component: AnyComponent(StoryLiveChatMessageComponent(
listItems.append(AnyComponentWithIdentity(id: message.stableId, component: AnyComponent(StoryLiveChatMessageComponent(
context: component.context,
strings: component.strings,
theme: component.theme,