Merge commit 'e6ba681c030590e5fa095f9828610889abf08ef3'

This commit is contained in:
Isaac
2023-12-20 14:06:25 +04:00
99 changed files with 2342 additions and 1244 deletions

View File

@@ -7,7 +7,7 @@ import TelegramApi
extension WallpaperSettings {
init(apiWallpaperSettings: Api.WallPaperSettings) {
switch apiWallpaperSettings {
case let .wallPaperSettings(flags, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, intensity, rotation, _):
case let .wallPaperSettings(flags, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, intensity, rotation, emoticon):
var colors: [UInt32] = []
if let backgroundColor = backgroundColor {
colors.append(UInt32(bitPattern: backgroundColor))
@@ -21,7 +21,7 @@ extension WallpaperSettings {
if let fourthBackgroundColor = fourthBackgroundColor {
colors.append(UInt32(bitPattern: fourthBackgroundColor))
}
self = WallpaperSettings(blur: (flags & 1 << 1) != 0, motion: (flags & 1 << 2) != 0, colors: colors, intensity: intensity, rotation: rotation)
self = WallpaperSettings(blur: (flags & 1 << 1) != 0, motion: (flags & 1 << 2) != 0, colors: colors, intensity: intensity, rotation: rotation, emoticon: emoticon)
}
}
}
@@ -42,6 +42,9 @@ func apiWallpaperSettings(_ wallpaperSettings: WallpaperSettings) -> Api.WallPap
if let _ = wallpaperSettings.intensity {
flags |= (1 << 3)
}
if let _ = wallpaperSettings.emoticon {
flags |= (1 << 7)
}
var secondBackgroundColor: Int32?
if wallpaperSettings.colors.count >= 2 {
flags |= (1 << 4)
@@ -57,7 +60,7 @@ func apiWallpaperSettings(_ wallpaperSettings: WallpaperSettings) -> Api.WallPap
flags |= (1 << 6)
fourthBackgroundColor = Int32(bitPattern: wallpaperSettings.colors[3])
}
return .wallPaperSettings(flags: flags, backgroundColor: backgroundColor, secondBackgroundColor: secondBackgroundColor, thirdBackgroundColor: thirdBackgroundColor, fourthBackgroundColor: fourthBackgroundColor, intensity: wallpaperSettings.intensity, rotation: wallpaperSettings.rotation ?? 0, emoticon: nil)
return .wallPaperSettings(flags: flags, backgroundColor: backgroundColor, secondBackgroundColor: secondBackgroundColor, thirdBackgroundColor: thirdBackgroundColor, fourthBackgroundColor: fourthBackgroundColor, intensity: wallpaperSettings.intensity, rotation: wallpaperSettings.rotation ?? 0, emoticon: wallpaperSettings.emoticon)
}
extension TelegramWallpaper {
@@ -77,7 +80,11 @@ extension TelegramWallpaper {
self = .color(0xffffff)
}
case let .wallPaperNoFile(id, _, settings):
if let settings = settings, case let .wallPaperSettings(_, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, _, rotation, _) = settings {
if let settings = settings, case let .wallPaperSettings(_, backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor, _, rotation, emoticon) = settings {
if id == 0, let emoticon = emoticon {
self = .emoticon(emoticon)
return
}
let colors: [UInt32] = ([backgroundColor, secondBackgroundColor, thirdBackgroundColor, fourthBackgroundColor] as [Int32?]).compactMap({ color -> UInt32? in
return color.flatMap(UInt32.init(bitPattern:))
})
@@ -105,6 +112,8 @@ extension TelegramWallpaper {
return (.inputWallPaperNoFile(id: 0), apiWallpaperSettings(WallpaperSettings(colors: [color])))
case let .gradient(gradient):
return (.inputWallPaperNoFile(id: gradient.id ?? 0), apiWallpaperSettings(WallpaperSettings(colors: gradient.colors, rotation: gradient.settings.rotation)))
case let .emoticon(emoticon):
return (.inputWallPaperNoFile(id: 0), apiWallpaperSettings(WallpaperSettings(emoticon: emoticon)))
default:
return nil
}

View File

@@ -12,6 +12,7 @@ public enum ServerProvidedSuggestion: String {
case upgradePremium = "PREMIUM_UPGRADE"
case annualPremium = "PREMIUM_ANNUAL"
case restorePremium = "PREMIUM_RESTORE"
case xmasPremiumGift = "PREMIUM_CHRISTMAS"
}
private var dismissedSuggestionsPromise = ValuePromise<[AccountRecordId: Set<ServerProvidedSuggestion>]>([:])

View File

@@ -6,13 +6,15 @@ public struct WallpaperSettings: Codable, Equatable {
public var colors: [UInt32]
public var intensity: Int32?
public var rotation: Int32?
public var emoticon: String?
public init(blur: Bool = false, motion: Bool = false, colors: [UInt32] = [], intensity: Int32? = nil, rotation: Int32? = nil) {
public init(blur: Bool = false, motion: Bool = false, colors: [UInt32] = [], intensity: Int32? = nil, rotation: Int32? = nil, emoticon: String? = nil) {
self.blur = blur
self.motion = motion
self.colors = colors
self.intensity = intensity
self.rotation = rotation
self.emoticon = emoticon
}
public init(from decoder: Decoder) throws {
@@ -32,6 +34,7 @@ public struct WallpaperSettings: Codable, Equatable {
self.intensity = try container.decodeIfPresent(Int32.self, forKey: "i")
self.rotation = try container.decodeIfPresent(Int32.self, forKey: "r")
self.emoticon = try container.decodeIfPresent(String.self, forKey: "e")
}
public func encode(to encoder: Encoder) throws {
@@ -42,6 +45,7 @@ public struct WallpaperSettings: Codable, Equatable {
try container.encode(self.colors.map(Int32.init(bitPattern:)), forKey: "colors")
try container.encodeIfPresent(self.intensity, forKey: "i")
try container.encodeIfPresent(self.rotation, forKey: "r")
try container.encodeIfPresent(self.emoticon, forKey: "e")
}
public static func ==(lhs: WallpaperSettings, rhs: WallpaperSettings) -> Bool {
@@ -60,6 +64,9 @@ public struct WallpaperSettings: Codable, Equatable {
if lhs.rotation != rhs.rotation {
return false
}
if lhs.emoticon != rhs.emoticon {
return false
}
return true
}
}
@@ -73,7 +80,7 @@ public struct TelegramWallpaperNativeCodable: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
switch try container.decode(Int32.self, forKey: "v") {
case 0:
let settings = try container.decode(WallpaperSettings.self, forKey: "settings")
@@ -106,9 +113,9 @@ public struct TelegramWallpaperNativeCodable: Codable {
}
case 4:
let settings = try container.decode(WallpaperSettings.self, forKey: "settings")
var colors: [UInt32] = []
if let topColor = (try container.decodeIfPresent(Int32.self, forKey: "c1")).flatMap(UInt32.init(bitPattern:)) {
colors.append(topColor)
if let bottomColor = (try container.decodeIfPresent(Int32.self, forKey: "c2")).flatMap(UInt32.init(bitPattern:)) {
@@ -117,12 +124,14 @@ public struct TelegramWallpaperNativeCodable: Codable {
} else {
colors = (try container.decode([Int32].self, forKey: "colors")).map(UInt32.init(bitPattern:))
}
self.value = .gradient(TelegramWallpaper.Gradient(
id: try container.decodeIfPresent(Int64.self, forKey: "id"),
colors: colors,
settings: settings
))
case 5:
self.value = .emoticon(try container.decode(String.self, forKey: "e"))
default:
assertionFailure()
self.value = .color(0xffffff)
@@ -131,41 +140,48 @@ public struct TelegramWallpaperNativeCodable: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
switch self.value {
case let .builtin(settings):
try container.encode(0 as Int32, forKey: "v")
try container.encode(settings, forKey: "settings")
case let .color(color):
try container.encode(1 as Int32, forKey: "v")
try container.encode(Int32(bitPattern: color), forKey: "c")
case let .gradient(gradient):
try container.encode(4 as Int32, forKey: "v")
try container.encodeIfPresent(gradient.id, forKey: "id")
try container.encode(gradient.colors.map(Int32.init(bitPattern:)), forKey: "colors")
try container.encode(gradient.settings, forKey: "settings")
case let .image(representations, settings):
try container.encode(2 as Int32, forKey: "v")
try container.encode(representations.map { item in
return PostboxEncoder().encodeObjectToRawData(item)
}, forKey: "i")
try container.encode(settings, forKey: "settings")
case let .file(file):
try container.encode(3 as Int32, forKey: "v")
try container.encode(file.id, forKey: "id")
try container.encode(file.accessHash, forKey: "accessHash")
try container.encode((file.isCreator ? 1 : 0) as Int32, forKey: "isCreator")
try container.encode((file.isDefault ? 1 : 0) as Int32, forKey: "isDefault")
try container.encode((file.isPattern ? 1 : 0) as Int32, forKey: "isPattern")
try container.encode((file.isDark ? 1 : 0) as Int32, forKey: "isDark")
try container.encode(file.slug, forKey: "slug")
try container.encode(PostboxEncoder().encodeObjectToRawData(file.file), forKey: "file")
try container.encode(file.settings, forKey: "settings")
case let .builtin(settings):
try container.encode(0 as Int32, forKey: "v")
try container.encode(settings, forKey: "settings")
case let .color(color):
try container.encode(1 as Int32, forKey: "v")
try container.encode(Int32(bitPattern: color), forKey: "c")
case let .gradient(gradient):
try container.encode(4 as Int32, forKey: "v")
try container.encodeIfPresent(gradient.id, forKey: "id")
try container.encode(gradient.colors.map(Int32.init(bitPattern:)), forKey: "colors")
try container.encode(gradient.settings, forKey: "settings")
case let .image(representations, settings):
try container.encode(2 as Int32, forKey: "v")
try container.encode(representations.map { item in
return PostboxEncoder().encodeObjectToRawData(item)
}, forKey: "i")
try container.encode(settings, forKey: "settings")
case let .file(file):
try container.encode(3 as Int32, forKey: "v")
try container.encode(file.id, forKey: "id")
try container.encode(file.accessHash, forKey: "accessHash")
try container.encode((file.isCreator ? 1 : 0) as Int32, forKey: "isCreator")
try container.encode((file.isDefault ? 1 : 0) as Int32, forKey: "isDefault")
try container.encode((file.isPattern ? 1 : 0) as Int32, forKey: "isPattern")
try container.encode((file.isDark ? 1 : 0) as Int32, forKey: "isDark")
try container.encode(file.slug, forKey: "slug")
try container.encode(PostboxEncoder().encodeObjectToRawData(file.file), forKey: "file")
try container.encode(file.settings, forKey: "settings")
case let .emoticon(emoticon):
try container.encode(5 as Int32, forKey: "v")
try container.encode(emoticon, forKey: "e")
}
}
}
public enum TelegramWallpaper: Equatable {
public static func emoticonWallpaper(emoticon: String) -> TelegramWallpaper {
return .file(File(id: -1, accessHash: -1, isCreator: false, isDefault: false, isPattern: false, isDark: false, slug: "", file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: EmptyMediaResource(), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(emoticon: emoticon)))
}
public struct Gradient: Equatable {
public var id: Int64?
public var colors: [UInt32]
@@ -221,6 +237,7 @@ public enum TelegramWallpaper: Equatable {
case gradient(Gradient)
case image([TelegramMediaImageRepresentation], WallpaperSettings)
case file(File)
case emoticon(String)
public var hasWallpaper: Bool {
switch self {
@@ -263,6 +280,12 @@ public enum TelegramWallpaper: Equatable {
} else {
return false
}
case let .emoticon(emoticon):
if case .emoticon(emoticon) = rhs {
return true
} else {
return false
}
}
}
@@ -298,6 +321,12 @@ public enum TelegramWallpaper: Equatable {
} else {
return false
}
case let .emoticon(emoticon):
if case .emoticon(emoticon) = wallpaper {
return true
} else {
return false
}
}
}
@@ -328,6 +357,8 @@ public enum TelegramWallpaper: Equatable {
case var .file(file):
file.settings = settings
return .file(file)
case .emoticon:
return self
}
}
}

View File

@@ -427,7 +427,7 @@ public final class EngineStoryViewListContext {
let sortMode = self.sortMode
let searchQuery = self.searchQuery
let currentOffset = state.nextOffset
let limit = state.items.isEmpty ? 50 : 100
let limit = 50
let signal: Signal<InternalState, NoError>
@@ -662,6 +662,9 @@ public final class EngineStoryViewListContext {
}
var flags: Int32 = 0
if let _ = currentOffset {
flags |= (1 << 1)
}
if case .repostsFirst = sortMode {
flags |= (1 << 2)
}
@@ -887,4 +890,3 @@ public final class EngineStoryViewListContext {
}
}
}

View File

@@ -14,7 +14,11 @@ public enum GetMessagesStrategy {
case cloud(skipLocal: Bool)
}
func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Postbox, network: Network, accountPeerId: PeerId, strategy: GetMessagesStrategy = .cloud(skipLocal: false)) -> Signal<GetMessagesResult, NoError> {
public enum GetMessagesError {
case privateChannel
}
func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Postbox, network: Network, accountPeerId: PeerId, strategy: GetMessagesStrategy = .cloud(skipLocal: false)) -> Signal<GetMessagesResult, GetMessagesError> {
let postboxSignal = postbox.transaction { transaction -> ([Message], Set<MessageId>, SimpleDictionary<PeerId, Peer>) in
var ids = messageIds
@@ -50,8 +54,9 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
if case .cloud = strategy {
return postboxSignal
|> castError(GetMessagesError.self)
|> mapToSignal { (existMessages, missingMessageIds, supportPeers) in
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>] = []
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), GetMessagesError>] = []
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingMessageIds) {
if let peer = supportPeers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
@@ -75,14 +80,20 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
case .messagesNotModified:
return (peer, [], [], [])
}
} |> `catch` { _ in
return Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>.single((peer, [], [], []))
} |> `catch` { error in
if error.errorDescription == "CHANNEL_PRIVATE" {
return .fail(.privateChannel)
} else {
return Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), GetMessagesError>.single((peer, [], [], []))
}
})
}
}
}
return .single(.progress) |> then(combineLatest(signals) |> mapToSignal { results -> Signal<GetMessagesResult, NoError> in
return .single(.progress)
|> castError(GetMessagesError.self)
|> then(combineLatest(signals) |> mapToSignal { results -> Signal<GetMessagesResult, GetMessagesError> in
return postbox.transaction { transaction -> GetMessagesResult in
for (peer, messages, chats, users) in results {
if !messages.isEmpty {
@@ -108,10 +119,12 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
return .result(existMessages + loadedMessages)
}
|> castError(GetMessagesError.self)
})
}
} else {
return postboxSignal
|> castError(GetMessagesError.self)
|> map {
return .result($0.0)
}

View File

@@ -162,7 +162,7 @@ public extension TelegramEngine {
return _internal_markAllChatsAsRead(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager)
}
public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], strategy: GetMessagesStrategy = .cloud(skipLocal: false)) -> Signal<GetMessagesResult, NoError> {
public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], strategy: GetMessagesStrategy = .cloud(skipLocal: false)) -> Signal<GetMessagesResult, GetMessagesError> {
return _internal_getMessagesLoadIfNecessary(messageIds, postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, strategy: strategy)
}

View File

@@ -134,6 +134,8 @@ func _internal_setChatWallpaper(postbox: Postbox, network: Network, stateManager
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedUserData {
return current.withUpdatedWallpaper(wallpaper)
} else if let current = current as? CachedChannelData {
return current.withUpdatedWallpaper(wallpaper)
} else {
return current
}