Autoremove improvements

This commit is contained in:
Ali 2022-11-27 15:27:05 +04:00
parent dc4a04daa7
commit 60ebcc847a
11 changed files with 327 additions and 189 deletions

View File

@ -835,6 +835,7 @@ public final class AvatarBadgeView: UIImageView {
private var originalContent: OriginalContent? private var originalContent: OriginalContent?
private var parameters: Parameters? private var parameters: Parameters?
private var hasContent: Bool = false
override public init(frame: CGRect) { override public init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
@ -845,7 +846,7 @@ public final class AvatarBadgeView: UIImageView {
} }
func update(content: OriginalContent) { func update(content: OriginalContent) {
if self.originalContent != content { if self.originalContent != content || !self.hasContent {
self.originalContent = content self.originalContent = content
self.update() self.update()
} }
@ -853,7 +854,7 @@ public final class AvatarBadgeView: UIImageView {
public func update(size: CGSize, text: String) { public func update(size: CGSize, text: String) {
let parameters = Parameters(size: size, text: text) let parameters = Parameters(size: size, text: text)
if self.parameters != parameters { if self.parameters != parameters || !self.hasContent {
self.parameters = parameters self.parameters = parameters
self.update() self.update()
} }
@ -864,6 +865,8 @@ public final class AvatarBadgeView: UIImageView {
return return
} }
self.hasContent = true
let blurredWidth = 16 let blurredWidth = 16
let blurredHeight = 16 let blurredHeight = 16
guard let blurredContext = DrawingContext(size: CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)), scale: 1.0, opaque: true) else { guard let blurredContext = DrawingContext(size: CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)), scale: 1.0, opaque: true) else {
@ -876,8 +879,11 @@ public final class AvatarBadgeView: UIImageView {
c.setFillColor(color.cgColor) c.setFillColor(color.cgColor)
c.fill(CGRect(origin: CGPoint(), size: blurredSize)) c.fill(CGRect(origin: CGPoint(), size: blurredSize))
case let .image(image): case let .image(image):
c.setFillColor(UIColor.black.cgColor)
c.fill(CGRect(origin: CGPoint(), size: blurredSize))
c.scaleBy(x: blurredSize.width / parameters.size.width, y: blurredSize.height / parameters.size.height) c.scaleBy(x: blurredSize.width / parameters.size.width, y: blurredSize.height / parameters.size.height)
let offsetFactor: CGFloat = 1.0 - 0.7071 let offsetFactor: CGFloat = 1.0 - 0.6
let imageFrame = CGRect(origin: CGPoint(x: parameters.size.width - image.size.width + offsetFactor * parameters.size.width, y: parameters.size.height - image.size.height + offsetFactor * parameters.size.height), size: image.size) let imageFrame = CGRect(origin: CGPoint(x: parameters.size.width - image.size.width + offsetFactor * parameters.size.width, y: parameters.size.height - image.size.height + offsetFactor * parameters.size.height), size: image.size)
UIGraphicsPushContext(c) UIGraphicsPushContext(c)
@ -900,7 +906,7 @@ public final class AvatarBadgeView: UIImageView {
UInt32(15), UInt32(15),
UInt32(15), UInt32(15),
nil, nil,
vImage_Flags(kvImageEdgeExtend) vImage_Flags(kvImageTruncateKernel | kvImageDoNotTile)
) )
let divisor: Int32 = 0x1000 let divisor: Int32 = 0x1000
@ -909,7 +915,7 @@ public final class AvatarBadgeView: UIImageView {
let gwgt: CGFloat = 0.6094 let gwgt: CGFloat = 0.6094
let bwgt: CGFloat = 0.0820 let bwgt: CGFloat = 0.0820
let adjustSaturation: CGFloat = 1.9 let adjustSaturation: CGFloat = 1.7
let a = (1.0 - adjustSaturation) * rwgt + adjustSaturation let a = (1.0 - adjustSaturation) * rwgt + adjustSaturation
let b = (1.0 - adjustSaturation) * rwgt let b = (1.0 - adjustSaturation) * rwgt
@ -928,7 +934,30 @@ public final class AvatarBadgeView: UIImageView {
0, 0, 0, 1 0, 0, 0, 1
] ]
var matrix: [Int16] = satMatrix.map { value in let brightness: CGFloat = 0.94
let brighnessMatrix: [CGFloat] = [
brightness, 0, 0, 0,
0, brightness, 0, 0,
0, 0, brightness, 0,
0, 0, 0, 1
]
func matrixMul(a: [CGFloat], b: [CGFloat], result: inout [CGFloat]) {
for i in 0 ..< 4 {
for j in 0 ..< 4 {
var sum: CGFloat = 0.0
for k in 0 ..< 4 {
sum += a[i + k * 4] * b[k + j * 4]
}
result[i + j * 4] = sum
}
}
}
var resultMatrix = Array<CGFloat>(repeating: 0.0, count: 4 * 4)
matrixMul(a: satMatrix, b: brighnessMatrix, result: &resultMatrix)
var matrix: [Int16] = resultMatrix.map { value in
return Int16(value * CGFloat(divisor)) return Int16(value * CGFloat(divisor))
} }
@ -947,14 +976,14 @@ public final class AvatarBadgeView: UIImageView {
context.setFillColor(UIColor.black.cgColor) context.setFillColor(UIColor.black.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
context.setBlendMode(.sourceIn)
blurredImage.draw(in: CGRect(origin: CGPoint(), size: size), blendMode: .sourceIn, alpha: 1.0) blurredImage.draw(in: CGRect(origin: CGPoint(), size: size), blendMode: .sourceIn, alpha: 1.0)
context.setBlendMode(.normal) context.setBlendMode(.normal)
context.setFillColor(UIColor(white: 0.0, alpha: 0.05).cgColor) /*context.setFillColor(UIColor(white: 1.0, alpha: 0.08).cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
context.setFillColor(UIColor(white: 0.0, alpha: 0.05).cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))*/
let string = NSAttributedString(string: parameters.text, font: Font.bold(floor(parameters.size.height * 0.48)), textColor: .white) let string = NSAttributedString(string: parameters.text, font: Font.bold(floor(parameters.size.height * 0.48)), textColor: .white)
let stringBounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil) let stringBounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
@ -970,7 +999,6 @@ public final class AvatarBadgeView: UIImageView {
context.addArc(center: CGPoint(x: size.width * 0.5, y: size.height * 0.5), radius: lineRadius, startAngle: CGFloat.pi * 0.5, endAngle: -CGFloat.pi * 0.5, clockwise: false) context.addArc(center: CGPoint(x: size.width * 0.5, y: size.height * 0.5), radius: lineRadius, startAngle: CGFloat.pi * 0.5, endAngle: -CGFloat.pi * 0.5, clockwise: false)
context.strokePath() context.strokePath()
let sectionAngle: CGFloat = CGFloat.pi / 11.0 let sectionAngle: CGFloat = CGFloat.pi / 11.0
for i in 0 ..< 10 { for i in 0 ..< 10 {
@ -978,15 +1006,13 @@ public final class AvatarBadgeView: UIImageView {
continue continue
} }
let startAngle = CGFloat.pi * 0.5 - CGFloat(i) * sectionAngle - sectionAngle * 0.1 let startAngle = CGFloat.pi * 0.5 - CGFloat(i) * sectionAngle - sectionAngle * 0.15
let endAngle = startAngle - sectionAngle * 0.8 let endAngle = startAngle - sectionAngle * 0.75
context.addArc(center: CGPoint(x: size.width * 0.5, y: size.height * 0.5), radius: lineRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true) context.addArc(center: CGPoint(x: size.width * 0.5, y: size.height * 0.5), radius: lineRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
context.strokePath() context.strokePath()
} }
//context.strokeEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: 2.0 + lineWidth * 0.5, dy: 2.0 + lineWidth * 0.5))
UIGraphicsPopContext() UIGraphicsPopContext()
}) })
} }

