mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
c73f24f5f2
commit
d6964efa67
@ -13753,3 +13753,11 @@ Sorry for the inconvenience.";
|
||||
"Gift.Withdraw.EnterPassword.Title" = "Enter Password";
|
||||
"Gift.Withdraw.EnterPassword.Text" = "Please enter your Two-Step Verification password to complete this action.";
|
||||
"Gift.Withdraw.EnterPassword.Done" = "Proceed";
|
||||
|
||||
"PeerInfo.Gifts.SortByValue" = "Sort by Value";
|
||||
"PeerInfo.Gifts.SortByDate" = "Sort by Date";
|
||||
"PeerInfo.Gifts.Unlimited" = "Unlimited";
|
||||
"PeerInfo.Gifts.Limited" = "Limited";
|
||||
"PeerInfo.Gifts.Unique" = "Unique";
|
||||
"PeerInfo.Gifts.Displayed" = "Displayed";
|
||||
"PeerInfo.Gifts.Hidden" = "Hidden";
|
||||
|
@ -389,8 +389,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1710230755] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
|
||||
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
|
||||
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
||||
dict[1946579745] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
||||
dict[-149933938] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
||||
dict[-1468646731] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
||||
dict[2006319353] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
||||
dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) }
|
||||
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
||||
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) }
|
||||
@ -401,7 +401,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
|
||||
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
||||
dict[-1979852936] = { return Api.InputMedia.parse_inputMediaStory($0) }
|
||||
dict[-264125395] = { return Api.InputMedia.parse_inputMediaUploadedDocument($0) }
|
||||
dict[58495792] = { return Api.InputMedia.parse_inputMediaUploadedDocument($0) }
|
||||
dict[505969924] = { return Api.InputMedia.parse_inputMediaUploadedPhoto($0) }
|
||||
dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) }
|
||||
dict[-1038383031] = { return Api.InputMedia.parse_inputMediaWebPage($0) }
|
||||
@ -620,7 +620,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1313731771] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
||||
dict[1882335561] = { return Api.MessageMedia.parse_messageMediaContact($0) }
|
||||
dict[1065280907] = { return Api.MessageMedia.parse_messageMediaDice($0) }
|
||||
dict[-608307692] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
|
||||
dict[1389939929] = { return Api.MessageMedia.parse_messageMediaDocument($0) }
|
||||
dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
|
||||
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
|
||||
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
||||
|
@ -432,8 +432,8 @@ public extension Api {
|
||||
indirect enum InputMedia: TypeConstructorDescription {
|
||||
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
|
||||
case inputMediaDice(emoticon: String)
|
||||
case inputMediaDocument(flags: Int32, id: Api.InputDocument, videoCover: Api.InputPhoto?, ttlSeconds: Int32?, query: String?)
|
||||
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?, videoCover: Api.InputPhoto?)
|
||||
case inputMediaDocument(flags: Int32, id: Api.InputDocument, videoCover: Api.InputPhoto?, videoTimestamp: Int32?, ttlSeconds: Int32?, query: String?)
|
||||
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?, videoCover: Api.InputPhoto?, videoTimestamp: Int32?)
|
||||
case inputMediaEmpty
|
||||
case inputMediaGame(id: Api.InputGame)
|
||||
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
|
||||
@ -444,7 +444,7 @@ public extension Api {
|
||||
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
|
||||
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
|
||||
case inputMediaStory(peer: Api.InputPeer, id: Int32)
|
||||
case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], stickers: [Api.InputDocument]?, videoCover: Api.InputPhoto?, ttlSeconds: Int32?)
|
||||
case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], stickers: [Api.InputDocument]?, videoCover: Api.InputPhoto?, videoTimestamp: Int32?, ttlSeconds: Int32?)
|
||||
case inputMediaUploadedPhoto(flags: Int32, file: Api.InputFile, stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
|
||||
case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
|
||||
case inputMediaWebPage(flags: Int32, url: String)
|
||||
@ -466,24 +466,26 @@ public extension Api {
|
||||
}
|
||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let ttlSeconds, let query):
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let videoTimestamp, let ttlSeconds, let query):
|
||||
if boxed {
|
||||
buffer.appendInt32(1946579745)
|
||||
buffer.appendInt32(-1468646731)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
id.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 3) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover):
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover, let videoTimestamp):
|
||||
if boxed {
|
||||
buffer.appendInt32(-149933938)
|
||||
buffer.appendInt32(2006319353)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaEmpty:
|
||||
if boxed {
|
||||
@ -582,9 +584,9 @@ public extension Api {
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let ttlSeconds):
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(-264125395)
|
||||
buffer.appendInt32(58495792)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
file.serialize(buffer, true)
|
||||
@ -601,6 +603,7 @@ public extension Api {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 6) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
|
||||
@ -643,10 +646,10 @@ public extension Api {
|
||||
return ("inputMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any)])
|
||||
case .inputMediaDice(let emoticon):
|
||||
return ("inputMediaDice", [("emoticon", emoticon as Any)])
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let ttlSeconds, let query):
|
||||
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover):
|
||||
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any), ("videoCover", videoCover as Any)])
|
||||
case .inputMediaDocument(let flags, let id, let videoCover, let videoTimestamp, let ttlSeconds, let query):
|
||||
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
|
||||
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds, let videoCover, let videoTimestamp):
|
||||
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any)])
|
||||
case .inputMediaEmpty:
|
||||
return ("inputMediaEmpty", [])
|
||||
case .inputMediaGame(let id):
|
||||
@ -667,8 +670,8 @@ public extension Api {
|
||||
return ("inputMediaPoll", [("flags", flags as Any), ("poll", poll as Any), ("correctAnswers", correctAnswers as Any), ("solution", solution as Any), ("solutionEntities", solutionEntities as Any)])
|
||||
case .inputMediaStory(let peer, let id):
|
||||
return ("inputMediaStory", [("peer", peer as Any), ("id", id as Any)])
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let ttlSeconds):
|
||||
return ("inputMediaUploadedDocument", [("flags", flags as Any), ("file", file as Any), ("thumb", thumb as Any), ("mimeType", mimeType as Any), ("attributes", attributes as Any), ("stickers", stickers as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
return ("inputMediaUploadedDocument", [("flags", flags as Any), ("file", file as Any), ("thumb", thumb as Any), ("mimeType", mimeType as Any), ("attributes", attributes as Any), ("stickers", stickers as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
|
||||
return ("inputMediaUploadedPhoto", [("flags", flags as Any), ("file", file as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
|
||||
@ -721,16 +724,19 @@ public extension Api {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
||||
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: String?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, videoCover: _3, ttlSeconds: _4, query: _5)
|
||||
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, videoCover: _3, videoTimestamp: _4, ttlSeconds: _5, query: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -747,12 +753,15 @@ public extension Api {
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3, videoCover: _4)
|
||||
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3, videoCover: _4, videoTimestamp: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -987,7 +996,9 @@ public extension Api {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||
} }
|
||||
var _8: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_8 = reader.readInt32() }
|
||||
if Int(_1!) & Int(1 << 7) != 0 {_8 = reader.readInt32() }
|
||||
var _9: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_9 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
||||
@ -995,9 +1006,10 @@ public extension Api {
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, videoCover: _7, ttlSeconds: _8)
|
||||
let _c8 = (Int(_1!) & Int(1 << 7) == 0) || _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, videoCover: _7, videoTimestamp: _8, ttlSeconds: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -710,7 +710,7 @@ public extension Api {
|
||||
indirect enum MessageMedia: TypeConstructorDescription {
|
||||
case messageMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String, userId: Int64)
|
||||
case messageMediaDice(value: Int32, emoticon: String)
|
||||
case messageMediaDocument(flags: Int32, document: Api.Document?, altDocuments: [Api.Document]?, videoCover: Api.Photo?, ttlSeconds: Int32?)
|
||||
case messageMediaDocument(flags: Int32, document: Api.Document?, altDocuments: [Api.Document]?, videoCover: Api.Photo?, videoTimestamp: Int32?, ttlSeconds: Int32?)
|
||||
case messageMediaEmpty
|
||||
case messageMediaGame(game: Api.Game)
|
||||
case messageMediaGeo(geo: Api.GeoPoint)
|
||||
@ -745,9 +745,9 @@ public extension Api {
|
||||
serializeInt32(value, buffer: buffer, boxed: false)
|
||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let ttlSeconds):
|
||||
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
if boxed {
|
||||
buffer.appendInt32(-608307692)
|
||||
buffer.appendInt32(1389939929)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
||||
@ -757,6 +757,7 @@ public extension Api {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 9) != 0 {videoCover!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .messageMediaEmpty:
|
||||
@ -910,8 +911,8 @@ public extension Api {
|
||||
return ("messageMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any), ("userId", userId as Any)])
|
||||
case .messageMediaDice(let value, let emoticon):
|
||||
return ("messageMediaDice", [("value", value as Any), ("emoticon", emoticon as Any)])
|
||||
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let ttlSeconds):
|
||||
return ("messageMediaDocument", [("flags", flags as Any), ("document", document as Any), ("altDocuments", altDocuments as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .messageMediaDocument(let flags, let document, let altDocuments, let videoCover, let videoTimestamp, let ttlSeconds):
|
||||
return ("messageMediaDocument", [("flags", flags as Any), ("document", document as Any), ("altDocuments", altDocuments as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any), ("ttlSeconds", ttlSeconds as Any)])
|
||||
case .messageMediaEmpty:
|
||||
return ("messageMediaEmpty", [])
|
||||
case .messageMediaGame(let game):
|
||||
@ -996,14 +997,17 @@ public extension Api {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Photo
|
||||
} }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() }
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, videoCover: _4, ttlSeconds: _5)
|
||||
let _c5 = (Int(_1!) & Int(1 << 10) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, videoCover: _4, videoTimestamp: _5, ttlSeconds: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -350,7 +350,8 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
|
||||
case let .messageMediaGeoLive(_, geo, heading, period, proximityNotificationRadius):
|
||||
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: proximityNotificationRadius, heading: heading)
|
||||
return (mediaMap, nil, nil, nil, nil)
|
||||
case let .messageMediaDocument(flags, document, altDocuments, coverPhoto, ttlSeconds):
|
||||
case let .messageMediaDocument(flags, document, altDocuments, coverPhoto, videoTimestamp, ttlSeconds):
|
||||
let _ = videoTimestamp
|
||||
if let document = document {
|
||||
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto) {
|
||||
return (mediaFile, ttlSeconds, (flags & (1 << 3)) != 0, (flags & (1 << 4)) != 0, nil)
|
||||
|
@ -229,7 +229,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
|
||||
}
|
||||
|> mapToSignal { validatedResource -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||
if let validatedResource = validatedResource.updatedResource as? TelegramCloudMediaResourceWithFileReference, let reference = validatedResource.fileReference {
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: 0, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: reference)), videoCover: nil, ttlSeconds: nil, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: 0, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: reference)), videoCover: nil, videoTimestamp: nil, ttlSeconds: nil, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -246,7 +246,7 @@ func mediaContentToUpload(accountPeerId: PeerId, network: Network, postbox: Post
|
||||
}
|
||||
}
|
||||
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, ttlSeconds: nil, query: emojiSearchQuery), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, videoTimestamp: nil, ttlSeconds: nil, query: emojiSearchQuery), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
}
|
||||
} else {
|
||||
return uploadedMediaFileContent(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, forceReupload: forceReupload, isGrouped: isGrouped, isPaid: false, passFetchProgress: passFetchProgress, forceNoBigParts: forceNoBigParts, peerId: peerId, messageId: messageId, text: text, attributes: attributes, autoremoveMessageAttribute: autoremoveMessageAttribute, autoclearMessageAttribute: autoclearMessageAttribute, file: file)
|
||||
@ -866,7 +866,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
|
||||
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|
||||
|> then(
|
||||
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: nil, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: nil, videoTimestamp: nil, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||
)
|
||||
}
|
||||
referenceKey = key
|
||||
@ -1122,11 +1122,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
}
|
||||
|
||||
if ttlSeconds != nil {
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)))
|
||||
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: nil, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)))
|
||||
}
|
||||
|
||||
if !isGrouped {
|
||||
let resultInfo = PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)
|
||||
let resultInfo = PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: nil, ttlSeconds: ttlSeconds), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)
|
||||
|
||||
return .single(.content(resultInfo))
|
||||
}
|
||||
@ -1137,11 +1137,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
|> mapError { _ -> PendingMessageUploadError in }
|
||||
|> mapToSignal { inputPeer -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||
if let inputPeer = inputPeer {
|
||||
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: .inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, ttlSeconds: ttlSeconds)))
|
||||
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: .inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: nil, ttlSeconds: ttlSeconds)))
|
||||
|> mapError { _ -> PendingMessageUploadError in return .generic }
|
||||
|> mapToSignal { result -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||
switch result {
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _):
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
|
||||
if let document = document, let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments), let resource = mediaFile.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
|
||||
var flags: Int32 = 0
|
||||
var ttlSeconds: Int32?
|
||||
@ -1156,7 +1156,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
flags |= (1 << 3)
|
||||
}
|
||||
|
||||
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaDocument(flags: flags, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: videoCoverPhoto, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil))
|
||||
let result: PendingMessageUploadedContentResult = .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaDocument(flags: flags, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: videoCoverPhoto, videoTimestamp: nil, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil))
|
||||
if let _ = ttlSeconds {
|
||||
return .single(result)
|
||||
} else {
|
||||
|
@ -702,7 +702,7 @@ private func uploadedFile(account: Account, data: Data, mimeType: String, attrib
|
||||
|> map { next -> UploadMediaEvent in
|
||||
switch next {
|
||||
case let .inputFile(inputFile):
|
||||
return .result(Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, ttlSeconds: nil))
|
||||
return .result(Api.InputMedia.inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil))
|
||||
case .inputSecretFile:
|
||||
preconditionFailure()
|
||||
case let .progress(progress):
|
||||
|
@ -158,11 +158,11 @@ public func standaloneUploadedFile(postbox: Postbox, network: Network, peerId: P
|
||||
if let _ = thumbnailFile {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, ttlSeconds: nil)))
|
||||
return network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: mimeType, attributes: inputDocumentAttributesFromFileAttributes(attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)))
|
||||
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|
||||
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||
switch media {
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _):
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
|
||||
if let document = document {
|
||||
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments) {
|
||||
return .single(.result(.media(.standalone(media: mediaFile))))
|
||||
|
@ -52,7 +52,7 @@ extension Api.MessageMedia {
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case let .messageMediaDocument(_, document, _, _, _):
|
||||
case let .messageMediaDocument(_, document, _, _, _, _):
|
||||
if let document = document {
|
||||
return collectPreCachedResources(for: document)
|
||||
}
|
||||
@ -626,14 +626,14 @@ extension Api.EncryptedMessage {
|
||||
extension Api.InputMedia {
|
||||
func withUpdatedStickers(_ stickers: [Api.InputDocument]?) -> Api.InputMedia {
|
||||
switch self {
|
||||
case let .inputMediaUploadedDocument(flags, file, thumb, mimeType, attributes, _, videoCover, ttlSeconds):
|
||||
case let .inputMediaUploadedDocument(flags, file, thumb, mimeType, attributes, _, videoCover, videoTimestamp, ttlSeconds):
|
||||
var flags = flags
|
||||
var attributes = attributes
|
||||
if let _ = stickers {
|
||||
flags |= (1 << 0)
|
||||
attributes.append(.documentAttributeHasStickers)
|
||||
}
|
||||
return .inputMediaUploadedDocument(flags: flags, file: file, thumb: thumb, mimeType: mimeType, attributes: attributes, stickers: stickers, videoCover: videoCover, ttlSeconds: ttlSeconds)
|
||||
return .inputMediaUploadedDocument(flags: flags, file: file, thumb: thumb, mimeType: mimeType, attributes: attributes, stickers: stickers, videoCover: videoCover, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds)
|
||||
case let .inputMediaUploadedPhoto(flags, file, _, ttlSeconds):
|
||||
var flags = flags
|
||||
if let _ = stickers {
|
||||
|
@ -153,7 +153,7 @@ public extension TelegramEngine {
|
||||
default:
|
||||
break
|
||||
}
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: resolvedMimeType, attributes: attributes, stickers: nil, videoCover: nil, ttlSeconds: nil)
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: resolvedMimeType, attributes: attributes, stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)
|
||||
}
|
||||
case let .progress(value):
|
||||
return .single(value)
|
||||
|
@ -1405,7 +1405,7 @@ func _internal_deleteBotPreviews(account: Account, peerId: PeerId, language: Str
|
||||
inputMedia.append(.inputMediaPhoto(flags: 0, id: .inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
inputMedia.append(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
} else if let file = item as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, ttlSeconds: nil, query: nil))
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, videoTimestamp: nil, ttlSeconds: nil, query: nil))
|
||||
}
|
||||
}
|
||||
if language == nil {
|
||||
@ -1463,7 +1463,7 @@ func _internal_deleteBotPreviewsLanguage(account: Account, peerId: PeerId, langu
|
||||
inputMedia.append(.inputMediaPhoto(flags: 0, id: .inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
inputMedia.append(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
} else if let file = item as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, ttlSeconds: nil, query: nil))
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, videoTimestamp: nil, ttlSeconds: nil, query: nil))
|
||||
}
|
||||
}
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current -> CachedPeerData? in
|
||||
@ -1528,7 +1528,7 @@ func _internal_editStory(account: Account, peerId: PeerId, id: Int32, media: Eng
|
||||
if let result = result, case let .content(uploadedContent) = result, case let .media(media, _) = uploadedContent.content {
|
||||
inputMedia = media
|
||||
} else if case let .existing(media) = media, let file = media as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: .inputFileStoryDocument(id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference))), thumb: nil, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: nil, videoCover: nil, ttlSeconds: nil)
|
||||
inputMedia = .inputMediaUploadedDocument(flags: 0, file: .inputFileStoryDocument(id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference))), thumb: nil, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)
|
||||
updatingCoverTime = true
|
||||
} else {
|
||||
inputMedia = nil
|
||||
@ -2099,7 +2099,7 @@ extension Stories.StoredItem {
|
||||
|
||||
var parsedAlternativeMedia: [Media] = []
|
||||
switch media {
|
||||
case let .messageMediaDocument(_, _, altDocuments, _, _):
|
||||
case let .messageMediaDocument(_, _, altDocuments, _, _, _):
|
||||
if let altDocuments {
|
||||
parsedAlternativeMedia = altDocuments.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
|
||||
}
|
||||
|
@ -2615,7 +2615,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
|
||||
inputMedia.append(.inputMediaPhoto(flags: 0, id: .inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
inputMedia.append(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil))
|
||||
} else if let file = item as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, ttlSeconds: nil, query: nil))
|
||||
inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), videoCover: nil, videoTimestamp: nil, ttlSeconds: nil, query: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -925,7 +925,10 @@ private final class ProfileGiftsContextImpl {
|
||||
private let cacheDisposable = MetaDisposable()
|
||||
private let actionDisposable = MetaDisposable()
|
||||
|
||||
private var sorting: ProfileGiftsContext.Sorting = .date
|
||||
private var filter: ProfileGiftsContext.Filters = ProfileGiftsContext.Filters.All
|
||||
private var gifts: [ProfileGiftsContext.State.StarGift] = []
|
||||
private var filteredGifts: [ProfileGiftsContext.State.StarGift] = []
|
||||
private var count: Int32?
|
||||
private var dataState: ProfileGiftsContext.State.DataState = .ready(canLoadMore: true, nextOffset: nil)
|
||||
private var notificationsEnabled: Bool?
|
||||
@ -1111,13 +1114,47 @@ private final class ProfileGiftsContextImpl {
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
func updateFilter(_ filter: ProfileGiftsContext.Filters) {
|
||||
self.filter = filter
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
func updateSorting(_ sorting: ProfileGiftsContext.Sorting) {
|
||||
self.sorting = sorting
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
private func pushState() {
|
||||
self._state = ProfileGiftsContext.State(gifts: self.gifts, count: self.count, dataState: self.dataState, notificationsEnabled: self.notificationsEnabled)
|
||||
self.stateValue.set(.single(ProfileGiftsContext.State(gifts: self.gifts, count: self.count, dataState: self.dataState, notificationsEnabled: self.notificationsEnabled)))
|
||||
let state = ProfileGiftsContext.State(filter: self.filter, sorting: self.sorting, gifts: self.gifts, count: self.count, dataState: self.dataState, notificationsEnabled: self.notificationsEnabled)
|
||||
self._state = state
|
||||
self.stateValue.set(.single(state))
|
||||
}
|
||||
}
|
||||
|
||||
public final class ProfileGiftsContext {
|
||||
public struct Filters: OptionSet {
|
||||
public var rawValue: Int32
|
||||
|
||||
public init(rawValue: Int32) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public static let unlimited = Filters(rawValue: 1 << 0)
|
||||
public static let limited = Filters(rawValue: 1 << 1)
|
||||
public static let unique = Filters(rawValue: 1 << 2)
|
||||
public static let displayed = Filters(rawValue: 1 << 3)
|
||||
public static let hidden = Filters(rawValue: 1 << 4)
|
||||
|
||||
public static var All: Filters {
|
||||
return [.unlimited, .limited, .unique, .displayed, .hidden]
|
||||
}
|
||||
}
|
||||
|
||||
public enum Sorting: Equatable {
|
||||
case date
|
||||
case value
|
||||
}
|
||||
|
||||
public struct State: Equatable {
|
||||
public struct StarGift: Equatable, Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@ -1273,6 +1310,9 @@ public final class ProfileGiftsContext {
|
||||
case ready(canLoadMore: Bool, nextOffset: String?)
|
||||
}
|
||||
|
||||
|
||||
public var filter: Filters
|
||||
public var sorting: Sorting
|
||||
public var gifts: [ProfileGiftsContext.State.StarGift]
|
||||
public var count: Int32?
|
||||
public var dataState: ProfileGiftsContext.State.DataState
|
||||
@ -1349,6 +1389,18 @@ public final class ProfileGiftsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func updateFilter(_ filter: ProfileGiftsContext.Filters) {
|
||||
self.impl.with { impl in
|
||||
impl.updateFilter(filter)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateSorting(_ sorting: ProfileGiftsContext.Sorting) {
|
||||
self.impl.with { impl in
|
||||
impl.updateSorting(sorting)
|
||||
}
|
||||
}
|
||||
|
||||
public var currentState: ProfileGiftsContext.State? {
|
||||
var state: ProfileGiftsContext.State?
|
||||
self.impl.syncWith { impl in
|
||||
|
@ -83,11 +83,11 @@ func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResour
|
||||
attributes.append(.documentAttributeVideo(flags: 0, duration: duration, w: dimensions.width, h: dimensions.height, preloadPrefixSize: nil, videoStartTs: nil, videoCodec: nil))
|
||||
}
|
||||
attributes.append(.documentAttributeImageSize(w: dimensions.width, h: dimensions.height))
|
||||
return account.network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: file, thumb: thumbnailFile, mimeType: mimeType, attributes: attributes, stickers: nil, videoCover: nil, ttlSeconds: nil)))
|
||||
return account.network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: file, thumb: thumbnailFile, mimeType: mimeType, attributes: attributes, stickers: nil, videoCover: nil, videoTimestamp: nil, ttlSeconds: nil)))
|
||||
|> mapError { _ -> UploadStickerError in return .generic }
|
||||
|> mapToSignal { media -> Signal<UploadStickerStatus, UploadStickerError> in
|
||||
switch media {
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _):
|
||||
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
|
||||
if let document = document, let file = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments), let uploadedResource = file.resource as? CloudDocumentMediaResource {
|
||||
account.postbox.mediaBox.copyResourceData(from: resource.id, to: uploadedResource.id, synchronous: true)
|
||||
if let thumbnail, let previewRepresentation = file.previewRepresentations.first(where: { $0.dimensions == PixelDimensions(width: 320, height: 320) }) {
|
||||
|
@ -201,6 +201,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
||||
case dismissedBusinessChatbotsBadge = 74
|
||||
case captionAboveMediaTooltip = 75
|
||||
case channelSendGiftTooltip = 76
|
||||
case starGiftWearTips = 77
|
||||
|
||||
var key: ValueBoxKey {
|
||||
let v = ValueBoxKey(length: 4)
|
||||
@ -549,6 +550,10 @@ private struct ApplicationSpecificNoticeKeys {
|
||||
static func channelSendGiftTooltip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.channelSendGiftTooltip.key)
|
||||
}
|
||||
|
||||
static func starGiftWearTips() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.starGiftWearTips.key)
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationSpecificNotice {
|
||||
@ -2335,4 +2340,31 @@ public struct ApplicationSpecificNotice {
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getStarGiftWearTips(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||
return accountManager.transaction { transaction -> Int32 in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.starGiftWearTips())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
return value.value
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func incrementStarGiftWearTips(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int = 1) -> Signal<Int, NoError> {
|
||||
return accountManager.transaction { transaction -> Int in
|
||||
var currentValue: Int32 = 0
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.starGiftWearTips())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
currentValue = value.value
|
||||
}
|
||||
let previousValue = currentValue
|
||||
currentValue += Int32(count)
|
||||
|
||||
if let entry = CodableEntry(ApplicationSpecificCounterNotice(value: currentValue)) {
|
||||
transaction.setNotice(ApplicationSpecificNoticeKeys.starGiftWearTips(), entry)
|
||||
}
|
||||
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,4 +193,10 @@ public struct PresentationResourcesRootController {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/AddStoryIcon"), color: .white)
|
||||
})
|
||||
}
|
||||
|
||||
public static func navigationSortIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.navigationPostStoryIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/SortIcon"), color: .white)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1113,7 +1113,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
}
|
||||
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, _, _, _):
|
||||
if case let .unique(gift) = gift {
|
||||
if !forAdditionalServiceMessage {
|
||||
if !forAdditionalServiceMessage && !"".isEmpty {
|
||||
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
|
||||
} else if let messagePeer = message.peers[message.id.peerId] {
|
||||
let peerName = EnginePeer(messagePeer).compactDisplayTitle
|
||||
|
@ -20,6 +20,7 @@ swift_library(
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/PresentationDataUtils",
|
||||
"//submodules/Markdown",
|
||||
"//submodules/TelegramNotices",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/Components/ViewControllerComponent",
|
||||
|
@ -31,6 +31,7 @@ import TooltipUI
|
||||
import GiftAnimationComponent
|
||||
import LottieComponent
|
||||
import ContextUI
|
||||
import TelegramNotices
|
||||
|
||||
private let modelButtonTag = GenericComponentViewTag()
|
||||
private let backdropButtonTag = GenericComponentViewTag()
|
||||
@ -286,6 +287,25 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
self.updated(transition: .spring(duration: 0.4))
|
||||
}
|
||||
|
||||
func commitWear(_ uniqueGift: StarGift.UniqueGift) {
|
||||
self.pendingWear = true
|
||||
self.pendingTakeOff = false
|
||||
self.inWearPreview = false
|
||||
self.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
let _ = self.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).startStandalone()
|
||||
|
||||
let _ = ApplicationSpecificNotice.incrementStarGiftWearTips(accountManager: self.context.sharedContext.accountManager).startStandalone()
|
||||
}
|
||||
|
||||
func commitTakeOff() {
|
||||
self.pendingTakeOff = true
|
||||
self.pendingWear = false
|
||||
self.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
let _ = self.context.engine.accountData.setEmojiStatus(file: nil, expirationDate: nil).startStandalone()
|
||||
}
|
||||
|
||||
func commitUpgrade() {
|
||||
guard let arguments = self.subject.arguments, let peerId = arguments.peerId, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
||||
return
|
||||
@ -1117,6 +1137,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
if peer.id == component.context.account.peerId, peer.isPremium {
|
||||
let animationContent: EmojiStatusComponent.Content
|
||||
var color: UIColor?
|
||||
var statusId: Int64 = 1
|
||||
if state.pendingWear {
|
||||
var fileId: Int64?
|
||||
for attribute in uniqueGift.attributes {
|
||||
@ -1128,6 +1149,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
}
|
||||
}
|
||||
if let fileId {
|
||||
statusId = fileId
|
||||
animationContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 18.0, height: 18.0), placeholderColor: theme.list.mediaPlaceholderColor, themeColor: tableLinkColor, loopMode: .count(2))
|
||||
} else {
|
||||
animationContent = .premium(color: tableLinkColor)
|
||||
@ -1168,7 +1190,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
))
|
||||
),
|
||||
AnyComponentWithIdentity(
|
||||
id: AnyHashable(1),
|
||||
id: AnyHashable(statusId),
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: component.context,
|
||||
animationCache: component.context.animationCache,
|
||||
@ -1351,17 +1373,26 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
action: { [weak state] in
|
||||
if let state {
|
||||
if isWearing {
|
||||
state.pendingTakeOff = true
|
||||
state.pendingWear = false
|
||||
state.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
state.commitTakeOff()
|
||||
|
||||
component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
||||
} else {
|
||||
if let controller = controller() as? GiftViewScreen {
|
||||
controller.dismissAllTooltips()
|
||||
}
|
||||
|
||||
state.requestWearPreview()
|
||||
let _ = (ApplicationSpecificNotice.getStarGiftWearTips(accountManager: component.context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue).start(next: { [weak state] count in
|
||||
guard let state else {
|
||||
return
|
||||
}
|
||||
if !component.context.isPremium || count < 3 {
|
||||
state.requestWearPreview()
|
||||
} else {
|
||||
state.commitWear(uniqueGift)
|
||||
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1731,7 +1762,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
items: tableItems
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),
|
||||
transition: .immediate
|
||||
transition: context.transition
|
||||
)
|
||||
context.add(table
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0))
|
||||
@ -1866,13 +1897,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
)
|
||||
controller.present(tooltipController, in: .window(.root))
|
||||
} else {
|
||||
state.pendingWear = true
|
||||
state.pendingTakeOff = false
|
||||
state.inWearPreview = false
|
||||
state.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
let _ = component.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).start()
|
||||
|
||||
state.commitWear(uniqueGift)
|
||||
Queue.mainQueue().after(0.2) {
|
||||
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
||||
}
|
||||
|
@ -439,13 +439,7 @@ public final class PeerInfoCoverComponent: Component {
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -1000.0 + availableSize.height), size: CGSize(width: availableSize.width, height: 1000.0))
|
||||
transition.containedViewLayoutTransition.updateFrameAdditive(view: self.backgroundView, frame: backgroundFrame)
|
||||
|
||||
/*let avatarBackgroundPatternContainerFrame = CGSize(width: 0.0, height: 0.0).centered(around: component.avatarCenter)
|
||||
transition.containedViewLayoutTransition.updateFrameAdditive(view: self.avatarBackgroundPatternContainer, frame: avatarBackgroundPatternContainerFrame)
|
||||
transition.containedViewLayoutTransition.updateSublayerTransformScaleAdditive(layer: self.avatarBackgroundPatternContainer.layer, scale: component.avatarScale)*/
|
||||
|
||||
//transition.setFrame(view: self.avatarBackgroundPatternView, frame: CGSize(width: 200.0, height: 200.0).centered(around: CGPoint()))
|
||||
|
||||
|
||||
let avatarPatternFrame = CGSize(width: 380.0, height: floor(component.defaultHeight * 1.0)).centered(around: component.avatarCenter)
|
||||
transition.setFrame(layer: self.avatarBackgroundPatternContentsLayer, frame: avatarPatternFrame)
|
||||
|
||||
@ -457,7 +451,7 @@ public final class PeerInfoCoverComponent: Component {
|
||||
]
|
||||
} else if case let .status(status) = component.subject, case let .starGift(_, _, _, _, _, _, _, patternColorValue, _) = status.content {
|
||||
let patternColor = UIColor(rgb: UInt32(bitPattern: patternColorValue))
|
||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
|
||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = "overlayBlendMode"
|
||||
self.avatarBackgroundPatternContentsLayer.colors = [
|
||||
patternColor.withAlphaComponent(0.6).cgColor,
|
||||
patternColor.withAlphaComponent(0.0).cgColor
|
||||
@ -469,7 +463,6 @@ public final class PeerInfoCoverComponent: Component {
|
||||
UIColor(white: 0.0, alpha: 0.6).cgColor,
|
||||
UIColor(white: 0.0, alpha: 0.0).cgColor
|
||||
]
|
||||
|
||||
} else {
|
||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
|
||||
let baseWhite: CGFloat = component.isDark ? 0.5 : 0.3
|
||||
|
@ -282,6 +282,10 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
text = ""
|
||||
accessibilityText = presentationData.strings.Story_Privacy_PostStory
|
||||
icon = PresentationResourcesRootController.navigationPostStoryIcon(presentationData.theme)
|
||||
case .sort:
|
||||
text = ""
|
||||
accessibilityText = presentationData.strings.Common_More
|
||||
icon = PresentationResourcesRootController.navigationSortIcon(presentationData.theme)
|
||||
}
|
||||
self.accessibilityLabel = accessibilityText
|
||||
self.containerNode.isGestureEnabled = isGestureEnabled
|
||||
|
@ -21,6 +21,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
||||
case qrCode
|
||||
case moreToSearch
|
||||
case postStory
|
||||
case sort
|
||||
}
|
||||
|
||||
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||
|
@ -2306,11 +2306,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
Queue.mainQueue().after(0.2) {
|
||||
backgroundCoverView.animateIn()
|
||||
}
|
||||
Queue.mainQueue().after(0.44) {
|
||||
Queue.mainQueue().after(0.5) {
|
||||
self.invokeDisplayGiftInfo()
|
||||
}
|
||||
} else {
|
||||
Queue.mainQueue().after(0.44) {
|
||||
Queue.mainQueue().after(0.5) {
|
||||
self.invokeDisplayGiftInfo()
|
||||
}
|
||||
}
|
||||
|
@ -4430,14 +4430,27 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
case .search, .searchWithTags, .standaloneSearch:
|
||||
strongSelf.activateSearch()
|
||||
case .more:
|
||||
if let currentPaneKey = strongSelf.paneContainerNode.currentPaneKey, case .savedMessagesChats = currentPaneKey {
|
||||
if let controller = strongSelf.controller, let source {
|
||||
PeerInfoScreenImpl.openSavedMessagesMoreMenu(context: strongSelf.context, sourceController: controller, isViewingAsTopics: true, sourceView: source.view, gesture: gesture)
|
||||
guard let source else {
|
||||
return
|
||||
}
|
||||
if let currentPaneKey = strongSelf.paneContainerNode.currentPaneKey {
|
||||
switch currentPaneKey {
|
||||
case .savedMessagesChats:
|
||||
if let controller = strongSelf.controller {
|
||||
PeerInfoScreenImpl.openSavedMessagesMoreMenu(context: strongSelf.context, sourceController: controller, isViewingAsTopics: true, sourceView: source.view, gesture: gesture)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if let source = source {
|
||||
strongSelf.displayMediaGalleryContextMenu(source: source, gesture: gesture)
|
||||
}
|
||||
strongSelf.displayMediaGalleryContextMenu(source: source, gesture: gesture)
|
||||
}
|
||||
case .sort:
|
||||
guard let source else {
|
||||
return
|
||||
}
|
||||
if let currentPaneKey = strongSelf.paneContainerNode.currentPaneKey, case .gifts = currentPaneKey {
|
||||
strongSelf.displayGiftsContextMenu(source: source, gesture: gesture)
|
||||
}
|
||||
case .qrCode:
|
||||
strongSelf.openQrCode()
|
||||
@ -4651,6 +4664,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
style: .customBlur(backgroundColor, -4.0),
|
||||
arrowStyle: .small,
|
||||
location: .point(sourceRect, .bottom),
|
||||
isShimmering: true,
|
||||
cornerRadius: 10.0,
|
||||
shouldDismissOnTouch: { _, _ in
|
||||
return .dismiss(consume: false)
|
||||
@ -10883,6 +10897,126 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
return .dismiss(consume: false)
|
||||
}), in: .current)
|
||||
}
|
||||
|
||||
private func displayGiftsContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) {
|
||||
guard let currentPaneKey = self.paneContainerNode.currentPaneKey, case .gifts = currentPaneKey else {
|
||||
return
|
||||
}
|
||||
guard let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
guard let data = self.data, let channel = data.peer as? TelegramChannel, channel.hasPermission(.sendSomething), let giftsContext = data.profileGiftsContext else {
|
||||
return
|
||||
}
|
||||
|
||||
let strings = self.presentationData.strings
|
||||
let items: Signal<ContextController.Items, NoError> = giftsContext.state
|
||||
|> map { state in
|
||||
return (state.filter, state.sorting)
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs -> Bool in
|
||||
let filterEquals = lhs.0 == rhs.0
|
||||
let sortingEquals = lhs.1 == rhs.1
|
||||
return filterEquals && sortingEquals
|
||||
})
|
||||
|> map { [weak giftsContext] filter, sorting -> ContextController.Items in
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: sorting == .date ? strings.PeerInfo_Gifts_SortByValue : strings.PeerInfo_Gifts_SortByDate, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: sorting == .date ? "Peer Info/SortValue" : "Peer Info/SortDate"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak giftsContext] _, f in
|
||||
f(.default)
|
||||
|
||||
giftsContext?.updateSorting(sorting == .date ? .value : .date)
|
||||
})))
|
||||
|
||||
items.append(.separator)
|
||||
|
||||
let toggleFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
|
||||
var updatedFilter = filter
|
||||
if updatedFilter.contains(value) {
|
||||
updatedFilter.remove(value)
|
||||
} else {
|
||||
updatedFilter.insert(value)
|
||||
}
|
||||
giftsContext?.updateFilter(updatedFilter)
|
||||
}
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in
|
||||
return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
toggleFilter(.unlimited)
|
||||
})))
|
||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in
|
||||
return filter.contains(.limited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
toggleFilter(.limited)
|
||||
})))
|
||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in
|
||||
return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
toggleFilter(.unique)
|
||||
})))
|
||||
|
||||
items.append(.separator)
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Displayed, icon: { theme in
|
||||
return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
toggleFilter(.displayed)
|
||||
})))
|
||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in
|
||||
return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
toggleFilter(.hidden)
|
||||
})))
|
||||
|
||||
return ContextController.Items(content: .list(items))
|
||||
}
|
||||
|
||||
let contextController = ContextController(presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: items, gesture: gesture)
|
||||
contextController.passthroughTouchEvent = { [weak self] sourceView, point in
|
||||
guard let strongSelf = self else {
|
||||
return .ignore
|
||||
}
|
||||
|
||||
let localPoint = strongSelf.view.convert(sourceView.convert(point, to: nil), from: nil)
|
||||
guard let localResult = strongSelf.hitTest(localPoint, with: nil) else {
|
||||
return .dismiss(consume: true, result: nil)
|
||||
}
|
||||
|
||||
var testView: UIView? = localResult
|
||||
while true {
|
||||
if let testViewValue = testView {
|
||||
if let node = testViewValue.asyncdisplaykit_node as? PeerInfoHeaderNavigationButton {
|
||||
node.isUserInteractionEnabled = false
|
||||
DispatchQueue.main.async {
|
||||
node.isUserInteractionEnabled = true
|
||||
}
|
||||
return .dismiss(consume: false, result: nil)
|
||||
} else {
|
||||
testView = testViewValue.superview
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return .dismiss(consume: true, result: nil)
|
||||
}
|
||||
self.mediaGalleryContextMenu = contextController
|
||||
controller.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
|
||||
private func displayMediaGalleryContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) {
|
||||
let peerId = self.peerId
|
||||
@ -11873,6 +12007,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
if let data = self.data, data.hasBotPreviewItems, let user = data.peer as? TelegramUser, let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) {
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true))
|
||||
}
|
||||
case .gifts:
|
||||
if let data = self.data, let channel = data.peer as? TelegramChannel, channel.hasPermission(.sendSomething) {
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .sort, isForExpandedView: true))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortDate.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortDate.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "sortdate_24.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortDate.imageset/sortdate_24.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortDate.imageset/sortdate_24.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "sort_30.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortIcon.imageset/sort_30.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortIcon.imageset/sort_30.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortValue.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Peer Info/SortValue.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "sortvalue_24.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortValue.imageset/sortvalue_24.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Peer Info/SortValue.imageset/sortvalue_24.pdf
vendored
Normal file
Binary file not shown.
@ -26,6 +26,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
|
||||
"//submodules/Components/BalancedTextComponent",
|
||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||
"//submodules/ShimmerEffect",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -18,6 +18,7 @@ import AccountContext
|
||||
import Markdown
|
||||
import BalancedTextComponent
|
||||
import MultilineTextWithEntitiesComponent
|
||||
import ShimmerEffect
|
||||
|
||||
public enum TooltipActiveTextItem {
|
||||
case url(String, Bool)
|
||||
@ -126,6 +127,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
private let isShimmering: Bool
|
||||
private let displayDuration: TooltipScreen.DisplayDuration
|
||||
private let shouldDismissOnTouch: (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch
|
||||
private let requestDismiss: () -> Void
|
||||
@ -149,6 +151,9 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
private var closeButtonNode: HighlightableButtonNode?
|
||||
private var actionButtonNode: HighlightableButtonNode?
|
||||
|
||||
private var shimmerContainerView: UIView?
|
||||
private var shimmerView: ShimmerEffectForegroundView?
|
||||
|
||||
private var isArrowInverted: Bool = false
|
||||
|
||||
private let fontSize: CGFloat
|
||||
@ -172,6 +177,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
displayDuration: TooltipScreen.DisplayDuration,
|
||||
inset: CGFloat = 12.0,
|
||||
cornerRadius: CGFloat? = nil,
|
||||
isShimmering: Bool = false,
|
||||
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?)
|
||||
{
|
||||
self.context = context
|
||||
@ -181,6 +187,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
self.action = action
|
||||
self.location = location
|
||||
self.displayDuration = displayDuration
|
||||
self.isShimmering = isShimmering
|
||||
self.inset = inset
|
||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||
self.requestDismiss = requestDismiss
|
||||
@ -446,7 +453,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
self.actionButtonNode?.addTarget(self, action: #selector(self.actionPressed), forControlEvents: .touchUpInside)
|
||||
self.closeButtonNode?.addTarget(self, action: #selector(self.closePressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
|
||||
@objc private func actionPressed() {
|
||||
if let action = self.action {
|
||||
action.action()
|
||||
@ -713,8 +720,8 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
transition.updateFrame(node: self.backgroundMaskNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0))
|
||||
transition.updateFrame(node: self.backgroundClipNode, frame: CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: backgroundFrame.size))
|
||||
|
||||
let effectFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0)
|
||||
if let effectNode = self.effectNode {
|
||||
let effectFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0)
|
||||
transition.updateFrame(node: effectNode, frame: effectFrame)
|
||||
effectNode.update(size: effectFrame.size, transition: transition)
|
||||
}
|
||||
@ -843,6 +850,69 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
transition.updateFrame(node: avatarNode, frame: avatarFrame)
|
||||
avatarNode.updateSize(size: avatarFrame.size)
|
||||
}
|
||||
|
||||
if self.isShimmering {
|
||||
let shimmerContainerView: UIView
|
||||
let shimmerView: ShimmerEffectForegroundView
|
||||
if let currentContainer = self.shimmerContainerView, let current = self.shimmerView {
|
||||
shimmerContainerView = currentContainer
|
||||
shimmerView = current
|
||||
} else {
|
||||
shimmerContainerView = UIView()
|
||||
shimmerView = ShimmerEffectForegroundView()
|
||||
|
||||
if let outerSnapshot = self.backgroundMaskNode.layer.snapshotContentTree(), let innerSnapshot = self.backgroundMaskNode.layer.snapshotContentTree() {
|
||||
outerSnapshot.backgroundColor = UIColor.black.cgColor
|
||||
|
||||
func tintLayers(_ layer: CALayer, color: UIColor, scale: CGFloat) {
|
||||
if let sublayers = layer.sublayers {
|
||||
for layer in sublayers {
|
||||
if let shapeLayer = layer as? CAShapeLayer {
|
||||
shapeLayer.fillColor = color.cgColor
|
||||
} else {
|
||||
if layer.cornerRadius > 0.0 {
|
||||
layer.backgroundColor = color.cgColor
|
||||
layer.bounds = CGRect(origin: .zero, size: CGSize(width: layer.bounds.width * scale, height: layer.bounds.height))
|
||||
}
|
||||
tintLayers(layer, color: color, scale: scale)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tintLayers(outerSnapshot, color: .white, scale: 1.0)
|
||||
tintLayers(innerSnapshot, color: .black, scale: 1.085)
|
||||
|
||||
outerSnapshot.addSublayer(innerSnapshot)
|
||||
|
||||
innerSnapshot.transform = CATransform3DMakeScale(0.9, 0.9, 1.0)
|
||||
innerSnapshot.position = innerSnapshot.position.offsetBy(dx: 10.0, dy: 10.0)
|
||||
|
||||
if let filter = CALayer.luminanceToAlpha() {
|
||||
outerSnapshot.filters = [filter]
|
||||
}
|
||||
|
||||
shimmerContainerView.layer.mask = outerSnapshot
|
||||
}
|
||||
|
||||
self.shimmerContainerView = shimmerContainerView
|
||||
self.backgroundContainerNode.view.addSubview(shimmerContainerView)
|
||||
|
||||
let shimmerFrame = effectFrame.insetBy(dx: -60.0, dy: 0.0)
|
||||
shimmerView.frame = shimmerFrame
|
||||
shimmerView.update(backgroundColor: .clear, foregroundColor: UIColor.white.withAlphaComponent(0.4), gradientSize: 60.0, globalTimeOffset: false, duration: 2.2, horizontal: true)
|
||||
shimmerView.updateAbsoluteRect(shimmerFrame, within: shimmerFrame.size)
|
||||
|
||||
shimmerContainerView.addSubview(shimmerView)
|
||||
}
|
||||
shimmerContainerView.frame = effectFrame.offsetBy(dx: 10.0, dy: 10.0)
|
||||
} else if let shimmerContainerView = self.shimmerContainerView, let shimmerView = self.shimmerView {
|
||||
self.shimmerContainerView = nil
|
||||
self.shimmerView = nil
|
||||
|
||||
shimmerContainerView.removeFromSuperview()
|
||||
shimmerView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
private var didRequestDismiss = false
|
||||
@ -1064,6 +1134,7 @@ public final class TooltipScreen: ViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
private let isShimmering: Bool
|
||||
private let displayDuration: DisplayDuration
|
||||
private let inset: CGFloat
|
||||
private let cornerRadius: CGFloat?
|
||||
@ -1098,6 +1169,7 @@ public final class TooltipScreen: ViewController {
|
||||
action: TooltipScreen.Action? = nil,
|
||||
location: TooltipScreen.Location,
|
||||
displayDuration: DisplayDuration = .default,
|
||||
isShimmering: Bool = false,
|
||||
inset: CGFloat = 12.0,
|
||||
cornerRadius: CGFloat? = nil,
|
||||
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch,
|
||||
@ -1116,6 +1188,7 @@ public final class TooltipScreen: ViewController {
|
||||
self.action = action
|
||||
self.location = location
|
||||
self.displayDuration = displayDuration
|
||||
self.isShimmering = isShimmering
|
||||
self.inset = inset
|
||||
self.cornerRadius = cornerRadius
|
||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||
@ -1177,7 +1250,7 @@ public final class TooltipScreen: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = TooltipScreenNode(context: self.context, account: self.account, sharedContext: self.sharedContext, text: self.text, textAlignment: self.textAlignment, balancedTextLayout: self.balancedTextLayout, constrainWidth: self.constrainWidth, style: self.style, arrowStyle: self.arrowStyle, icon: self.icon, action: self.action, location: self.location, displayDuration: self.displayDuration, inset: self.inset, cornerRadius: self.cornerRadius, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
self.displayNode = TooltipScreenNode(context: self.context, account: self.account, sharedContext: self.sharedContext, text: self.text, textAlignment: self.textAlignment, balancedTextLayout: self.balancedTextLayout, constrainWidth: self.constrainWidth, style: self.style, arrowStyle: self.arrowStyle, icon: self.icon, action: self.action, location: self.location, displayDuration: self.displayDuration, inset: self.inset, cornerRadius: self.cornerRadius, isShimmering: self.isShimmering, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user