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.Title" = "Enter Password";
|
||||||
"Gift.Withdraw.EnterPassword.Text" = "Please enter your Two-Step Verification password to complete this action.";
|
"Gift.Withdraw.EnterPassword.Text" = "Please enter your Two-Step Verification password to complete this action.";
|
||||||
"Gift.Withdraw.EnterPassword.Done" = "Proceed";
|
"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[1710230755] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
|
||||||
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
|
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
|
||||||
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
||||||
dict[1946579745] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
dict[-1468646731] = { return Api.InputMedia.parse_inputMediaDocument($0) }
|
||||||
dict[-149933938] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
dict[2006319353] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
||||||
dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) }
|
dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) }
|
||||||
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
||||||
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($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[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
|
||||||
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
||||||
dict[-1979852936] = { return Api.InputMedia.parse_inputMediaStory($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[505969924] = { return Api.InputMedia.parse_inputMediaUploadedPhoto($0) }
|
||||||
dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) }
|
dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) }
|
||||||
dict[-1038383031] = { return Api.InputMedia.parse_inputMediaWebPage($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[1313731771] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
||||||
dict[1882335561] = { return Api.MessageMedia.parse_messageMediaContact($0) }
|
dict[1882335561] = { return Api.MessageMedia.parse_messageMediaContact($0) }
|
||||||
dict[1065280907] = { return Api.MessageMedia.parse_messageMediaDice($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[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
|
||||||
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
|
dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) }
|
||||||
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
||||||
|
@ -432,8 +432,8 @@ public extension Api {
|
|||||||
indirect enum InputMedia: TypeConstructorDescription {
|
indirect enum InputMedia: TypeConstructorDescription {
|
||||||
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
|
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
|
||||||
case inputMediaDice(emoticon: String)
|
case inputMediaDice(emoticon: String)
|
||||||
case inputMediaDocument(flags: Int32, id: Api.InputDocument, videoCover: Api.InputPhoto?, ttlSeconds: Int32?, query: String?)
|
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?)
|
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?, videoCover: Api.InputPhoto?, videoTimestamp: Int32?)
|
||||||
case inputMediaEmpty
|
case inputMediaEmpty
|
||||||
case inputMediaGame(id: Api.InputGame)
|
case inputMediaGame(id: Api.InputGame)
|
||||||
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
|
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 inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
|
||||||
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
|
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
|
||||||
case inputMediaStory(peer: Api.InputPeer, id: Int32)
|
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 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 inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
|
||||||
case inputMediaWebPage(flags: Int32, url: String)
|
case inputMediaWebPage(flags: Int32, url: String)
|
||||||
@ -466,24 +466,26 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||||
break
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(1946579745)
|
buffer.appendInt32(-1468646731)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
id.serialize(buffer, true)
|
id.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 3) != 0 {videoCover!.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 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
|
||||||
break
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(-149933938)
|
buffer.appendInt32(2006319353)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeString(url, 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 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 2) != 0 {videoCover!.serialize(buffer, true)}
|
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
|
break
|
||||||
case .inputMediaEmpty:
|
case .inputMediaEmpty:
|
||||||
if boxed {
|
if boxed {
|
||||||
@ -582,9 +584,9 @@ public extension Api {
|
|||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
serializeInt32(id, buffer: buffer, boxed: false)
|
serializeInt32(id, buffer: buffer, boxed: false)
|
||||||
break
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(-264125395)
|
buffer.appendInt32(58495792)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
file.serialize(buffer, true)
|
file.serialize(buffer, true)
|
||||||
@ -601,6 +603,7 @@ public extension Api {
|
|||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 6) != 0 {videoCover!.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)}
|
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
|
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)])
|
return ("inputMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any)])
|
||||||
case .inputMediaDice(let emoticon):
|
case .inputMediaDice(let emoticon):
|
||||||
return ("inputMediaDice", [("emoticon", emoticon as Any)])
|
return ("inputMediaDice", [("emoticon", emoticon as Any)])
|
||||||
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):
|
||||||
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
|
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):
|
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)])
|
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any), ("videoCover", videoCover as Any), ("videoTimestamp", videoTimestamp as Any)])
|
||||||
case .inputMediaEmpty:
|
case .inputMediaEmpty:
|
||||||
return ("inputMediaEmpty", [])
|
return ("inputMediaEmpty", [])
|
||||||
case .inputMediaGame(let id):
|
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)])
|
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):
|
case .inputMediaStory(let peer, let id):
|
||||||
return ("inputMediaStory", [("peer", peer as Any), ("id", id as Any)])
|
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):
|
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), ("ttlSeconds", ttlSeconds as Any)])
|
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):
|
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)])
|
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):
|
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
|
_3 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||||
} }
|
} }
|
||||||
var _4: Int32?
|
var _4: Int32?
|
||||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt32() }
|
||||||
var _5: String?
|
var _5: Int32?
|
||||||
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
|
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 _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil
|
||||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
|
||||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||||
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, videoCover: _3, ttlSeconds: _4, query: _5)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||||
|
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, videoCover: _3, videoTimestamp: _4, ttlSeconds: _5, query: _6)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -747,12 +753,15 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||||
_4 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
_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 _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 {
|
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||||
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3, videoCover: _4)
|
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||||
|
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3, videoCover: _4, videoTimestamp: _5)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -987,7 +996,9 @@ public extension Api {
|
|||||||
_7 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
_7 = Api.parse(reader, signature: signature) as? Api.InputPhoto
|
||||||
} }
|
} }
|
||||||
var _8: Int32?
|
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 _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
|
||||||
@ -995,9 +1006,10 @@ public extension Api {
|
|||||||
let _c5 = _5 != nil
|
let _c5 = _5 != nil
|
||||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||||
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
||||||
let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil
|
let _c8 = (Int(_1!) & Int(1 << 7) == 0) || _8 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
|
||||||
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, videoCover: _7, ttlSeconds: _8)
|
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 {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -710,7 +710,7 @@ public extension Api {
|
|||||||
indirect enum MessageMedia: TypeConstructorDescription {
|
indirect enum MessageMedia: TypeConstructorDescription {
|
||||||
case messageMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String, userId: Int64)
|
case messageMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String, userId: Int64)
|
||||||
case messageMediaDice(value: Int32, emoticon: String)
|
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 messageMediaEmpty
|
||||||
case messageMediaGame(game: Api.Game)
|
case messageMediaGame(game: Api.Game)
|
||||||
case messageMediaGeo(geo: Api.GeoPoint)
|
case messageMediaGeo(geo: Api.GeoPoint)
|
||||||
@ -745,9 +745,9 @@ public extension Api {
|
|||||||
serializeInt32(value, buffer: buffer, boxed: false)
|
serializeInt32(value, buffer: buffer, boxed: false)
|
||||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||||
break
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(-608307692)
|
buffer.appendInt32(1389939929)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)}
|
||||||
@ -757,6 +757,7 @@ public extension Api {
|
|||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 9) != 0 {videoCover!.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)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .messageMediaEmpty:
|
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)])
|
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):
|
case .messageMediaDice(let value, let emoticon):
|
||||||
return ("messageMediaDice", [("value", value as Any), ("emoticon", emoticon as Any)])
|
return ("messageMediaDice", [("value", value as Any), ("emoticon", emoticon as Any)])
|
||||||
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):
|
||||||
return ("messageMediaDocument", [("flags", flags as Any), ("document", document as Any), ("altDocuments", altDocuments as Any), ("videoCover", videoCover as Any), ("ttlSeconds", ttlSeconds as Any)])
|
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:
|
case .messageMediaEmpty:
|
||||||
return ("messageMediaEmpty", [])
|
return ("messageMediaEmpty", [])
|
||||||
case .messageMediaGame(let game):
|
case .messageMediaGame(let game):
|
||||||
@ -996,14 +997,17 @@ public extension Api {
|
|||||||
_4 = Api.parse(reader, signature: signature) as? Api.Photo
|
_4 = Api.parse(reader, signature: signature) as? Api.Photo
|
||||||
} }
|
} }
|
||||||
var _5: Int32?
|
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 _c1 = _1 != nil
|
||||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil
|
||||||
let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil
|
let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil
|
||||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
let _c5 = (Int(_1!) & Int(1 << 10) == 0) || _5 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||||
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, videoCover: _4, ttlSeconds: _5)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||||
|
return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, altDocuments: _3, videoCover: _4, videoTimestamp: _5, ttlSeconds: _6)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -350,7 +350,8 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
|
|||||||
case let .messageMediaGeoLive(_, geo, heading, period, proximityNotificationRadius):
|
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)
|
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)
|
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 document = document {
|
||||||
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto) {
|
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto) {
|
||||||
return (mediaFile, ttlSeconds, (flags & (1 << 3)) != 0, (flags & (1 << 4)) != 0, nil)
|
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
|
|> mapToSignal { validatedResource -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||||
if let validatedResource = validatedResource.updatedResource as? TelegramCloudMediaResourceWithFileReference, let reference = validatedResource.fileReference {
|
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 {
|
} else {
|
||||||
return .fail(.generic)
|
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 {
|
} 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)
|
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)))
|
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|
||||||
|> then(
|
|> 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
|
referenceKey = key
|
||||||
@ -1122,11 +1122,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ttlSeconds != nil {
|
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 {
|
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))
|
return .single(.content(resultInfo))
|
||||||
}
|
}
|
||||||
@ -1137,11 +1137,11 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
|||||||
|> mapError { _ -> PendingMessageUploadError in }
|
|> mapError { _ -> PendingMessageUploadError in }
|
||||||
|> mapToSignal { inputPeer -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
|> mapToSignal { inputPeer -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||||
if let inputPeer = inputPeer {
|
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 }
|
|> mapError { _ -> PendingMessageUploadError in return .generic }
|
||||||
|> mapToSignal { result -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
|> mapToSignal { result -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||||
switch result {
|
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 {
|
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 flags: Int32 = 0
|
||||||
var ttlSeconds: Int32?
|
var ttlSeconds: Int32?
|
||||||
@ -1156,7 +1156,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
|||||||
flags |= (1 << 3)
|
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 {
|
if let _ = ttlSeconds {
|
||||||
return .single(result)
|
return .single(result)
|
||||||
} else {
|
} else {
|
||||||
|
@ -702,7 +702,7 @@ private func uploadedFile(account: Account, data: Data, mimeType: String, attrib
|
|||||||
|> map { next -> UploadMediaEvent in
|
|> map { next -> UploadMediaEvent in
|
||||||
switch next {
|
switch next {
|
||||||
case let .inputFile(inputFile):
|
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:
|
case .inputSecretFile:
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
case let .progress(progress):
|
case let .progress(progress):
|
||||||
|
@ -158,11 +158,11 @@ public func standaloneUploadedFile(postbox: Postbox, network: Network, peerId: P
|
|||||||
if let _ = thumbnailFile {
|
if let _ = thumbnailFile {
|
||||||
flags |= 1 << 2
|
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 }
|
|> mapError { _ -> StandaloneUploadMediaError in return .generic }
|
||||||
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
|> mapToSignal { media -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||||
switch media {
|
switch media {
|
||||||
case let .messageMediaDocument(_, document, altDocuments, _, _):
|
case let .messageMediaDocument(_, document, altDocuments, _, _, _):
|
||||||
if let document = document {
|
if let document = document {
|
||||||
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments) {
|
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments) {
|
||||||
return .single(.result(.media(.standalone(media: mediaFile))))
|
return .single(.result(.media(.standalone(media: mediaFile))))
|
||||||
|
@ -52,7 +52,7 @@ extension Api.MessageMedia {
|
|||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case let .messageMediaDocument(_, document, _, _, _):
|
case let .messageMediaDocument(_, document, _, _, _, _):
|
||||||
if let document = document {
|
if let document = document {
|
||||||
return collectPreCachedResources(for: document)
|
return collectPreCachedResources(for: document)
|
||||||
}
|
}
|
||||||
@ -626,14 +626,14 @@ extension Api.EncryptedMessage {
|
|||||||
extension Api.InputMedia {
|
extension Api.InputMedia {
|
||||||
func withUpdatedStickers(_ stickers: [Api.InputDocument]?) -> Api.InputMedia {
|
func withUpdatedStickers(_ stickers: [Api.InputDocument]?) -> Api.InputMedia {
|
||||||
switch self {
|
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 flags = flags
|
||||||
var attributes = attributes
|
var attributes = attributes
|
||||||
if let _ = stickers {
|
if let _ = stickers {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
attributes.append(.documentAttributeHasStickers)
|
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):
|
case let .inputMediaUploadedPhoto(flags, file, _, ttlSeconds):
|
||||||
var flags = flags
|
var flags = flags
|
||||||
if let _ = stickers {
|
if let _ = stickers {
|
||||||
|
@ -153,7 +153,7 @@ public extension TelegramEngine {
|
|||||||
default:
|
default:
|
||||||
break
|
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):
|
case let .progress(value):
|
||||||
return .single(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(.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))
|
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 {
|
} 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 {
|
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(.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))
|
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 {
|
} 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
|
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 {
|
if let result = result, case let .content(uploadedContent) = result, case let .media(media, _) = uploadedContent.content {
|
||||||
inputMedia = media
|
inputMedia = media
|
||||||
} else if case let .existing(media) = media, let file = media as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
|
} 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
|
updatingCoverTime = true
|
||||||
} else {
|
} else {
|
||||||
inputMedia = nil
|
inputMedia = nil
|
||||||
@ -2099,7 +2099,7 @@ extension Stories.StoredItem {
|
|||||||
|
|
||||||
var parsedAlternativeMedia: [Media] = []
|
var parsedAlternativeMedia: [Media] = []
|
||||||
switch media {
|
switch media {
|
||||||
case let .messageMediaDocument(_, _, altDocuments, _, _):
|
case let .messageMediaDocument(_, _, altDocuments, _, _, _):
|
||||||
if let altDocuments {
|
if let altDocuments {
|
||||||
parsedAlternativeMedia = altDocuments.compactMap { telegramMediaFileFromApiDocument($0, 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(.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))
|
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 {
|
} 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 cacheDisposable = MetaDisposable()
|
||||||
private let actionDisposable = 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 gifts: [ProfileGiftsContext.State.StarGift] = []
|
||||||
|
private var filteredGifts: [ProfileGiftsContext.State.StarGift] = []
|
||||||
private var count: Int32?
|
private var count: Int32?
|
||||||
private var dataState: ProfileGiftsContext.State.DataState = .ready(canLoadMore: true, nextOffset: nil)
|
private var dataState: ProfileGiftsContext.State.DataState = .ready(canLoadMore: true, nextOffset: nil)
|
||||||
private var notificationsEnabled: Bool?
|
private var notificationsEnabled: Bool?
|
||||||
@ -1111,13 +1114,47 @@ private final class ProfileGiftsContextImpl {
|
|||||||
self.pushState()
|
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() {
|
private func pushState() {
|
||||||
self._state = 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.stateValue.set(.single(ProfileGiftsContext.State(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 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 State: Equatable {
|
||||||
public struct StarGift: Equatable, Codable {
|
public struct StarGift: Equatable, Codable {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
@ -1273,6 +1310,9 @@ public final class ProfileGiftsContext {
|
|||||||
case ready(canLoadMore: Bool, nextOffset: String?)
|
case ready(canLoadMore: Bool, nextOffset: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public var filter: Filters
|
||||||
|
public var sorting: Sorting
|
||||||
public var gifts: [ProfileGiftsContext.State.StarGift]
|
public var gifts: [ProfileGiftsContext.State.StarGift]
|
||||||
public var count: Int32?
|
public var count: Int32?
|
||||||
public var dataState: ProfileGiftsContext.State.DataState
|
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? {
|
public var currentState: ProfileGiftsContext.State? {
|
||||||
var state: ProfileGiftsContext.State?
|
var state: ProfileGiftsContext.State?
|
||||||
self.impl.syncWith { impl in
|
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(.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))
|
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 }
|
|> mapError { _ -> UploadStickerError in return .generic }
|
||||||
|> mapToSignal { media -> Signal<UploadStickerStatus, UploadStickerError> in
|
|> mapToSignal { media -> Signal<UploadStickerStatus, UploadStickerError> in
|
||||||
switch media {
|
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 {
|
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)
|
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) }) {
|
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 dismissedBusinessChatbotsBadge = 74
|
||||||
case captionAboveMediaTooltip = 75
|
case captionAboveMediaTooltip = 75
|
||||||
case channelSendGiftTooltip = 76
|
case channelSendGiftTooltip = 76
|
||||||
|
case starGiftWearTips = 77
|
||||||
|
|
||||||
var key: ValueBoxKey {
|
var key: ValueBoxKey {
|
||||||
let v = ValueBoxKey(length: 4)
|
let v = ValueBoxKey(length: 4)
|
||||||
@ -549,6 +550,10 @@ private struct ApplicationSpecificNoticeKeys {
|
|||||||
static func channelSendGiftTooltip() -> NoticeEntryKey {
|
static func channelSendGiftTooltip() -> NoticeEntryKey {
|
||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.channelSendGiftTooltip.key)
|
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 {
|
public struct ApplicationSpecificNotice {
|
||||||
@ -2335,4 +2340,31 @@ public struct ApplicationSpecificNotice {
|
|||||||
return Int(previousValue)
|
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)
|
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, _, _, _, _, _, _, _, _):
|
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, _, _, _):
|
||||||
if case let .unique(gift) = gift {
|
if case let .unique(gift) = gift {
|
||||||
if !forAdditionalServiceMessage {
|
if !forAdditionalServiceMessage && !"".isEmpty {
|
||||||
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
|
||||||
} else if let messagePeer = message.peers[message.id.peerId] {
|
} else if let messagePeer = message.peers[message.id.peerId] {
|
||||||
let peerName = EnginePeer(messagePeer).compactDisplayTitle
|
let peerName = EnginePeer(messagePeer).compactDisplayTitle
|
||||||
|
@ -20,6 +20,7 @@ swift_library(
|
|||||||
"//submodules/AccountContext",
|
"//submodules/AccountContext",
|
||||||
"//submodules/PresentationDataUtils",
|
"//submodules/PresentationDataUtils",
|
||||||
"//submodules/Markdown",
|
"//submodules/Markdown",
|
||||||
|
"//submodules/TelegramNotices",
|
||||||
"//submodules/ComponentFlow",
|
"//submodules/ComponentFlow",
|
||||||
"//submodules/Components/ComponentDisplayAdapters",
|
"//submodules/Components/ComponentDisplayAdapters",
|
||||||
"//submodules/Components/ViewControllerComponent",
|
"//submodules/Components/ViewControllerComponent",
|
||||||
|
@ -31,6 +31,7 @@ import TooltipUI
|
|||||||
import GiftAnimationComponent
|
import GiftAnimationComponent
|
||||||
import LottieComponent
|
import LottieComponent
|
||||||
import ContextUI
|
import ContextUI
|
||||||
|
import TelegramNotices
|
||||||
|
|
||||||
private let modelButtonTag = GenericComponentViewTag()
|
private let modelButtonTag = GenericComponentViewTag()
|
||||||
private let backdropButtonTag = GenericComponentViewTag()
|
private let backdropButtonTag = GenericComponentViewTag()
|
||||||
@ -286,6 +287,25 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
self.updated(transition: .spring(duration: 0.4))
|
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() {
|
func commitUpgrade() {
|
||||||
guard let arguments = self.subject.arguments, let peerId = arguments.peerId, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
guard let arguments = self.subject.arguments, let peerId = arguments.peerId, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
||||||
return
|
return
|
||||||
@ -1117,6 +1137,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if peer.id == component.context.account.peerId, peer.isPremium {
|
if peer.id == component.context.account.peerId, peer.isPremium {
|
||||||
let animationContent: EmojiStatusComponent.Content
|
let animationContent: EmojiStatusComponent.Content
|
||||||
var color: UIColor?
|
var color: UIColor?
|
||||||
|
var statusId: Int64 = 1
|
||||||
if state.pendingWear {
|
if state.pendingWear {
|
||||||
var fileId: Int64?
|
var fileId: Int64?
|
||||||
for attribute in uniqueGift.attributes {
|
for attribute in uniqueGift.attributes {
|
||||||
@ -1128,6 +1149,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let fileId {
|
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))
|
animationContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 18.0, height: 18.0), placeholderColor: theme.list.mediaPlaceholderColor, themeColor: tableLinkColor, loopMode: .count(2))
|
||||||
} else {
|
} else {
|
||||||
animationContent = .premium(color: tableLinkColor)
|
animationContent = .premium(color: tableLinkColor)
|
||||||
@ -1168,7 +1190,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
))
|
))
|
||||||
),
|
),
|
||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
id: AnyHashable(1),
|
id: AnyHashable(statusId),
|
||||||
component: AnyComponent(EmojiStatusComponent(
|
component: AnyComponent(EmojiStatusComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
animationCache: component.context.animationCache,
|
animationCache: component.context.animationCache,
|
||||||
@ -1351,9 +1373,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
action: { [weak state] in
|
action: { [weak state] in
|
||||||
if let state {
|
if let state {
|
||||||
if isWearing {
|
if isWearing {
|
||||||
state.pendingTakeOff = true
|
state.commitTakeOff()
|
||||||
state.pendingWear = false
|
|
||||||
state.updated(transition: .spring(duration: 0.4))
|
|
||||||
|
|
||||||
component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
||||||
} else {
|
} else {
|
||||||
@ -1361,7 +1381,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
controller.dismissAllTooltips()
|
controller.dismissAllTooltips()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
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
|
items: tableItems
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),
|
||||||
transition: .immediate
|
transition: context.transition
|
||||||
)
|
)
|
||||||
context.add(table
|
context.add(table
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0))
|
.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))
|
controller.present(tooltipController, in: .window(.root))
|
||||||
} else {
|
} else {
|
||||||
state.pendingWear = true
|
state.commitWear(uniqueGift)
|
||||||
state.pendingTakeOff = false
|
|
||||||
state.inWearPreview = false
|
|
||||||
state.updated(transition: .spring(duration: 0.4))
|
|
||||||
|
|
||||||
let _ = component.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).start()
|
|
||||||
|
|
||||||
Queue.mainQueue().after(0.2) {
|
Queue.mainQueue().after(0.2) {
|
||||||
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string)
|
||||||
}
|
}
|
||||||
|
@ -440,12 +440,6 @@ 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))
|
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)
|
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)
|
let avatarPatternFrame = CGSize(width: 380.0, height: floor(component.defaultHeight * 1.0)).centered(around: component.avatarCenter)
|
||||||
transition.setFrame(layer: self.avatarBackgroundPatternContentsLayer, frame: avatarPatternFrame)
|
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 {
|
} else if case let .status(status) = component.subject, case let .starGift(_, _, _, _, _, _, _, patternColorValue, _) = status.content {
|
||||||
let patternColor = UIColor(rgb: UInt32(bitPattern: patternColorValue))
|
let patternColor = UIColor(rgb: UInt32(bitPattern: patternColorValue))
|
||||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
|
self.avatarBackgroundPatternContentsLayer.compositingFilter = "overlayBlendMode"
|
||||||
self.avatarBackgroundPatternContentsLayer.colors = [
|
self.avatarBackgroundPatternContentsLayer.colors = [
|
||||||
patternColor.withAlphaComponent(0.6).cgColor,
|
patternColor.withAlphaComponent(0.6).cgColor,
|
||||||
patternColor.withAlphaComponent(0.0).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.6).cgColor,
|
||||||
UIColor(white: 0.0, alpha: 0.0).cgColor
|
UIColor(white: 0.0, alpha: 0.0).cgColor
|
||||||
]
|
]
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
|
self.avatarBackgroundPatternContentsLayer.compositingFilter = nil
|
||||||
let baseWhite: CGFloat = component.isDark ? 0.5 : 0.3
|
let baseWhite: CGFloat = component.isDark ? 0.5 : 0.3
|
||||||
|
@ -282,6 +282,10 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||||||
text = ""
|
text = ""
|
||||||
accessibilityText = presentationData.strings.Story_Privacy_PostStory
|
accessibilityText = presentationData.strings.Story_Privacy_PostStory
|
||||||
icon = PresentationResourcesRootController.navigationPostStoryIcon(presentationData.theme)
|
icon = PresentationResourcesRootController.navigationPostStoryIcon(presentationData.theme)
|
||||||
|
case .sort:
|
||||||
|
text = ""
|
||||||
|
accessibilityText = presentationData.strings.Common_More
|
||||||
|
icon = PresentationResourcesRootController.navigationSortIcon(presentationData.theme)
|
||||||
}
|
}
|
||||||
self.accessibilityLabel = accessibilityText
|
self.accessibilityLabel = accessibilityText
|
||||||
self.containerNode.isGestureEnabled = isGestureEnabled
|
self.containerNode.isGestureEnabled = isGestureEnabled
|
||||||
|
@ -21,6 +21,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
|||||||
case qrCode
|
case qrCode
|
||||||
case moreToSearch
|
case moreToSearch
|
||||||
case postStory
|
case postStory
|
||||||
|
case sort
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||||
|
@ -2306,11 +2306,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
Queue.mainQueue().after(0.2) {
|
Queue.mainQueue().after(0.2) {
|
||||||
backgroundCoverView.animateIn()
|
backgroundCoverView.animateIn()
|
||||||
}
|
}
|
||||||
Queue.mainQueue().after(0.44) {
|
Queue.mainQueue().after(0.5) {
|
||||||
self.invokeDisplayGiftInfo()
|
self.invokeDisplayGiftInfo()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Queue.mainQueue().after(0.44) {
|
Queue.mainQueue().after(0.5) {
|
||||||
self.invokeDisplayGiftInfo()
|
self.invokeDisplayGiftInfo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4430,14 +4430,27 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
case .search, .searchWithTags, .standaloneSearch:
|
case .search, .searchWithTags, .standaloneSearch:
|
||||||
strongSelf.activateSearch()
|
strongSelf.activateSearch()
|
||||||
case .more:
|
case .more:
|
||||||
if let currentPaneKey = strongSelf.paneContainerNode.currentPaneKey, case .savedMessagesChats = currentPaneKey {
|
guard let source else {
|
||||||
if let controller = strongSelf.controller, let source {
|
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)
|
PeerInfoScreenImpl.openSavedMessagesMoreMenu(context: strongSelf.context, sourceController: controller, isViewingAsTopics: true, sourceView: source.view, gesture: gesture)
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
} else {
|
} 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:
|
case .qrCode:
|
||||||
strongSelf.openQrCode()
|
strongSelf.openQrCode()
|
||||||
@ -4651,6 +4664,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
style: .customBlur(backgroundColor, -4.0),
|
style: .customBlur(backgroundColor, -4.0),
|
||||||
arrowStyle: .small,
|
arrowStyle: .small,
|
||||||
location: .point(sourceRect, .bottom),
|
location: .point(sourceRect, .bottom),
|
||||||
|
isShimmering: true,
|
||||||
cornerRadius: 10.0,
|
cornerRadius: 10.0,
|
||||||
shouldDismissOnTouch: { _, _ in
|
shouldDismissOnTouch: { _, _ in
|
||||||
return .dismiss(consume: false)
|
return .dismiss(consume: false)
|
||||||
@ -10884,6 +10898,126 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}), in: .current)
|
}), 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?) {
|
private func displayMediaGalleryContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) {
|
||||||
let peerId = self.peerId
|
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) {
|
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))
|
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:
|
default:
|
||||||
break
|
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/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
|
||||||
"//submodules/Components/BalancedTextComponent",
|
"//submodules/Components/BalancedTextComponent",
|
||||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||||
|
"//submodules/ShimmerEffect",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -18,6 +18,7 @@ import AccountContext
|
|||||||
import Markdown
|
import Markdown
|
||||||
import BalancedTextComponent
|
import BalancedTextComponent
|
||||||
import MultilineTextWithEntitiesComponent
|
import MultilineTextWithEntitiesComponent
|
||||||
|
import ShimmerEffect
|
||||||
|
|
||||||
public enum TooltipActiveTextItem {
|
public enum TooltipActiveTextItem {
|
||||||
case url(String, Bool)
|
case url(String, Bool)
|
||||||
@ -126,6 +127,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private let isShimmering: Bool
|
||||||
private let displayDuration: TooltipScreen.DisplayDuration
|
private let displayDuration: TooltipScreen.DisplayDuration
|
||||||
private let shouldDismissOnTouch: (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch
|
private let shouldDismissOnTouch: (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch
|
||||||
private let requestDismiss: () -> Void
|
private let requestDismiss: () -> Void
|
||||||
@ -149,6 +151,9 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
private var closeButtonNode: HighlightableButtonNode?
|
private var closeButtonNode: HighlightableButtonNode?
|
||||||
private var actionButtonNode: HighlightableButtonNode?
|
private var actionButtonNode: HighlightableButtonNode?
|
||||||
|
|
||||||
|
private var shimmerContainerView: UIView?
|
||||||
|
private var shimmerView: ShimmerEffectForegroundView?
|
||||||
|
|
||||||
private var isArrowInverted: Bool = false
|
private var isArrowInverted: Bool = false
|
||||||
|
|
||||||
private let fontSize: CGFloat
|
private let fontSize: CGFloat
|
||||||
@ -172,6 +177,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
displayDuration: TooltipScreen.DisplayDuration,
|
displayDuration: TooltipScreen.DisplayDuration,
|
||||||
inset: CGFloat = 12.0,
|
inset: CGFloat = 12.0,
|
||||||
cornerRadius: CGFloat? = nil,
|
cornerRadius: CGFloat? = nil,
|
||||||
|
isShimmering: Bool = false,
|
||||||
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?)
|
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?)
|
||||||
{
|
{
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -181,6 +187,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
self.action = action
|
self.action = action
|
||||||
self.location = location
|
self.location = location
|
||||||
self.displayDuration = displayDuration
|
self.displayDuration = displayDuration
|
||||||
|
self.isShimmering = isShimmering
|
||||||
self.inset = inset
|
self.inset = inset
|
||||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||||
self.requestDismiss = requestDismiss
|
self.requestDismiss = requestDismiss
|
||||||
@ -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.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))
|
transition.updateFrame(node: self.backgroundClipNode, frame: CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: backgroundFrame.size))
|
||||||
|
|
||||||
if let effectNode = self.effectNode {
|
|
||||||
let effectFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0)
|
let effectFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0)
|
||||||
|
if let effectNode = self.effectNode {
|
||||||
transition.updateFrame(node: effectNode, frame: effectFrame)
|
transition.updateFrame(node: effectNode, frame: effectFrame)
|
||||||
effectNode.update(size: effectFrame.size, transition: transition)
|
effectNode.update(size: effectFrame.size, transition: transition)
|
||||||
}
|
}
|
||||||
@ -843,6 +850,69 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
transition.updateFrame(node: avatarNode, frame: avatarFrame)
|
transition.updateFrame(node: avatarNode, frame: avatarFrame)
|
||||||
avatarNode.updateSize(size: avatarFrame.size)
|
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
|
private var didRequestDismiss = false
|
||||||
@ -1064,6 +1134,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private let isShimmering: Bool
|
||||||
private let displayDuration: DisplayDuration
|
private let displayDuration: DisplayDuration
|
||||||
private let inset: CGFloat
|
private let inset: CGFloat
|
||||||
private let cornerRadius: CGFloat?
|
private let cornerRadius: CGFloat?
|
||||||
@ -1098,6 +1169,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
action: TooltipScreen.Action? = nil,
|
action: TooltipScreen.Action? = nil,
|
||||||
location: TooltipScreen.Location,
|
location: TooltipScreen.Location,
|
||||||
displayDuration: DisplayDuration = .default,
|
displayDuration: DisplayDuration = .default,
|
||||||
|
isShimmering: Bool = false,
|
||||||
inset: CGFloat = 12.0,
|
inset: CGFloat = 12.0,
|
||||||
cornerRadius: CGFloat? = nil,
|
cornerRadius: CGFloat? = nil,
|
||||||
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch,
|
shouldDismissOnTouch: @escaping (CGPoint, CGRect) -> TooltipScreen.DismissOnTouch,
|
||||||
@ -1116,6 +1188,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
self.action = action
|
self.action = action
|
||||||
self.location = location
|
self.location = location
|
||||||
self.displayDuration = displayDuration
|
self.displayDuration = displayDuration
|
||||||
|
self.isShimmering = isShimmering
|
||||||
self.inset = inset
|
self.inset = inset
|
||||||
self.cornerRadius = cornerRadius
|
self.cornerRadius = cornerRadius
|
||||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||||
@ -1177,7 +1250,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
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 {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user