View File

@ -2665,19 +2665,19 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
avatarBadgeBackground.bounds = CGRect(origin: CGPoint(), size: avatarBadgeBackgroundFrame.size) avatarBadgeBackground.bounds = CGRect(origin: CGPoint(), size: avatarBadgeBackgroundFrame.size)
if animateIn { if animateIn {
ContainedViewLayoutTransition.immediate.updateSublayerTransformScale(node: avatarBadgeNode, scale: 0.001) ContainedViewLayoutTransition.immediate.updateSublayerTransformScale(node: avatarBadgeNode, scale: 0.00001)
ContainedViewLayoutTransition.immediate.updateTransformScale(layer: avatarBadgeBackground.layer, scale: 0.001) ContainedViewLayoutTransition.immediate.updateTransformScale(layer: avatarBadgeBackground.layer, scale: 0.00001)
} }
transition.updateSublayerTransformScale(node: avatarBadgeNode, scale: max(0.001, inlineNavigationLocation.progress)) transition.updateSublayerTransformScale(node: avatarBadgeNode, scale: max(0.00001, inlineNavigationLocation.progress))
transition.updateTransformScale(layer: avatarBadgeBackground.layer, scale: max(0.001, inlineNavigationLocation.progress)) transition.updateTransformScale(layer: avatarBadgeBackground.layer, scale: max(0.00001, inlineNavigationLocation.progress))
} else if let avatarBadgeNode = strongSelf.avatarBadgeNode { } else if let avatarBadgeNode = strongSelf.avatarBadgeNode {
strongSelf.avatarBadgeNode = nil strongSelf.avatarBadgeNode = nil
transition.updateSublayerTransformScale(node: avatarBadgeNode, scale: 0.001, completion: { [weak avatarBadgeNode] _ in transition.updateSublayerTransformScale(node: avatarBadgeNode, scale: 0.00001, completion: { [weak avatarBadgeNode] _ in
avatarBadgeNode?.removeFromSupernode() avatarBadgeNode?.removeFromSupernode()
}) })
if let avatarBadgeBackground = strongSelf.avatarBadgeBackground { if let avatarBadgeBackground = strongSelf.avatarBadgeBackground {
strongSelf.avatarBadgeBackground = nil strongSelf.avatarBadgeBackground = nil
transition.updateTransformScale(layer: avatarBadgeBackground.layer, scale: 0.001, completion: { [weak avatarBadgeBackground] _ in transition.updateTransformScale(layer: avatarBadgeBackground.layer, scale: 0.00001, completion: { [weak avatarBadgeBackground] _ in
avatarBadgeBackground?.removeFromSupernode() avatarBadgeBackground?.removeFromSupernode()
}) })
} }
@ -2747,7 +2747,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let onlineInlineNavigationFraction: CGFloat = item.interaction.inlineNavigationLocation?.progress ?? 0.0 let onlineInlineNavigationFraction: CGFloat = item.interaction.inlineNavigationLocation?.progress ?? 0.0
transition.updateAlpha(node: strongSelf.onlineNode, alpha: 1.0 - onlineInlineNavigationFraction) transition.updateAlpha(node: strongSelf.onlineNode, alpha: 1.0 - onlineInlineNavigationFraction)
transition.updateSublayerTransformScale(node: strongSelf.onlineNode, scale: (1.0 - onlineInlineNavigationFraction) * 1.0 + onlineInlineNavigationFraction * 0.001) transition.updateSublayerTransformScale(node: strongSelf.onlineNode, scale: (1.0 - onlineInlineNavigationFraction) * 1.0 + onlineInlineNavigationFraction * 0.00001)
let onlineIcon: UIImage? let onlineIcon: UIImage?
if strongSelf.reallyHighlighted { if strongSelf.reallyHighlighted {
@ -2775,7 +2775,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
avatarTimerTransition = .immediate avatarTimerTransition = .immediate
avatarTimerBadge = AvatarBadgeView(frame: CGRect()) avatarTimerBadge = AvatarBadgeView(frame: CGRect())
strongSelf.avatarTimerBadge = avatarTimerBadge strongSelf.avatarTimerBadge = avatarTimerBadge
strongSelf.avatarNode.badgeView = avatarTimerBadge
strongSelf.contextContainer.view.addSubview(avatarTimerBadge) strongSelf.contextContainer.view.addSubview(avatarTimerBadge)
} }
let avatarBadgeSize = CGSize(width: avatarTimerBadgeDiameter, height: avatarTimerBadgeDiameter) let avatarBadgeSize = CGSize(width: avatarTimerBadgeDiameter, height: avatarTimerBadgeDiameter)
@ -2783,7 +2782,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let avatarBadgeFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - avatarBadgeSize.width, y: avatarFrame.maxY - avatarBadgeSize.height), size: avatarBadgeSize) let avatarBadgeFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - avatarBadgeSize.width, y: avatarFrame.maxY - avatarBadgeSize.height), size: avatarBadgeSize)
avatarTimerTransition.updatePosition(layer: avatarTimerBadge.layer, position: avatarBadgeFrame.center) avatarTimerTransition.updatePosition(layer: avatarTimerBadge.layer, position: avatarBadgeFrame.center)
avatarTimerTransition.updateBounds(layer: avatarTimerBadge.layer, bounds: CGRect(origin: CGPoint(), size: avatarBadgeFrame.size)) avatarTimerTransition.updateBounds(layer: avatarTimerBadge.layer, bounds: CGRect(origin: CGPoint(), size: avatarBadgeFrame.size))
avatarTimerTransition.updateTransformScale(layer: avatarTimerBadge.layer, scale: autoremoveTimeoutFraction * 1.0 + (1.0 - autoremoveTimeoutFraction) * 0.001) avatarTimerTransition.updateTransformScale(layer: avatarTimerBadge.layer, scale: autoremoveTimeoutFraction * 1.0 + (1.0 - autoremoveTimeoutFraction) * 0.00001)
strongSelf.avatarNode.badgeView = avatarTimerBadge
} else if let avatarTimerBadge = strongSelf.avatarTimerBadge { } else if let avatarTimerBadge = strongSelf.avatarTimerBadge {
strongSelf.avatarTimerBadge = nil strongSelf.avatarTimerBadge = nil
strongSelf.avatarNode.badgeView = nil strongSelf.avatarNode.badgeView = nil

View File

@ -187,7 +187,8 @@ private func globalAutoremoveScreenEntries(presentationData: PresentationData, s
if effectiveCurrentValue == 0 { if effectiveCurrentValue == 0 {
entries.append(.info("If enabled, all new messages in chats you start will be automatically deleted for everyone at some point after they have been sent. This will not affect your existing chats.")) entries.append(.info("If enabled, all new messages in chats you start will be automatically deleted for everyone at some point after they have been sent. This will not affect your existing chats."))
} else { } else {
entries.append(.info("All new messages in chats you started will be automatically deleted for everyone 3 weeks after they have been sent. You can also [apply this setting for your existing chats]()."))
entries.append(.info("All new messages in chats you started will be automatically deleted for everyone \(timeIntervalString(strings: presentationData.strings, value: effectiveCurrentValue)) after they have been sent. You can also [apply this setting for your existing chats]()."))
} }
return entries return entries

View File

@ -207,3 +207,23 @@ extension SelectivePrivacySettings {
self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor) self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor)
} }
} }
public struct GlobalMessageAutoremoveTimeoutSettings: Equatable, Codable {
public static var `default` = GlobalMessageAutoremoveTimeoutSettings(
messageAutoremoveTimeout: nil
)
public var messageAutoremoveTimeout: Int32?
public init(messageAutoremoveTimeout: Int32?) {
self.messageAutoremoveTimeout = messageAutoremoveTimeout
}
}
func updateGlobalMessageAutoremoveTimeoutSettings(transaction: Transaction, _ f: (GlobalMessageAutoremoveTimeoutSettings) -> GlobalMessageAutoremoveTimeoutSettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.globalMessageAutoremoveTimeoutSettings, { current in
let previous = current?.get(GlobalMessageAutoremoveTimeoutSettings.self) ?? GlobalMessageAutoremoveTimeoutSettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}

View File

@ -46,8 +46,31 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
let messageId: Int32? let messageId: Int32?
var apiMessage: Api.Message? var apiMessage: Api.Message?
var correspondingMessageId: Int32?
for update in result.allUpdates {
switch update {
case let .updateMessageID(id, randomId):
for attribute in message.attributes {
if let attribute = attribute as? OutgoingMessageInfoAttribute {
if attribute.uniqueId == randomId {
correspondingMessageId = id
break
}
}
}
default:
break
}
}
for resultMessage in result.messages { for resultMessage in result.messages {
if let id = resultMessage.id() { if let id = resultMessage.id() {
if let correspondingMessageId = correspondingMessageId {
if id.id != correspondingMessageId {
continue
}
}
if id.peerId == message.id.peerId { if id.peerId == message.id.peerId {
apiMessage = resultMessage apiMessage = resultMessage
break break

View File

@ -7,9 +7,11 @@ import MtProtoKit
func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountManagerTypes>, postbox: Postbox, network: Network) -> Signal<Void, NoError> { func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountManagerTypes>, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = Signal<Void, NoError> { subscriber in let poll = Signal<Void, NoError> { subscriber in
return (network.request(Api.functions.help.getConfig()) return (combineLatest(
|> retryRequest network.request(Api.functions.help.getConfig()) |> retryRequest,
|> mapToSignal { result -> Signal<Void, NoError> in network.request(Api.functions.messages.getDefaultHistoryTTL()) |> retryRequest
)
|> mapToSignal { result, defaultHistoryTtl -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Signal<Void, NoError> in return postbox.transaction { transaction -> Signal<Void, NoError> in
switch result { switch result {
case let .config(flags, _, _, _, _, dcOptions, _, chatSizeMax, megagroupSizeMax, forwardedCountMax, _, _, _, _, _, _, _, _, savedGifsLimit, editTimeLimit, revokeTimeLimit, revokePmTimeLimit, _, stickersRecentLimit, stickersFavedLimit, _, _, pinnedDialogsCountMax, pinnedInfolderCountMax, _, _, _, _, _, autoupdateUrlPrefix, gifSearchUsername, venueSearchUsername, imgSearchUsername, _, captionLengthMax, _, webfileDcId, suggestedLangCode, langPackVersion, baseLangPackVersion, defaultReaction): case let .config(flags, _, _, _, _, dcOptions, _, chatSizeMax, megagroupSizeMax, forwardedCountMax, _, _, _, _, _, _, _, _, savedGifsLimit, editTimeLimit, revokeTimeLimit, revokePmTimeLimit, _, stickersRecentLimit, stickersFavedLimit, _, _, pinnedDialogsCountMax, pinnedInfolderCountMax, _, _, _, _, _, autoupdateUrlPrefix, gifSearchUsername, venueSearchUsername, imgSearchUsername, _, captionLengthMax, _, webfileDcId, suggestedLangCode, langPackVersion, baseLangPackVersion, defaultReaction):
@ -71,6 +73,21 @@ func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountM
}) })
} }
let messageAutoremoveSeconds: Int32?
switch defaultHistoryTtl {
case let .defaultHistoryTTL(period):
if period != 0 {
messageAutoremoveSeconds = period
} else {
messageAutoremoveSeconds = nil
}
}
updateGlobalMessageAutoremoveTimeoutSettings(transaction: transaction, { settings in
var settings = settings
settings.messageAutoremoveTimeout = messageAutoremoveSeconds
return settings
})
return accountManager.transaction { transaction -> Signal<Void, NoError> in return accountManager.transaction { transaction -> Signal<Void, NoError> in
let (primary, secondary) = getLocalization(transaction) let (primary, secondary) = getLocalization(transaction)
var invalidateLocalization = false var invalidateLocalization = false

View File

@ -246,6 +246,7 @@ private enum PreferencesKeyValues: Int32 {
case secretChatSettings = 23 case secretChatSettings = 23
case reactionSettings = 24 case reactionSettings = 24
case premiumPromo = 26 case premiumPromo = 26
case globalMessageAutoremoveTimeoutSettings = 27
} }
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey { public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
@ -374,6 +375,12 @@ public struct PreferencesKeys {
key.setInt32(0, value: PreferencesKeyValues.premiumPromo.rawValue) key.setInt32(0, value: PreferencesKeyValues.premiumPromo.rawValue)
return key return key
}() }()
public static let globalMessageAutoremoveTimeoutSettings: ValueBoxKey = {
let key = ValueBoxKey(length: 4)
key.setInt32(0, value: PreferencesKeyValues.globalMessageAutoremoveTimeoutSettings.rawValue)
return key
}()
} }
private enum SharedDataKeyValues: Int32 { private enum SharedDataKeyValues: Int32 {

View File

@ -379,5 +379,26 @@ public extension TelegramEngine.EngineData.Item {
return premiumPromoConfiguration return premiumPromoConfiguration
} }
} }
public struct GlobalAutoremoveTimeout: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = Int32?
public init() {
}
var key: PostboxViewKey {
return .preferences(keys: Set([PreferencesKeys.globalMessageAutoremoveTimeoutSettings]))
}
func extract(view: PostboxView) -> Result {
guard let view = view as? PreferencesView else {
preconditionFailure()
}
guard let settings = view.values[PreferencesKeys.globalMessageAutoremoveTimeoutSettings]?.get(GlobalMessageAutoremoveTimeoutSettings.self) else {
return GlobalMessageAutoremoveTimeoutSettings.default.messageAutoremoveTimeout
}
return settings.messageAutoremoveTimeout
}
}
} }
} }

View File

@ -155,6 +155,12 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
return updated return updated
}) })
updateGlobalMessageAutoremoveTimeoutSettings(transaction: transaction, { settings in
var settings = settings
settings.messageAutoremoveTimeout = messageAutoremoveSeconds
return settings
})
return AccountPrivacySettings(presence: SelectivePrivacySettings(apiRules: lastSeenRules, peers: peerMap), groupInvitations: SelectivePrivacySettings(apiRules: groupRules, peers: peerMap), voiceCalls: SelectivePrivacySettings(apiRules: voiceRules, peers: peerMap), voiceCallsP2P: SelectivePrivacySettings(apiRules: voiceP2PRules, peers: peerMap), profilePhoto: SelectivePrivacySettings(apiRules: profilePhotoRules, peers: peerMap), forwards: SelectivePrivacySettings(apiRules: forwardRules, peers: peerMap), phoneNumber: SelectivePrivacySettings(apiRules: phoneNumberRules, peers: peerMap), phoneDiscoveryEnabled: phoneDiscoveryValue, voiceMessages: SelectivePrivacySettings(apiRules: voiceMessagesRules, peers: peerMap), automaticallyArchiveAndMuteNonContacts: automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: accountTimeoutSeconds, messageAutoremoveTimeout: messageAutoremoveSeconds) return AccountPrivacySettings(presence: SelectivePrivacySettings(apiRules: lastSeenRules, peers: peerMap), groupInvitations: SelectivePrivacySettings(apiRules: groupRules, peers: peerMap), voiceCalls: SelectivePrivacySettings(apiRules: voiceRules, peers: peerMap), voiceCallsP2P: SelectivePrivacySettings(apiRules: voiceP2PRules, peers: peerMap), profilePhoto: SelectivePrivacySettings(apiRules: profilePhotoRules, peers: peerMap), forwards: SelectivePrivacySettings(apiRules: forwardRules, peers: peerMap), phoneNumber: SelectivePrivacySettings(apiRules: phoneNumberRules, peers: peerMap), phoneDiscoveryEnabled: phoneDiscoveryValue, voiceMessages: SelectivePrivacySettings(apiRules: voiceMessagesRules, peers: peerMap), automaticallyArchiveAndMuteNonContacts: automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: accountTimeoutSeconds, messageAutoremoveTimeout: messageAutoremoveSeconds)
} }
} }

