mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
c546792fcd
@ -1244,6 +1244,25 @@ public struct StickersSearchConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension PeerNameColors.Colors {
|
||||||
|
init?(colors: EngineAvailableColorOptions.MultiColorPack) {
|
||||||
|
if colors.colors.isEmpty {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
self.main = UIColor(rgb: colors.colors[0])
|
||||||
|
if colors.colors.count > 1 {
|
||||||
|
self.secondary = UIColor(rgb: colors.colors[1])
|
||||||
|
} else {
|
||||||
|
self.secondary = nil
|
||||||
|
}
|
||||||
|
if colors.colors.count > 2 {
|
||||||
|
self.tertiary = UIColor(rgb: colors.colors[2])
|
||||||
|
} else {
|
||||||
|
self.tertiary = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class PeerNameColors: Equatable {
|
public class PeerNameColors: Equatable {
|
||||||
public struct Colors: Equatable {
|
public struct Colors: Equatable {
|
||||||
public let main: UIColor
|
public let main: UIColor
|
||||||
@ -1347,8 +1366,69 @@ public class PeerNameColors: Equatable {
|
|||||||
self.profileDisplayOrder = profileDisplayOrder
|
self.profileDisplayOrder = profileDisplayOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func with(appConfiguration: AppConfiguration) -> PeerNameColors {
|
public static func with(availableReplyColors: EngineAvailableColorOptions, availableProfileColors: EngineAvailableColorOptions) -> PeerNameColors {
|
||||||
if let data = appConfiguration.data {
|
var colors: [Int32: Colors] = [:]
|
||||||
|
var darkColors: [Int32: Colors] = [:]
|
||||||
|
var displayOrder: [Int32] = []
|
||||||
|
var profileColors: [Int32: Colors] = [:]
|
||||||
|
var profileDarkColors: [Int32: Colors] = [:]
|
||||||
|
var profileDisplayOrder: [Int32] = []
|
||||||
|
|
||||||
|
if !availableReplyColors.options.isEmpty {
|
||||||
|
for option in availableReplyColors.options {
|
||||||
|
if let parsedLight = PeerNameColors.Colors(colors: option.value.light.background) {
|
||||||
|
colors[option.key] = parsedLight
|
||||||
|
}
|
||||||
|
if let parsedDark = (option.value.dark?.background).flatMap(PeerNameColors.Colors.init(colors:)) {
|
||||||
|
darkColors[option.key] = parsedDark
|
||||||
|
}
|
||||||
|
|
||||||
|
//displayOrder.append(contentsOf: availableReplyColors.options.filter({ !$0.value.isHidden }).map(\.key))
|
||||||
|
for option in availableReplyColors.options {
|
||||||
|
if !displayOrder.contains(option.key) {
|
||||||
|
displayOrder.append(option.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*for i in (0 ..< 7).reversed() {
|
||||||
|
if !displayOrder.contains(Int32(i)) {
|
||||||
|
displayOrder.insert(Int32(i), at: 0)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let defaultValue = PeerNameColors.defaultValue
|
||||||
|
colors = defaultValue.colors
|
||||||
|
darkColors = defaultValue.darkColors
|
||||||
|
displayOrder = defaultValue.displayOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
if !availableProfileColors.options.isEmpty {
|
||||||
|
for option in availableProfileColors.options {
|
||||||
|
if let parsedLight = PeerNameColors.Colors(colors: option.value.light.background) {
|
||||||
|
profileColors[option.key] = parsedLight
|
||||||
|
}
|
||||||
|
if let parsedDark = (option.value.dark?.background).flatMap(PeerNameColors.Colors.init(colors:)) {
|
||||||
|
profileDarkColors[option.key] = parsedDark
|
||||||
|
}
|
||||||
|
for option in availableProfileColors.options {
|
||||||
|
if !profileDisplayOrder.contains(option.key) {
|
||||||
|
profileDisplayOrder.append(option.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//profileDisplayOrder = availableProfileColors.options.filter({ !$0.value.isHidden }).map(\.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PeerNameColors(
|
||||||
|
colors: colors,
|
||||||
|
darkColors: darkColors,
|
||||||
|
displayOrder: displayOrder,
|
||||||
|
profileColors: profileColors,
|
||||||
|
profileDarkColors: profileDarkColors,
|
||||||
|
profileDisplayOrder: profileDisplayOrder
|
||||||
|
)
|
||||||
|
|
||||||
|
/*if let data = appConfiguration.data {
|
||||||
var colors = PeerNameColors.defaultSingleColors
|
var colors = PeerNameColors.defaultSingleColors
|
||||||
var darkColors: [Int32: Colors] = [:]
|
var darkColors: [Int32: Colors] = [:]
|
||||||
|
|
||||||
@ -1463,7 +1543,7 @@ public class PeerNameColors: Equatable {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return .defaultValue
|
return .defaultValue
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func == (lhs: PeerNameColors, rhs: PeerNameColors) -> Bool {
|
public static func == (lhs: PeerNameColors, rhs: PeerNameColors) -> Bool {
|
||||||
|
@ -1244,7 +1244,7 @@ public extension Api {
|
|||||||
return parser(reader)
|
return parser(reader)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
|
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,7 @@ final class AccountTaskManager {
|
|||||||
tasks.add(managedRecentReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
tasks.add(managedRecentReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||||
tasks.add(_internal_loadedStickerPack(postbox: self.stateManager.postbox, network: self.stateManager.network, reference: .iconStatusEmoji, forceActualized: true).start())
|
tasks.add(_internal_loadedStickerPack(postbox: self.stateManager.postbox, network: self.stateManager.network, reference: .iconStatusEmoji, forceActualized: true).start())
|
||||||
tasks.add(_internal_loadedStickerPack(postbox: self.stateManager.postbox, network: self.stateManager.network, reference: .iconTopicEmoji, forceActualized: true).start())
|
tasks.add(_internal_loadedStickerPack(postbox: self.stateManager.postbox, network: self.stateManager.network, reference: .iconTopicEmoji, forceActualized: true).start())
|
||||||
|
tasks.add(managedPeerColorUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||||
|
|
||||||
self.managedTopReactionsDisposable.set(managedTopReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
self.managedTopReactionsDisposable.set(managedTopReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||||
|
|
||||||
|
@ -27,3 +27,5 @@ func managedGenericEmojiEffects(postbox: Postbox, network: Network) -> Signal<Vo
|
|||||||
}
|
}
|
||||||
return (poll |> then(.complete() |> suspendAwareDelay(2.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
return (poll |> then(.complete() |> suspendAwareDelay(2.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,421 @@
|
|||||||
|
import Foundation
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramApi
|
||||||
|
import MtProtoKit
|
||||||
|
|
||||||
|
public final class EngineAvailableColorOptions: Codable, Equatable {
|
||||||
|
public final class MultiColorPack: Codable, Equatable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case colors = "c"
|
||||||
|
}
|
||||||
|
|
||||||
|
public let colors: [UInt32]
|
||||||
|
|
||||||
|
public init(colors: [UInt32]) {
|
||||||
|
self.colors = colors
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.colors = try container.decode([Int32].self, forKey: .colors).map(UInt32.init(bitPattern:))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.colors.map(Int32.init(bitPattern:)), forKey: .colors)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: MultiColorPack, rhs: MultiColorPack) -> Bool {
|
||||||
|
if lhs === rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs.colors != rhs.colors {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class ColorOption: Codable, Equatable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case palette = "p"
|
||||||
|
case background = "b"
|
||||||
|
case stories = "s"
|
||||||
|
}
|
||||||
|
|
||||||
|
public let palette: MultiColorPack
|
||||||
|
public let background: MultiColorPack
|
||||||
|
public let stories: MultiColorPack?
|
||||||
|
|
||||||
|
public init(palette: MultiColorPack, background: MultiColorPack, stories: MultiColorPack?) {
|
||||||
|
self.palette = palette
|
||||||
|
self.background = background
|
||||||
|
self.stories = stories
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.palette = try container.decode(MultiColorPack.self, forKey: .palette)
|
||||||
|
self.background = try container.decode(MultiColorPack.self, forKey: .background)
|
||||||
|
self.stories = try container.decodeIfPresent(MultiColorPack.self, forKey: .stories)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.palette, forKey: .palette)
|
||||||
|
try container.encode(self.background, forKey: .background)
|
||||||
|
try container.encodeIfPresent(self.stories, forKey: .stories)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: ColorOption, rhs: ColorOption) -> Bool {
|
||||||
|
if lhs === rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs.palette != rhs.palette {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.background != rhs.background {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.stories != rhs.stories {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class ColorOptionPack: Codable, Equatable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case light = "l"
|
||||||
|
case dark = "d"
|
||||||
|
case isHidden = "h"
|
||||||
|
}
|
||||||
|
|
||||||
|
public let light: ColorOption
|
||||||
|
public let dark: ColorOption?
|
||||||
|
public let isHidden: Bool
|
||||||
|
|
||||||
|
public init(light: ColorOption, dark: ColorOption?, isHidden: Bool) {
|
||||||
|
self.light = light
|
||||||
|
self.dark = dark
|
||||||
|
self.isHidden = isHidden
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.light = try container.decode(ColorOption.self, forKey: .light)
|
||||||
|
self.dark = try container.decodeIfPresent(ColorOption.self, forKey: .dark)
|
||||||
|
self.isHidden = try container.decode(Bool.self, forKey: .isHidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.light, forKey: .light)
|
||||||
|
try container.encodeIfPresent(self.dark, forKey: .dark)
|
||||||
|
try container.encodeIfPresent(self.isHidden, forKey: .isHidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: ColorOptionPack, rhs: ColorOptionPack) -> Bool {
|
||||||
|
if lhs === rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs.light != rhs.light {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.dark != rhs.dark {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.isHidden != rhs.isHidden {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case hash = "h"
|
||||||
|
case options = "o"
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Option: Codable, Equatable {
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case key = "k"
|
||||||
|
case value = "v"
|
||||||
|
}
|
||||||
|
|
||||||
|
public let key: Int32
|
||||||
|
public let value: ColorOptionPack
|
||||||
|
|
||||||
|
public init(key: Int32, value: ColorOptionPack) {
|
||||||
|
self.key = key
|
||||||
|
self.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.key = try container.decode(Int32.self, forKey: .key)
|
||||||
|
self.value = try container.decode(ColorOptionPack.self, forKey: .value)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.key, forKey: .key)
|
||||||
|
try container.encode(self.value, forKey: .value)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: Option, rhs: Option) -> Bool {
|
||||||
|
if lhs === rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs.key != rhs.key {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.value != rhs.value {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public let hash: Int32
|
||||||
|
public let options: [Option]
|
||||||
|
|
||||||
|
public init(hash: Int32, options: [Option]) {
|
||||||
|
self.hash = hash
|
||||||
|
self.options = options
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
self.hash = try container.decode(Int32.self, forKey: .hash)
|
||||||
|
self.options = try container.decode([Option].self, forKey: .options)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.hash, forKey: .hash)
|
||||||
|
try container.encode(self.options, forKey: .options)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: EngineAvailableColorOptions, rhs: EngineAvailableColorOptions) -> Bool {
|
||||||
|
if lhs === rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs.hash != rhs.hash {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.options != rhs.options {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension EngineAvailableColorOptions.ColorOption {
|
||||||
|
convenience init?(apiColors: [Int32]) {
|
||||||
|
let palette: EngineAvailableColorOptions.MultiColorPack
|
||||||
|
let background: EngineAvailableColorOptions.MultiColorPack
|
||||||
|
let stories: EngineAvailableColorOptions.MultiColorPack?
|
||||||
|
|
||||||
|
if apiColors.count == 1 {
|
||||||
|
palette = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[0])
|
||||||
|
])
|
||||||
|
background = palette
|
||||||
|
stories = nil
|
||||||
|
} else if apiColors.count == 2 {
|
||||||
|
palette = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[0]),
|
||||||
|
UInt32(bitPattern: apiColors[1])
|
||||||
|
])
|
||||||
|
background = palette
|
||||||
|
stories = nil
|
||||||
|
} else if apiColors.count == 3 {
|
||||||
|
palette = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[0]),
|
||||||
|
UInt32(bitPattern: apiColors[1]),
|
||||||
|
UInt32(bitPattern: apiColors[2])
|
||||||
|
])
|
||||||
|
background = palette
|
||||||
|
stories = nil
|
||||||
|
} else if apiColors.count == 4 {
|
||||||
|
palette = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[0])
|
||||||
|
])
|
||||||
|
background = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[1])
|
||||||
|
])
|
||||||
|
stories = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[2]),
|
||||||
|
UInt32(bitPattern: apiColors[3])
|
||||||
|
])
|
||||||
|
} else if apiColors.count == 6 {
|
||||||
|
palette = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[0]),
|
||||||
|
UInt32(bitPattern: apiColors[1])
|
||||||
|
])
|
||||||
|
background = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[2]),
|
||||||
|
UInt32(bitPattern: apiColors[3])
|
||||||
|
])
|
||||||
|
stories = EngineAvailableColorOptions.MultiColorPack(colors: [
|
||||||
|
UInt32(bitPattern: apiColors[4]),
|
||||||
|
UInt32(bitPattern: apiColors[5])
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(palette: palette, background: background, stories: stories)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension EngineAvailableColorOptions {
|
||||||
|
convenience init(hash: Int32, apiColors: [Api.help.PeerColorOption]) {
|
||||||
|
var mappedOptions: [Option] = []
|
||||||
|
for apiColor in apiColors {
|
||||||
|
switch apiColor {
|
||||||
|
case let .peerColorOption(flags, colorId, colors, darkColors):
|
||||||
|
let isHidden = (flags & (1 << 0)) != 0
|
||||||
|
let mappedColors = colors.flatMap(EngineAvailableColorOptions.ColorOption.init(apiColors:))
|
||||||
|
let mappedDarkColors = darkColors.flatMap(EngineAvailableColorOptions.ColorOption.init(apiColors:))
|
||||||
|
|
||||||
|
if let mappedColors = mappedColors {
|
||||||
|
mappedOptions.append(Option(key: colorId, value: ColorOptionPack(light: mappedColors, dark: mappedDarkColors, isHidden: isHidden)))
|
||||||
|
} else if colorId >= 0 && colorId <= 6 {
|
||||||
|
let staticMap: [UInt32] = [
|
||||||
|
0xcc5049,
|
||||||
|
0xd67722,
|
||||||
|
0x955cdb,
|
||||||
|
0x40a920,
|
||||||
|
0x309eba,
|
||||||
|
0x368ad1,
|
||||||
|
0xc7508b
|
||||||
|
]
|
||||||
|
let colorPack = MultiColorPack(colors: [staticMap[Int(colorId)]])
|
||||||
|
let defaultColors = EngineAvailableColorOptions.ColorOption(palette: colorPack, background: colorPack, stories: nil)
|
||||||
|
mappedOptions.append(Option(key: colorId, value: ColorOptionPack(light: defaultColors, dark: nil, isHidden: isHidden)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(hash: hash, options: mappedOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func managedPeerColorUpdates(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
|
||||||
|
let poll = combineLatest(
|
||||||
|
_internal_fetchPeerColors(postbox: postbox, network: network, scope: .replies),
|
||||||
|
_internal_fetchPeerColors(postbox: postbox, network: network, scope: .profile)
|
||||||
|
)
|
||||||
|
|> mapToSignal { _ -> Signal<Never, NoError> in
|
||||||
|
}
|
||||||
|
return (poll |> then(.complete() |> suspendAwareDelay(2.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PeerColorsScope {
|
||||||
|
case replies
|
||||||
|
case profile
|
||||||
|
}
|
||||||
|
|
||||||
|
private func _internal_fetchPeerColors(postbox: Postbox, network: Network, scope: PeerColorsScope) -> Signal<Never, NoError> {
|
||||||
|
return postbox.transaction { transaction -> Int32 in
|
||||||
|
#if DEBUG
|
||||||
|
if "".isEmpty {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return _internal_cachedAvailableColorOptions(transaction: transaction, scope: scope).hash
|
||||||
|
}
|
||||||
|
|> mapToSignal { hash -> Signal<Never, NoError> in
|
||||||
|
let signal: Signal<Api.help.PeerColors, MTRpcError>
|
||||||
|
switch scope {
|
||||||
|
case .replies:
|
||||||
|
signal = network.request(Api.functions.help.getPeerColors(hash: hash))
|
||||||
|
case .profile:
|
||||||
|
signal = network.request(Api.functions.help.getPeerProfileColors(hash: hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
return signal
|
||||||
|
|> `catch` { _ -> Signal<Api.help.PeerColors, NoError> in
|
||||||
|
return .single(.peerColorsNotModified)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
|
switch result {
|
||||||
|
case .peerColorsNotModified:
|
||||||
|
return .complete()
|
||||||
|
case let .peerColors(hash, colors):
|
||||||
|
return postbox.transaction { transaction -> Void in
|
||||||
|
let value = EngineAvailableColorOptions(hash: hash, apiColors: colors)
|
||||||
|
_internal_setCachedAvailableColorOptions(transaction: transaction, scope: scope, value: value)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_cachedAvailableColorOptions(postbox: Postbox, scope: PeerColorsScope) -> Signal<EngineAvailableColorOptions, NoError> {
|
||||||
|
return postbox.transaction { transaction -> EngineAvailableColorOptions in
|
||||||
|
return _internal_cachedAvailableColorOptions(transaction: transaction, scope: scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_observeAvailableColorOptions(postbox: Postbox, scope: PeerColorsScope) -> Signal<EngineAvailableColorOptions, NoError> {
|
||||||
|
let key = ValueBoxKey(length: 8)
|
||||||
|
switch scope {
|
||||||
|
case .replies:
|
||||||
|
key.setInt64(0, value: 0)
|
||||||
|
case .profile:
|
||||||
|
key.setInt64(0, value: 1)
|
||||||
|
}
|
||||||
|
let viewKey: PostboxViewKey = .cachedItem(ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.peerColorOptions, key: key))
|
||||||
|
return postbox.combinedView(keys: [viewKey])
|
||||||
|
|> map { views -> EngineAvailableColorOptions in
|
||||||
|
guard let view = views.views[viewKey] as? CachedItemView, let value = view.value?.get(EngineAvailableColorOptions.self) else {
|
||||||
|
return EngineAvailableColorOptions(hash: 0, options: [])
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_cachedAvailableColorOptions(transaction: Transaction, scope: PeerColorsScope) -> EngineAvailableColorOptions {
|
||||||
|
let key = ValueBoxKey(length: 8)
|
||||||
|
switch scope {
|
||||||
|
case .replies:
|
||||||
|
key.setInt64(0, value: 0)
|
||||||
|
case .profile:
|
||||||
|
key.setInt64(0, value: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.peerColorOptions, key: key))?.get(EngineAvailableColorOptions.self)
|
||||||
|
if let cached = cached {
|
||||||
|
return cached
|
||||||
|
} else {
|
||||||
|
return EngineAvailableColorOptions(hash: 0, options: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_setCachedAvailableColorOptions(transaction: Transaction, scope: PeerColorsScope, value: EngineAvailableColorOptions) {
|
||||||
|
let key = ValueBoxKey(length: 8)
|
||||||
|
switch scope {
|
||||||
|
case .replies:
|
||||||
|
key.setInt64(0, value: 0)
|
||||||
|
case .profile:
|
||||||
|
key.setInt64(0, value: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let entry = CodableEntry(value) {
|
||||||
|
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.peerColorOptions, key: key), entry: entry)
|
||||||
|
}
|
||||||
|
}
|
@ -114,6 +114,7 @@ public struct Namespaces {
|
|||||||
public static let cachedChannelBoosts: Int8 = 31
|
public static let cachedChannelBoosts: Int8 = 31
|
||||||
public static let displayedMessageNotifications: Int8 = 32
|
public static let displayedMessageNotifications: Int8 = 32
|
||||||
public static let recommendedChannels: Int8 = 33
|
public static let recommendedChannels: Int8 = 33
|
||||||
|
public static let peerColorOptions: Int8 = 34
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UnorderedItemList {
|
public struct UnorderedItemList {
|
||||||
|
@ -35,6 +35,10 @@ public extension TelegramEngine {
|
|||||||
return _internal_updateAbout(account: self.account, about: about)
|
return _internal_updateAbout(account: self.account, about: about)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func observeAvailableColorOptions(scope: PeerColorsScope) -> Signal<EngineAvailableColorOptions, NoError> {
|
||||||
|
return _internal_observeAvailableColorOptions(postbox: self.account.postbox, scope: scope)
|
||||||
|
}
|
||||||
|
|
||||||
public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
|
public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
|
||||||
return _internal_updateNameColorAndEmoji(account: self.account, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId)
|
return _internal_updateNameColorAndEmoji(account: self.account, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId)
|
||||||
}
|
}
|
||||||
|
@ -523,5 +523,37 @@ public extension TelegramEngine.EngineData.Item {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct AvailableColorOptions: TelegramEngineDataItem, PostboxViewDataItem {
|
||||||
|
public typealias Result = EngineAvailableColorOptions
|
||||||
|
|
||||||
|
public let scope: PeerColorsScope
|
||||||
|
|
||||||
|
public init(scope: PeerColorsScope) {
|
||||||
|
self.scope = scope
|
||||||
|
}
|
||||||
|
|
||||||
|
var key: PostboxViewKey {
|
||||||
|
let key = ValueBoxKey(length: 8)
|
||||||
|
switch scope {
|
||||||
|
case .replies:
|
||||||
|
key.setInt64(0, value: 0)
|
||||||
|
case .profile:
|
||||||
|
key.setInt64(0, value: 1)
|
||||||
|
}
|
||||||
|
let viewKey: PostboxViewKey = .cachedItem(ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.peerColorOptions, key: key))
|
||||||
|
return viewKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func extract(view: PostboxView) -> Result {
|
||||||
|
guard let view = view as? CachedItemView else {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
guard let value = view.value?.get(EngineAvailableColorOptions.self) else {
|
||||||
|
return EngineAvailableColorOptions(hash: 0, options: [])
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ public final class AccountContextImpl: AccountContext {
|
|||||||
|
|
||||||
public let imageCache: AnyObject?
|
public let imageCache: AnyObject?
|
||||||
|
|
||||||
public init(sharedContext: SharedAccountContextImpl, account: Account, limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, appConfiguration: AppConfiguration, temp: Bool = false)
|
public init(sharedContext: SharedAccountContextImpl, account: Account, limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, appConfiguration: AppConfiguration, availableReplyColors: EngineAvailableColorOptions, availableProfileColors: EngineAvailableColorOptions, temp: Bool = false)
|
||||||
{
|
{
|
||||||
self.sharedContextImpl = sharedContext
|
self.sharedContextImpl = sharedContext
|
||||||
self.account = account
|
self.account = account
|
||||||
@ -263,7 +263,7 @@ public final class AccountContextImpl: AccountContext {
|
|||||||
self.imageCache = DirectMediaImageCache(account: account)
|
self.imageCache = DirectMediaImageCache(account: account)
|
||||||
|
|
||||||
self.userLimits = EngineConfiguration.UserLimits(UserLimitsConfiguration.defaultValue)
|
self.userLimits = EngineConfiguration.UserLimits(UserLimitsConfiguration.defaultValue)
|
||||||
self.peerNameColors = PeerNameColors.defaultValue
|
self.peerNameColors = PeerNameColors.with(availableReplyColors: availableReplyColors, availableProfileColors: availableProfileColors)
|
||||||
self.audioTranscriptionTrial = AudioTranscription.TrialState.defaultValue
|
self.audioTranscriptionTrial = AudioTranscription.TrialState.defaultValue
|
||||||
self.isPremium = false
|
self.isPremium = false
|
||||||
|
|
||||||
@ -411,12 +411,15 @@ public final class AccountContextImpl: AccountContext {
|
|||||||
self.userLimits = userLimits
|
self.userLimits = userLimits
|
||||||
})
|
})
|
||||||
|
|
||||||
self.peerNameColorsConfigurationDisposable = (self._appConfiguration.get()
|
self.peerNameColorsConfigurationDisposable = (combineLatest(
|
||||||
|> deliverOnMainQueue).startStrict(next: { [weak self] appConfiguration in
|
self.engine.accountData.observeAvailableColorOptions(scope: .replies),
|
||||||
|
self.engine.accountData.observeAvailableColorOptions(scope: .profile)
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).startStrict(next: { [weak self] availableReplyColors, availableProfileColors in
|
||||||
guard let self = self else {
|
guard let self = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.peerNameColors = PeerNameColors.with(appConfiguration: appConfiguration)
|
self.peerNameColors = PeerNameColors.with(availableReplyColors: availableReplyColors, availableProfileColors: availableProfileColors)
|
||||||
})
|
})
|
||||||
|
|
||||||
self.audioTranscriptionTrialDisposable = (self.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: account.peerId))
|
self.audioTranscriptionTrialDisposable = (self.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: account.peerId))
|
||||||
|
@ -59,6 +59,8 @@ private final class AccountUserInterfaceInUseContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typealias AccountInitialData = (limitsConfiguration: LimitsConfiguration?, contentSettings: ContentSettings?, appConfiguration: AppConfiguration?, availableReplyColors: EngineAvailableColorOptions, availableProfileColors: EngineAvailableColorOptions)
|
||||||
|
|
||||||
private struct AccountAttributes: Equatable {
|
private struct AccountAttributes: Equatable {
|
||||||
let sortIndex: Int32
|
let sortIndex: Int32
|
||||||
let isTestingEnvironment: Bool
|
let isTestingEnvironment: Bool
|
||||||
@ -67,12 +69,12 @@ private struct AccountAttributes: Equatable {
|
|||||||
|
|
||||||
private enum AddedAccountResult {
|
private enum AddedAccountResult {
|
||||||
case upgrading(Float)
|
case upgrading(Float)
|
||||||
case ready(AccountRecordId, Account?, Int32, LimitsConfiguration?, ContentSettings?, AppConfiguration?)
|
case ready(AccountRecordId, Account?, Int32, AccountInitialData)
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum AddedAccountsResult {
|
private enum AddedAccountsResult {
|
||||||
case upgrading(Float)
|
case upgrading(Float)
|
||||||
case ready([(AccountRecordId, Account?, Int32, LimitsConfiguration?, ContentSettings?, AppConfiguration?)])
|
case ready([(AccountRecordId, Account?, Int32, AccountInitialData)])
|
||||||
}
|
}
|
||||||
|
|
||||||
private var testHasInstance = false
|
private var testHasInstance = false
|
||||||
@ -524,15 +526,17 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return TelegramEngine(account: account).data.get(
|
return TelegramEngine(account: account).data.get(
|
||||||
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
TelegramEngine.EngineData.Item.Configuration.Limits(),
|
||||||
TelegramEngine.EngineData.Item.Configuration.ContentSettings(),
|
TelegramEngine.EngineData.Item.Configuration.ContentSettings(),
|
||||||
TelegramEngine.EngineData.Item.Configuration.App()
|
TelegramEngine.EngineData.Item.Configuration.App(),
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.AvailableColorOptions(scope: .replies),
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.AvailableColorOptions(scope: .profile)
|
||||||
)
|
)
|
||||||
|> map { limitsConfiguration, contentSettings, appConfiguration -> AddedAccountResult in
|
|> map { limitsConfiguration, contentSettings, appConfiguration, availableReplyColors, availableProfileColors -> AddedAccountResult in
|
||||||
return .ready(id, account, attributes.sortIndex, limitsConfiguration._asLimits(), contentSettings, appConfiguration)
|
return .ready(id, account, attributes.sortIndex, (limitsConfiguration._asLimits(), contentSettings, appConfiguration, availableReplyColors, availableProfileColors))
|
||||||
}
|
}
|
||||||
case let .upgrading(progress):
|
case let .upgrading(progress):
|
||||||
return .single(.upgrading(progress))
|
return .single(.upgrading(progress))
|
||||||
default:
|
default:
|
||||||
return .single(.ready(id, nil, attributes.sortIndex, nil, nil, nil))
|
return .single(.ready(id, nil, attributes.sortIndex, (nil, nil, nil, EngineAvailableColorOptions(hash: 0, options: []), EngineAvailableColorOptions(hash: 0, options: []))))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -553,13 +557,13 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
|
|
||||||
let mappedAddedAccounts = combineLatest(queue: .mainQueue(), addedSignals)
|
let mappedAddedAccounts = combineLatest(queue: .mainQueue(), addedSignals)
|
||||||
|> map { results -> AddedAccountsResult in
|
|> map { results -> AddedAccountsResult in
|
||||||
var readyAccounts: [(AccountRecordId, Account?, Int32, LimitsConfiguration?, ContentSettings?, AppConfiguration?)] = []
|
var readyAccounts: [(AccountRecordId, Account?, Int32, AccountInitialData)] = []
|
||||||
var totalProgress: Float = 0.0
|
var totalProgress: Float = 0.0
|
||||||
var hasItemsWithProgress = false
|
var hasItemsWithProgress = false
|
||||||
for result in results {
|
for result in results {
|
||||||
switch result {
|
switch result {
|
||||||
case let .ready(id, account, sortIndex, limitsConfiguration, contentSettings, appConfiguration):
|
case let .ready(id, account, sortIndex, initialData):
|
||||||
readyAccounts.append((id, account, sortIndex, limitsConfiguration, contentSettings, appConfiguration))
|
readyAccounts.append((id, account, sortIndex, initialData))
|
||||||
totalProgress += 1.0
|
totalProgress += 1.0
|
||||||
case let .upgrading(progress):
|
case let .upgrading(progress):
|
||||||
hasItemsWithProgress = true
|
hasItemsWithProgress = true
|
||||||
@ -577,7 +581,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
|> deliverOnMainQueue).start(next: { mappedAddedAccounts, authAccount in
|
|> deliverOnMainQueue).start(next: { mappedAddedAccounts, authAccount in
|
||||||
print("SharedAccountContextImpl: accounts processed in \(CFAbsoluteTimeGetCurrent() - startTime)")
|
print("SharedAccountContextImpl: accounts processed in \(CFAbsoluteTimeGetCurrent() - startTime)")
|
||||||
|
|
||||||
var addedAccounts: [(AccountRecordId, Account?, Int32, LimitsConfiguration?, ContentSettings?, AppConfiguration?)] = []
|
var addedAccounts: [(AccountRecordId, Account?, Int32, AccountInitialData)] = []
|
||||||
switch mappedAddedAccounts {
|
switch mappedAddedAccounts {
|
||||||
case let .upgrading(progress):
|
case let .upgrading(progress):
|
||||||
self.displayUpgradeProgress(progress)
|
self.displayUpgradeProgress(progress)
|
||||||
@ -616,7 +620,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
let context = AccountContextImpl(sharedContext: self, account: account, limitsConfiguration: accountRecord.3 ?? .defaultValue, contentSettings: accountRecord.4 ?? .default, appConfiguration: accountRecord.5 ?? .defaultValue)
|
let context = AccountContextImpl(sharedContext: self, account: account, limitsConfiguration: accountRecord.3.limitsConfiguration ?? .defaultValue, contentSettings: accountRecord.3.contentSettings ?? .default, appConfiguration: accountRecord.3.appConfiguration ?? .defaultValue, availableReplyColors: accountRecord.3.availableReplyColors, availableProfileColors: accountRecord.3.availableProfileColors)
|
||||||
|
|
||||||
self.activeAccountsValue!.accounts.append((account.id, context, accountRecord.2))
|
self.activeAccountsValue!.accounts.append((account.id, context, accountRecord.2))
|
||||||
|
|
||||||
@ -1221,7 +1225,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func makeTempAccountContext(account: Account) -> AccountContext {
|
public func makeTempAccountContext(account: Account) -> AccountContext {
|
||||||
return AccountContextImpl(sharedContext: self, account: account, limitsConfiguration: .defaultValue, contentSettings: .default, appConfiguration: .defaultValue, temp: true)
|
return AccountContextImpl(sharedContext: self, account: account, limitsConfiguration: .defaultValue, contentSettings: .default, appConfiguration: .defaultValue, availableReplyColors: EngineAvailableColorOptions(hash: 0, options: []), availableProfileColors: EngineAvailableColorOptions(hash: 0, options: []), temp: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func openChatMessage(_ params: OpenChatMessageParams) -> Bool {
|
public func openChatMessage(_ params: OpenChatMessageParams) -> Bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user