View File

@ -298,10 +298,10 @@ private struct CreateGroupState: Equatable {
var nameSetFromVenue: Bool var nameSetFromVenue: Bool
var avatar: ItemListAvatarAndNameInfoItemUpdatingAvatar? var avatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?
var location: PeerGeoLocation? var location: PeerGeoLocation?
var autoremoveTimeout: Int32 var autoremoveTimeout: Int32?
} }
private func createGroupEntries(presentationData: PresentationData, state: CreateGroupState, peerIds: [PeerId], view: MultiplePeersView, venues: [TelegramMediaMap]?) -> [CreateGroupEntry] { private func createGroupEntries(presentationData: PresentationData, state: CreateGroupState, peerIds: [PeerId], view: MultiplePeersView, venues: [TelegramMediaMap]?, globalAutoremoveTimeout: Int32) -> [CreateGroupEntry] {
var entries: [CreateGroupEntry] = [] var entries: [CreateGroupEntry] = []
let groupInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: nil) let groupInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: nil)
@ -311,11 +311,12 @@ private func createGroupEntries(presentationData: PresentationData, state: Creat
entries.append(.groupInfo(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, groupInfoState, state.avatar)) entries.append(.groupInfo(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, groupInfoState, state.avatar))
//TODO:localize //TODO:localize
let autoremoveTimeout = state.autoremoveTimeout ?? globalAutoremoveTimeout
let autoRemoveText: String let autoRemoveText: String
if state.autoremoveTimeout == 0 { if autoremoveTimeout == 0 {
autoRemoveText = "Off" autoRemoveText = "Off"
} else { } else {
autoRemoveText = timeIntervalString(strings: presentationData.strings, value: state.autoremoveTimeout) autoRemoveText = timeIntervalString(strings: presentationData.strings, value: autoremoveTimeout)
} }
entries.append(.autoDelete(title: "Auto-Delete Messages", value: autoRemoveText)) entries.append(.autoDelete(title: "Auto-Delete Messages", value: autoRemoveText))
entries.append(.autoDeleteInfo("Automatically delete messages sent in this group for everyone after a period of time.")) entries.append(.autoDeleteInfo("Automatically delete messages sent in this group for everyone after a period of time."))
@ -382,7 +383,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
location = PeerGeoLocation(latitude: latitude, longitude: longitude, address: address ?? "") location = PeerGeoLocation(latitude: latitude, longitude: longitude, address: address ?? "")
} }
let initialState = CreateGroupState(creating: false, editingName: .title(title: initialTitle ?? "", type: .group), nameSetFromVenue: false, avatar: nil, location: location, autoremoveTimeout: 0) let initialState = CreateGroupState(creating: false, editingName: .title(title: initialTitle ?? "", type: .group), nameSetFromVenue: false, avatar: nil, location: location, autoremoveTimeout: nil)
let statePromise = ValuePromise(initialState, ignoreRepeated: true) let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState) let stateValue = Atomic(value: initialState)
let updateState: ((CreateGroupState) -> CreateGroupState) -> Void = { f in let updateState: ((CreateGroupState) -> CreateGroupState) -> Void = { f in
@ -434,6 +435,8 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
} }
if !creating && !title.isEmpty { if !creating && !title.isEmpty {
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalAutoremoveTimeout())
|> deliverOnMainQueue).start(next: { maybeGlobalAutoremoveTimeout in
updateState { current in updateState { current in
var current = current var current = current
current.creating = true current.creating = true
@ -441,7 +444,8 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
} }
endEditingImpl?() endEditingImpl?()
let autoremoveTimeout = stateValue.with({ $0 }).autoremoveTimeout let globalAutoremoveTimeout: Int32 = maybeGlobalAutoremoveTimeout ?? 0
let autoremoveTimeout = stateValue.with({ $0 }).autoremoveTimeout ?? globalAutoremoveTimeout
let ttlPeriod: Int32? = autoremoveTimeout == 0 ? nil : autoremoveTimeout let ttlPeriod: Int32? = autoremoveTimeout == 0 ? nil : autoremoveTimeout
let createSignal: Signal<PeerId?, CreateGroupError> let createSignal: Signal<PeerId?, CreateGroupError>
@ -565,6 +569,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
} }
})) }))
})
} }
}, changeProfilePhoto: { }, changeProfilePhoto: {
endEditingImpl?() endEditingImpl?()
@ -825,9 +830,12 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
}) })
ensureItemVisibleImpl?(.info, true) ensureItemVisibleImpl?(.info, true)
}, updateAutoDelete: { }, updateAutoDelete: {
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalAutoremoveTimeout())
|> deliverOnMainQueue).start(next: { maybeGlobalAutoremoveTimeout in
var subItems: [ContextMenuItem] = [] var subItems: [ContextMenuItem] = []
let currentValue = stateValue.with({ $0 }).autoremoveTimeout let globalAutoremoveTimeout: Int32 = maybeGlobalAutoremoveTimeout ?? 0
let currentValue: Int32 = stateValue.with({ $0 }).autoremoveTimeout ?? globalAutoremoveTimeout
let applyValue: (Int32) -> Void = { value in let applyValue: (Int32) -> Void = { value in
updateState { state in updateState { state in
@ -905,9 +913,17 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
presentInGlobalOverlay?(contextController) presentInGlobalOverlay?(contextController)
} }
}) })
})
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), context.account.postbox.multiplePeersView(peerIds), .single(nil) |> then(addressPromise.get()), .single(nil) |> then(venuesPromise.get())) let signal = combineLatest(queue: .mainQueue(),
|> map { presentationData, state, view, address, venues -> (ItemListControllerState, (ItemListNodeState, Any)) in context.sharedContext.presentationData,
statePromise.get(),
context.account.postbox.multiplePeersView(peerIds),
.single(nil) |> then(addressPromise.get()),
.single(nil) |> then(venuesPromise.get()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.GlobalAutoremoveTimeout())
)
|> map { presentationData, state, view, address, venues, globalAutoremoveTimeout -> (ItemListControllerState, (ItemListNodeState, Any)) in
let rightNavigationButton: ItemListNavigationButton let rightNavigationButton: ItemListNavigationButton
if state.creating { if state.creating {
@ -919,7 +935,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
} }
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Compose_NewGroupTitle), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Compose_NewGroupTitle), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGroupEntries(presentationData: presentationData, state: state, peerIds: peerIds, view: view, venues: venues), style: .blocks, focusItemTag: CreateGroupEntryTag.info) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGroupEntries(presentationData: presentationData, state: state, peerIds: peerIds, view: view, venues: venues, globalAutoremoveTimeout: globalAutoremoveTimeout ?? 0), style: .blocks, focusItemTag: CreateGroupEntryTag.info)
return (controllerState, (listState, arguments)) return (controllerState, (listState, arguments))
} }

View File

@ -158,7 +158,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
} }
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white)
displayUndo = false displayUndo = false
self.originalRemainingSeconds = 3.5 self.originalRemainingSeconds = 4.5
case let .succeed(text): case let .succeed(text):
self.avatarNode = nil self.avatarNode = nil
self.iconNode = nil self.iconNode = nil