mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 21:16:35 +00:00
Merge commit 'a91658373baee67ebcef073a68b21b87787ca6eb'
This commit is contained in:
commit
73b67e9a4e
@ -217,9 +217,9 @@ public enum DeviceMetrics: CaseIterable, Equatable {
|
|||||||
case .iPhone14Pro, .iPhone14ProMax:
|
case .iPhone14Pro, .iPhone14ProMax:
|
||||||
return 55.0
|
return 55.0
|
||||||
case .iPhone16Pro, .iPhone16ProMax:
|
case .iPhone16Pro, .iPhone16ProMax:
|
||||||
return 55.0
|
return 62.0
|
||||||
case .iPhoneAir:
|
case .iPhoneAir:
|
||||||
return 55.0
|
return 62.0
|
||||||
case let .unknown(_, _, _, screenCornerRadius):
|
case let .unknown(_, _, _, screenCornerRadius):
|
||||||
return screenCornerRadius
|
return screenCornerRadius
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -965,7 +965,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||||
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
|
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
|
||||||
dict[-2136190013] = { return Api.StarGift.parse_starGift($0) }
|
dict[-2136190013] = { return Api.StarGift.parse_starGift($0) }
|
||||||
dict[973640632] = { return Api.StarGift.parse_starGiftUnique($0) }
|
dict[-1329630181] = { return Api.StarGift.parse_starGiftUnique($0) }
|
||||||
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
||||||
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
||||||
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
||||||
|
|||||||
@ -289,7 +289,7 @@ public extension Api {
|
|||||||
public extension Api {
|
public extension Api {
|
||||||
enum StarGift: TypeConstructorDescription {
|
enum StarGift: TypeConstructorDescription {
|
||||||
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, availabilityResale: Int64?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?, resellMinStars: Int64?, title: String?, releasedBy: Api.Peer?, perUserTotal: Int32?, perUserRemains: Int32?, lockedUntilDate: Int32?)
|
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, availabilityResale: Int64?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?, resellMinStars: Int64?, title: String?, releasedBy: Api.Peer?, perUserTotal: Int32?, perUserRemains: Int32?, lockedUntilDate: Int32?)
|
||||||
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, themePeer: Api.Peer?, peerColor: Api.PeerColor?)
|
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, themePeer: Api.Peer?, peerColor: Api.PeerColor?, hostId: Api.Peer?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -315,9 +315,9 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserRemains!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserRemains!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(lockedUntilDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(lockedUntilDate!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor):
|
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(973640632)
|
buffer.appendInt32(-1329630181)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt64(id, buffer: buffer, boxed: false)
|
serializeInt64(id, buffer: buffer, boxed: false)
|
||||||
@ -346,6 +346,7 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 8) != 0 {serializeString(valueCurrency!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeString(valueCurrency!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 10) != 0 {themePeer!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 10) != 0 {themePeer!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 11) != 0 {peerColor!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 11) != 0 {peerColor!.serialize(buffer, true)}
|
||||||
|
if Int(flags) & Int(1 << 12) != 0 {hostId!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,8 +355,8 @@ public extension Api {
|
|||||||
switch self {
|
switch self {
|
||||||
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate):
|
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate):
|
||||||
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("availabilityResale", availabilityResale as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any), ("resellMinStars", resellMinStars as Any), ("title", title as Any), ("releasedBy", releasedBy as Any), ("perUserTotal", perUserTotal as Any), ("perUserRemains", perUserRemains as Any), ("lockedUntilDate", lockedUntilDate as Any)])
|
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("availabilityResale", availabilityResale as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any), ("resellMinStars", resellMinStars as Any), ("title", title as Any), ("releasedBy", releasedBy as Any), ("perUserTotal", perUserTotal as Any), ("perUserRemains", perUserRemains as Any), ("lockedUntilDate", lockedUntilDate as Any)])
|
||||||
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor):
|
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
|
||||||
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any)])
|
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any), ("hostId", hostId as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +474,10 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 11) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 11) != 0 {if let signature = reader.readInt32() {
|
||||||
_19 = Api.parse(reader, signature: signature) as? Api.PeerColor
|
_19 = Api.parse(reader, signature: signature) as? Api.PeerColor
|
||||||
} }
|
} }
|
||||||
|
var _20: Api.Peer?
|
||||||
|
if Int(_1!) & Int(1 << 12) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_20 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
@ -492,8 +497,9 @@ public extension Api {
|
|||||||
let _c17 = (Int(_1!) & Int(1 << 8) == 0) || _17 != nil
|
let _c17 = (Int(_1!) & Int(1 << 8) == 0) || _17 != nil
|
||||||
let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil
|
let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil
|
||||||
let _c19 = (Int(_1!) & Int(1 << 11) == 0) || _19 != nil
|
let _c19 = (Int(_1!) & Int(1 << 11) == 0) || _19 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 {
|
let _c20 = (Int(_1!) & Int(1 << 12) == 0) || _20 != nil
|
||||||
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, themePeer: _18, peerColor: _19)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 {
|
||||||
|
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, themePeer: _18, peerColor: _19, hostId: _20)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -520,9 +520,10 @@ final class VideoChatMicButtonComponent: Component {
|
|||||||
var titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) * 0.5), y: size.height + 16.0), size: titleSize)
|
var titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) * 0.5), y: size.height + 16.0), size: titleSize)
|
||||||
if component.isCompact {
|
if component.isCompact {
|
||||||
titleFrame.origin.y -= 11.0
|
titleFrame.origin.y -= 11.0
|
||||||
}
|
} else {
|
||||||
if subtitleText != nil {
|
if subtitleText != nil {
|
||||||
titleFrame.origin.y -= 5.0
|
titleFrame.origin.y -= 5.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let titleView = self.title.view {
|
if let titleView = self.title.view {
|
||||||
if titleView.superview == nil {
|
if titleView.superview == nil {
|
||||||
|
|||||||
@ -2034,7 +2034,7 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
||||||
let value: CGFloat = 1.0 - Display.bezierPoint(0.42, 0.0, 0.58, 1.0, step)
|
let value: CGFloat = 1.0 - Display.bezierPoint(0.42, 0.0, 0.58, 1.0, step)
|
||||||
return UIColor(white: 0.0, alpha: baseGradientAlpha * value).multipliedWith(.red)
|
return UIColor(white: 0.0, alpha: baseGradientAlpha * value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let locations = (0 ..< numSteps).map { i -> CGFloat in
|
let locations = (0 ..< numSteps).map { i -> CGFloat in
|
||||||
|
|||||||
@ -2206,7 +2206,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
let landscapeControlsWidth: CGFloat = 104.0
|
let landscapeControlsWidth: CGFloat = 104.0
|
||||||
var landscapeControlsOffsetX: CGFloat = 0.0
|
var landscapeControlsOffsetX: CGFloat = 0.0
|
||||||
let landscapeControlsSpacing: CGFloat = 30.0
|
let landscapeControlsSpacing: CGFloat = 20.0
|
||||||
|
|
||||||
var leftInset: CGFloat = max(environment.safeInsets.left, 16.0)
|
var leftInset: CGFloat = max(environment.safeInsets.left, 16.0)
|
||||||
|
|
||||||
@ -2554,11 +2554,58 @@ final class VideoChatScreenComponent: Component {
|
|||||||
self.encryptionKeyBackground = nil
|
self.encryptionKeyBackground = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let videoButtonContent: VideoChatActionButtonComponent.Content?
|
||||||
|
let videoControlButtonContent: VideoChatActionButtonComponent.Content
|
||||||
|
|
||||||
|
var buttonAudio: VideoChatActionButtonComponent.Content.Audio = .speaker
|
||||||
|
var buttonIsEnabled = false
|
||||||
|
if let (availableOutputs, maybeCurrentOutput) = self.audioOutputState, let currentOutput = maybeCurrentOutput {
|
||||||
|
buttonIsEnabled = availableOutputs.count > 1
|
||||||
|
switch currentOutput {
|
||||||
|
case .builtin:
|
||||||
|
buttonAudio = .builtin
|
||||||
|
case .speaker:
|
||||||
|
buttonAudio = .speaker
|
||||||
|
case .headphones:
|
||||||
|
buttonAudio = .headphones
|
||||||
|
case let .port(port):
|
||||||
|
var type: VideoChatActionButtonComponent.Content.BluetoothType = .generic
|
||||||
|
let portName = port.name.lowercased()
|
||||||
|
if portName.contains("airpods max") {
|
||||||
|
type = .airpodsMax
|
||||||
|
} else if portName.contains("airpods pro") {
|
||||||
|
type = .airpodsPro
|
||||||
|
} else if portName.contains("airpods") {
|
||||||
|
type = .airpods
|
||||||
|
}
|
||||||
|
buttonAudio = .bluetooth(type)
|
||||||
|
}
|
||||||
|
if availableOutputs.count <= 1 {
|
||||||
|
buttonAudio = .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let callState = self.callState, let muteState = callState.muteState, !muteState.canUnmute {
|
||||||
|
videoButtonContent = nil
|
||||||
|
videoControlButtonContent = .audio(audio: buttonAudio, isEnabled: buttonIsEnabled)
|
||||||
|
} else {
|
||||||
|
let isVideoActive = self.callState?.isMyVideoActive ?? false
|
||||||
|
videoButtonContent = .video(isActive: isVideoActive)
|
||||||
|
if isVideoActive {
|
||||||
|
videoControlButtonContent = .rotateCamera
|
||||||
|
} else {
|
||||||
|
videoControlButtonContent = .audio(audio: buttonAudio, isEnabled: buttonIsEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let actionButtonDiameter: CGFloat = 56.0
|
let actionButtonDiameter: CGFloat = 56.0
|
||||||
let expandedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter
|
let expandedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter
|
||||||
let collapsedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter // 116.0
|
let collapsedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter // 116.0
|
||||||
|
|
||||||
let buttonsWidth: CGFloat = actionButtonDiameter * 5.0
|
let buttonsCount = videoButtonContent == nil ? 4 : 5
|
||||||
|
|
||||||
|
let buttonsWidth: CGFloat = actionButtonDiameter * CGFloat(buttonsCount)
|
||||||
let remainingButtonsSpace: CGFloat
|
let remainingButtonsSpace: CGFloat
|
||||||
if isTwoColumnLayout {
|
if isTwoColumnLayout {
|
||||||
remainingButtonsSpace = mainColumnWidth - buttonsWidth
|
remainingButtonsSpace = mainColumnWidth - buttonsWidth
|
||||||
@ -2566,7 +2613,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
remainingButtonsSpace = availableSize.width - 16.0 * 2.0 - buttonsWidth
|
remainingButtonsSpace = availableSize.width - 16.0 * 2.0 - buttonsWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
let actionMicrophoneButtonSpacing = min(25.0, floor(remainingButtonsSpace * 0.25))
|
let actionMicrophoneButtonSpacing = min(33.0, floor(remainingButtonsSpace / CGFloat(buttonsCount - 1)))
|
||||||
|
|
||||||
var collapsedMicrophoneButtonFrame: CGRect = CGRect(origin: CGPoint(x: floor((availableSize.width - collapsedMicrophoneButtonDiameter) * 0.5), y: availableSize.height - 48.0 - environment.safeInsets.bottom - collapsedMicrophoneButtonDiameter), size: CGSize(width: collapsedMicrophoneButtonDiameter, height: collapsedMicrophoneButtonDiameter))
|
var collapsedMicrophoneButtonFrame: CGRect = CGRect(origin: CGPoint(x: floor((availableSize.width - collapsedMicrophoneButtonDiameter) * 0.5), y: availableSize.height - 48.0 - environment.safeInsets.bottom - collapsedMicrophoneButtonDiameter), size: CGSize(width: collapsedMicrophoneButtonDiameter, height: collapsedMicrophoneButtonDiameter))
|
||||||
if self.isAnimatedOutFromPrivateCall {
|
if self.isAnimatedOutFromPrivateCall {
|
||||||
@ -2607,7 +2654,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let microphoneButtonFrame: CGRect
|
var microphoneButtonFrame: CGRect
|
||||||
if areButtonsCollapsed {
|
if areButtonsCollapsed {
|
||||||
microphoneButtonFrame = expandedMicrophoneButtonFrame
|
microphoneButtonFrame = expandedMicrophoneButtonFrame
|
||||||
} else {
|
} else {
|
||||||
@ -2631,25 +2678,40 @@ final class VideoChatScreenComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
expandedParticipantsClippingY = expandedMicrophoneButtonFrame.minY - 24.0
|
expandedParticipantsClippingY = expandedMicrophoneButtonFrame.minY - 24.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let actionButtonSize = CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
let actionButtonSize = CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
||||||
var firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - (actionButtonDiameter + actionMicrophoneButtonSpacing) * 2.0, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
var firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - (actionButtonDiameter + actionMicrophoneButtonSpacing) * 2.0, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
||||||
var secondActionButtonFrame = CGRect(origin: CGPoint(x: firstActionButtonFrame.minX + actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
var secondActionButtonFrame = CGRect(origin: CGPoint(x: firstActionButtonFrame.minX + actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
||||||
|
|
||||||
var fourthActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + 2.0 * actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
var fourthActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + 2.0 * actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
||||||
var thirdActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
var thirdActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
||||||
|
|
||||||
if buttonsOnTheSide {
|
if buttonsCount == 4 {
|
||||||
secondActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
if buttonsOnTheSide {
|
||||||
secondActionButtonFrame.origin.y = microphoneButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
firstActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
secondActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
thirdActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
fourthActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
|
||||||
|
microphoneButtonFrame.origin.y = availableSize.height * 0.5 - landscapeControlsSpacing * 0.5 - actionButtonDiameter
|
||||||
|
firstActionButtonFrame.origin.y = microphoneButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
||||||
|
thirdActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing
|
||||||
|
fourthActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing + actionButtonDiameter + landscapeControlsSpacing
|
||||||
|
} else {
|
||||||
|
microphoneButtonFrame.origin.x = availableSize.width * 0.5 - actionMicrophoneButtonSpacing * 0.5 - actionButtonDiameter
|
||||||
|
firstActionButtonFrame.origin.x = microphoneButtonFrame.minX - actionMicrophoneButtonSpacing - actionButtonDiameter
|
||||||
|
thirdActionButtonFrame.origin.x = microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing
|
||||||
|
fourthActionButtonFrame.origin.x = microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing + actionButtonDiameter + actionMicrophoneButtonSpacing
|
||||||
|
}
|
||||||
|
} else if buttonsOnTheSide {
|
||||||
firstActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
firstActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
firstActionButtonFrame.origin.y = secondActionButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
secondActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
|
||||||
thirdActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
thirdActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
thirdActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing
|
|
||||||
|
|
||||||
fourthActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
fourthActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
|
||||||
|
secondActionButtonFrame.origin.y = microphoneButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
||||||
|
firstActionButtonFrame.origin.y = secondActionButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
||||||
|
thirdActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing
|
||||||
fourthActionButtonFrame.origin.y = thirdActionButtonFrame.maxY + landscapeControlsSpacing
|
fourthActionButtonFrame.origin.y = thirdActionButtonFrame.maxY + landscapeControlsSpacing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3065,84 +3127,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
transition.setBounds(view: microphoneButtonView, bounds: CGRect(origin: CGPoint(), size: microphoneButtonFrame.size))
|
transition.setBounds(view: microphoneButtonView, bounds: CGRect(origin: CGPoint(), size: microphoneButtonFrame.size))
|
||||||
}
|
}
|
||||||
|
|
||||||
let videoButtonContent: VideoChatActionButtonComponent.Content
|
|
||||||
let videoControlButtonContent: VideoChatActionButtonComponent.Content
|
|
||||||
|
|
||||||
var buttonAudio: VideoChatActionButtonComponent.Content.Audio = .speaker
|
|
||||||
var buttonIsEnabled = false
|
|
||||||
if let (availableOutputs, maybeCurrentOutput) = self.audioOutputState, let currentOutput = maybeCurrentOutput {
|
|
||||||
buttonIsEnabled = availableOutputs.count > 1
|
|
||||||
switch currentOutput {
|
|
||||||
case .builtin:
|
|
||||||
buttonAudio = .builtin
|
|
||||||
case .speaker:
|
|
||||||
buttonAudio = .speaker
|
|
||||||
case .headphones:
|
|
||||||
buttonAudio = .headphones
|
|
||||||
case let .port(port):
|
|
||||||
var type: VideoChatActionButtonComponent.Content.BluetoothType = .generic
|
|
||||||
let portName = port.name.lowercased()
|
|
||||||
if portName.contains("airpods max") {
|
|
||||||
type = .airpodsMax
|
|
||||||
} else if portName.contains("airpods pro") {
|
|
||||||
type = .airpodsPro
|
|
||||||
} else if portName.contains("airpods") {
|
|
||||||
type = .airpods
|
|
||||||
}
|
|
||||||
buttonAudio = .bluetooth(type)
|
|
||||||
}
|
|
||||||
if availableOutputs.count <= 1 {
|
|
||||||
buttonAudio = .none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let callState = self.callState, let muteState = callState.muteState, !muteState.canUnmute {
|
|
||||||
videoButtonContent = .audio(audio: buttonAudio, isEnabled: buttonIsEnabled)
|
|
||||||
videoControlButtonContent = .audio(audio: buttonAudio, isEnabled: buttonIsEnabled)
|
|
||||||
} else {
|
|
||||||
let isVideoActive = self.callState?.isMyVideoActive ?? false
|
|
||||||
videoButtonContent = .video(isActive: isVideoActive)
|
|
||||||
if isVideoActive {
|
|
||||||
videoControlButtonContent = .rotateCamera
|
|
||||||
} else {
|
|
||||||
videoControlButtonContent = .audio(audio: buttonAudio, isEnabled: buttonIsEnabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = self.videoButton.update(
|
|
||||||
transition: transition,
|
|
||||||
component: AnyComponent(PlainButtonComponent(
|
|
||||||
content: AnyComponent(VideoChatActionButtonComponent(
|
|
||||||
strings: environment.strings,
|
|
||||||
content: videoButtonContent,
|
|
||||||
microphoneState: actionButtonMicrophoneState,
|
|
||||||
isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide
|
|
||||||
)),
|
|
||||||
effectAlignment: .center,
|
|
||||||
action: { [weak self] in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if let callState = self.callState, let muteState = callState.muteState, !muteState.canUnmute {
|
|
||||||
self.onAudioRoutePressed()
|
|
||||||
} else {
|
|
||||||
self.onCameraPressed()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
animateAlpha: false
|
|
||||||
)),
|
|
||||||
environment: {},
|
|
||||||
containerSize: CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
|
||||||
)
|
|
||||||
|
|
||||||
if let videoButtonView = self.videoButton.view {
|
|
||||||
if videoButtonView.superview == nil {
|
|
||||||
self.containerView.addSubview(videoButtonView)
|
|
||||||
}
|
|
||||||
transition.setPosition(view: videoButtonView, position: secondActionButtonFrame.center)
|
|
||||||
transition.setBounds(view: videoButtonView, bounds: CGRect(origin: CGPoint(), size: secondActionButtonFrame.size))
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = self.speakerButton.update(
|
let _ = self.speakerButton.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(PlainButtonComponent(
|
component: AnyComponent(PlainButtonComponent(
|
||||||
@ -3178,6 +3163,47 @@ final class VideoChatScreenComponent: Component {
|
|||||||
transition.setBounds(view: speakerButtonView, bounds: CGRect(origin: CGPoint(), size: firstActionButtonFrame.size))
|
transition.setBounds(view: speakerButtonView, bounds: CGRect(origin: CGPoint(), size: firstActionButtonFrame.size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let videoButtonContent {
|
||||||
|
let _ = self.videoButton.update(
|
||||||
|
transition: transition,
|
||||||
|
component: AnyComponent(PlainButtonComponent(
|
||||||
|
content: AnyComponent(VideoChatActionButtonComponent(
|
||||||
|
strings: environment.strings,
|
||||||
|
content: videoButtonContent,
|
||||||
|
microphoneState: actionButtonMicrophoneState,
|
||||||
|
isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide
|
||||||
|
)),
|
||||||
|
effectAlignment: .center,
|
||||||
|
action: { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let callState = self.callState, let muteState = callState.muteState, !muteState.canUnmute {
|
||||||
|
self.onAudioRoutePressed()
|
||||||
|
} else {
|
||||||
|
self.onCameraPressed()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animateAlpha: false
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
||||||
|
)
|
||||||
|
if let videoButtonView = self.videoButton.view {
|
||||||
|
if videoButtonView.superview == nil {
|
||||||
|
self.containerView.addSubview(videoButtonView)
|
||||||
|
}
|
||||||
|
transition.setPosition(view: videoButtonView, position: secondActionButtonFrame.center)
|
||||||
|
transition.setBounds(view: videoButtonView, bounds: CGRect(origin: CGPoint(), size: secondActionButtonFrame.size))
|
||||||
|
}
|
||||||
|
} else if let videoButtonView = self.videoButton.view {
|
||||||
|
let transition = ComponentTransition(animation: .curve(duration: 0.25, curve: .easeInOut))
|
||||||
|
transition.animateScale(view: videoButtonView, from: 1.0, to: 0.01)
|
||||||
|
transition.animateAlpha(view: videoButtonView, from: 1.0, to: 0.0, completion: { _ in
|
||||||
|
videoButtonView.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let _ = self.messageButton.update(
|
let _ = self.messageButton.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(PlainButtonComponent(
|
component: AnyComponent(PlainButtonComponent(
|
||||||
@ -3239,7 +3265,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
var inputPanelBottomInset: CGFloat = 0.0
|
var inputPanelBottomInset: CGFloat = 0.0
|
||||||
var inputPanelSize: CGSize = .zero
|
var inputPanelSize: CGSize = .zero
|
||||||
if self.inputPanelIsActive {
|
if self.inputPanelIsActive {
|
||||||
let inputPanelAvailableWidth = availableSize.width
|
let inputPanelAvailableWidth = availableSize.width - environment.safeInsets.left - environment.safeInsets.right
|
||||||
var inputPanelAvailableHeight = 103.0
|
var inputPanelAvailableHeight = 103.0
|
||||||
|
|
||||||
let keyboardWasHidden = self.inputPanelExternalState.isKeyboardHidden
|
let keyboardWasHidden = self.inputPanelExternalState.isKeyboardHidden
|
||||||
@ -3462,7 +3488,11 @@ final class VideoChatScreenComponent: Component {
|
|||||||
inputPanelBottomInset = inputHeight - environment.safeInsets.bottom
|
inputPanelBottomInset = inputHeight - environment.safeInsets.bottom
|
||||||
} else {
|
} else {
|
||||||
if self.inputPanelExternalState.isEditing {
|
if self.inputPanelExternalState.isEditing {
|
||||||
inputPanelBottomInset = availableSize.height - microphoneButtonFrame.minY
|
if buttonsOnTheSide {
|
||||||
|
inputPanelBottomInset = 16.0
|
||||||
|
} else {
|
||||||
|
inputPanelBottomInset = availableSize.height - microphoneButtonFrame.minY
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
inputPanelBottomInset = -inputPanelSize.height - environment.safeInsets.bottom
|
inputPanelBottomInset = -inputPanelSize.height - environment.safeInsets.bottom
|
||||||
}
|
}
|
||||||
@ -3758,7 +3788,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let messagesBottomInset: CGFloat = max(inputPanelBottomInset + inputPanelSize.height + 31.0, availableSize.height - microphoneButtonFrame.minY + 16.0) + reactionsInset
|
let normalMessagesBottomInset: CGFloat = buttonsOnTheSide ? 16.0 : availableSize.height - microphoneButtonFrame.minY + 16.0
|
||||||
|
let messagesBottomInset: CGFloat = max(inputPanelBottomInset + inputPanelSize.height + 31.0, normalMessagesBottomInset) + reactionsInset
|
||||||
let messagesListSize = self.messagesList.update(
|
let messagesListSize = self.messagesList.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(MessageListComponent(
|
component: AnyComponent(MessageListComponent(
|
||||||
@ -3768,9 +3799,9 @@ final class VideoChatScreenComponent: Component {
|
|||||||
sendActionTransition: sendActionTransition
|
sendActionTransition: sendActionTransition
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width, height: availableSize.height - messagesBottomInset)
|
containerSize: CGSize(width: availableSize.width - environment.safeInsets.left - environment.safeInsets.right, height: availableSize.height - messagesBottomInset)
|
||||||
)
|
)
|
||||||
let messagesListFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - messagesListSize.height - messagesBottomInset), size: messagesListSize)
|
let messagesListFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - messagesListSize.width) / 2.0), y: availableSize.height - messagesListSize.height - messagesBottomInset), size: messagesListSize)
|
||||||
if let messagesListView = self.messagesList.view {
|
if let messagesListView = self.messagesList.view {
|
||||||
if messagesListView.superview == nil {
|
if messagesListView.superview == nil {
|
||||||
messagesListView.isUserInteractionEnabled = false
|
messagesListView.isUserInteractionEnabled = false
|
||||||
|
|||||||
@ -362,7 +362,8 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
|
|||||||
valueCurrency: nil,
|
valueCurrency: nil,
|
||||||
flags: [],
|
flags: [],
|
||||||
themePeerId: nil,
|
themePeerId: nil,
|
||||||
peerColor: nil
|
peerColor: nil,
|
||||||
|
hostPeerId: nil
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
|
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
|
||||||
items.append(OrderedItemListEntry(id: RecentStarGiftItemId(id).rawValue, contents: entry))
|
items.append(OrderedItemListEntry(id: RecentStarGiftItemId(id).rawValue, contents: entry))
|
||||||
|
|||||||
@ -322,6 +322,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
case flags
|
case flags
|
||||||
case themePeerId
|
case themePeerId
|
||||||
case peerColor
|
case peerColor
|
||||||
|
case hostPeerId
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Flags: OptionSet {
|
public struct Flags: OptionSet {
|
||||||
@ -610,8 +611,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
public let flags: Flags
|
public let flags: Flags
|
||||||
public let themePeerId: EnginePeer.Id?
|
public let themePeerId: EnginePeer.Id?
|
||||||
public let peerColor: PeerCollectibleColor?
|
public let peerColor: PeerCollectibleColor?
|
||||||
|
public let hostPeerId: EnginePeer.Id?
|
||||||
|
|
||||||
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?) {
|
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?, hostPeerId: EnginePeer.Id?) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.giftId = giftId
|
self.giftId = giftId
|
||||||
self.title = title
|
self.title = title
|
||||||
@ -629,6 +631,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.themePeerId = themePeerId
|
self.themePeerId = themePeerId
|
||||||
self.peerColor = peerColor
|
self.peerColor = peerColor
|
||||||
|
self.hostPeerId = hostPeerId
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
@ -664,6 +667,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.flags = try container.decodeIfPresent(Int32.self, forKey: .flags).flatMap { Flags(rawValue: $0) } ?? []
|
self.flags = try container.decodeIfPresent(Int32.self, forKey: .flags).flatMap { Flags(rawValue: $0) } ?? []
|
||||||
self.themePeerId = try container.decodeIfPresent(Int64.self, forKey: .themePeerId).flatMap { EnginePeer.Id($0) }
|
self.themePeerId = try container.decodeIfPresent(Int64.self, forKey: .themePeerId).flatMap { EnginePeer.Id($0) }
|
||||||
self.peerColor = try container.decodeIfPresent(PeerCollectibleColor.self, forKey: .peerColor)
|
self.peerColor = try container.decodeIfPresent(PeerCollectibleColor.self, forKey: .peerColor)
|
||||||
|
self.hostPeerId = try container.decodeIfPresent(Int64.self, forKey: .hostPeerId).flatMap { EnginePeer.Id($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
@ -698,6 +702,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.flags = decoder.decodeOptionalInt32ForKey(CodingKeys.flags.rawValue).flatMap { Flags(rawValue: $0) } ?? []
|
self.flags = decoder.decodeOptionalInt32ForKey(CodingKeys.flags.rawValue).flatMap { Flags(rawValue: $0) } ?? []
|
||||||
self.themePeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.themePeerId.rawValue).flatMap { EnginePeer.Id($0) }
|
self.themePeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.themePeerId.rawValue).flatMap { EnginePeer.Id($0) }
|
||||||
self.peerColor = decoder.decodeCodable(PeerCollectibleColor.self, forKey: CodingKeys.peerColor.rawValue)
|
self.peerColor = decoder.decodeCodable(PeerCollectibleColor.self, forKey: CodingKeys.peerColor.rawValue)
|
||||||
|
self.hostPeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.hostPeerId.rawValue).flatMap { EnginePeer.Id($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
@ -726,6 +731,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
try container.encode(self.flags.rawValue, forKey: .flags)
|
try container.encode(self.flags.rawValue, forKey: .flags)
|
||||||
try container.encodeIfPresent(self.themePeerId?.toInt64(), forKey: .themePeerId)
|
try container.encodeIfPresent(self.themePeerId?.toInt64(), forKey: .themePeerId)
|
||||||
try container.encodeIfPresent(self.peerColor, forKey: .peerColor)
|
try container.encodeIfPresent(self.peerColor, forKey: .peerColor)
|
||||||
|
try container.encodeIfPresent(self.hostPeerId?.toInt64(), forKey: .hostPeerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@ -778,6 +784,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: CodingKeys.peerColor.rawValue)
|
encoder.encodeNil(forKey: CodingKeys.peerColor.rawValue)
|
||||||
}
|
}
|
||||||
|
if let hostPeerId = self.hostPeerId {
|
||||||
|
encoder.encodeInt64(hostPeerId.toInt64(), forKey: CodingKeys.hostPeerId.rawValue)
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: CodingKeys.hostPeerId.rawValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withResellAmounts(_ resellAmounts: [CurrencyAmount]?) -> UniqueGift {
|
public func withResellAmounts(_ resellAmounts: [CurrencyAmount]?) -> UniqueGift {
|
||||||
@ -798,7 +809,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
valueCurrency: self.valueCurrency,
|
valueCurrency: self.valueCurrency,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
themePeerId: self.themePeerId,
|
themePeerId: self.themePeerId,
|
||||||
peerColor: self.peerColor
|
peerColor: self.peerColor,
|
||||||
|
hostPeerId: self.hostPeerId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,7 +832,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
valueCurrency: self.valueCurrency,
|
valueCurrency: self.valueCurrency,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
themePeerId: self.themePeerId,
|
themePeerId: self.themePeerId,
|
||||||
peerColor: self.peerColor
|
peerColor: self.peerColor,
|
||||||
|
hostPeerId: self.hostPeerId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +855,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
valueCurrency: self.valueCurrency,
|
valueCurrency: self.valueCurrency,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
themePeerId: themePeerId,
|
themePeerId: themePeerId,
|
||||||
peerColor: self.peerColor
|
peerColor: self.peerColor,
|
||||||
|
hostPeerId: self.hostPeerId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +878,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
valueCurrency: self.valueCurrency,
|
valueCurrency: self.valueCurrency,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
themePeerId: self.themePeerId,
|
themePeerId: self.themePeerId,
|
||||||
peerColor: self.peerColor
|
peerColor: self.peerColor,
|
||||||
|
hostPeerId: self.hostPeerId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -977,7 +992,7 @@ extension StarGift {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId, perUserLimit: perUserLimit, lockedUntilDate: lockedUntilDate))
|
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId, perUserLimit: perUserLimit, lockedUntilDate: lockedUntilDate))
|
||||||
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, themePeer, peerColor):
|
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, themePeer, peerColor, hostPeerId):
|
||||||
let owner: StarGift.UniqueGift.Owner
|
let owner: StarGift.UniqueGift.Owner
|
||||||
if let ownerAddress {
|
if let ownerAddress {
|
||||||
owner = .address(ownerAddress)
|
owner = .address(ownerAddress)
|
||||||
@ -1009,7 +1024,7 @@ extension StarGift {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
self = .unique(StarGift.UniqueGift(id: id, giftId: giftId, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellAmounts: resellAmounts, resellForTonOnly: (apiFlags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId, valueAmount: valueAmount, valueCurrency: valueCurrency, flags: flags, themePeerId: themePeer?.peerId, peerColor: peerCollectibleColor))
|
self = .unique(StarGift.UniqueGift(id: id, giftId: giftId, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellAmounts: resellAmounts, resellForTonOnly: (apiFlags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId, valueAmount: valueAmount, valueCurrency: valueCurrency, flags: flags, themePeerId: themePeer?.peerId, peerColor: peerCollectibleColor, hostPeerId: hostPeerId?.peerId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -332,14 +332,6 @@ public extension Peer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var profileColor: PeerNameColor? {
|
var profileColor: PeerNameColor? {
|
||||||
if let emojiStatus {
|
|
||||||
switch emojiStatus.content {
|
|
||||||
case let .starGift(_, _, _, _, _, _, outerColor, _, _):
|
|
||||||
return PeerNameColor.other(outerColor)
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch self {
|
switch self {
|
||||||
case let user as TelegramUser:
|
case let user as TelegramUser:
|
||||||
return user.profileColor
|
return user.profileColor
|
||||||
@ -402,7 +394,7 @@ public extension Peer {
|
|||||||
|
|
||||||
public extension TelegramPeerUsername {
|
public extension TelegramPeerUsername {
|
||||||
var isActive: Bool {
|
var isActive: Bool {
|
||||||
return self.flags.contains(.isActive) || self.flags.contains(.isEditable)
|
return self.flags.contains(.isActive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1501,7 +1501,18 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let note = cachedData.note, !note.text.isEmpty {
|
if let note = cachedData.note, !note.text.isEmpty {
|
||||||
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.PeerInfo_Notes, rightLabel: presentationData.strings.PeerInfo_NotesInfo, text: note.text, entities: note.entities, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: []), action: nil, linkItemAction: bioLinkAction, button: nil, contextAction: noteContextAction, requestLayout: { animated in
|
var entities = note.entities
|
||||||
|
if !context.isPremium {
|
||||||
|
entities = entities.filter { entity in
|
||||||
|
switch entity.type {
|
||||||
|
case .Url, .TextUrl:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.PeerInfo_Notes, rightLabel: presentationData.strings.PeerInfo_NotesInfo, text: note.text, entities: entities, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: []), action: nil, linkItemAction: bioLinkAction, button: nil, contextAction: noteContextAction, requestLayout: { animated in
|
||||||
interaction.requestLayout(animated)
|
interaction.requestLayout(animated)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -4577,7 +4588,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
|
|
||||||
let noteUpdateSignal: Signal<Never, ContactUpdateError>
|
let noteUpdateSignal: Signal<Never, ContactUpdateError>
|
||||||
if noteUpdated, let note {
|
if noteUpdated, let note {
|
||||||
let entities = generateChatInputTextEntities(note)
|
let entities = generateTextEntities(note.string, enabledTypes: [.mention, .hashtag, .allUrl], currentEntities: generateChatInputTextEntities(note))
|
||||||
noteUpdateSignal = context.engine.contacts.updateContactNote(peerId: peer.id, text: note.string, entities: entities)
|
noteUpdateSignal = context.engine.contacts.updateContactNote(peerId: peer.id, text: note.string, entities: entities)
|
||||||
|> mapError { _ -> ContactUpdateError in
|
|> mapError { _ -> ContactUpdateError in
|
||||||
return .generic
|
return .generic
|
||||||
|
|||||||
@ -768,7 +768,8 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
valueCurrency: nil,
|
valueCurrency: nil,
|
||||||
flags: [],
|
flags: [],
|
||||||
themePeerId: nil,
|
themePeerId: nil,
|
||||||
peerColor: nil
|
peerColor: nil,
|
||||||
|
hostPeerId: nil
|
||||||
)
|
)
|
||||||
signal = component.context.engine.accountData.setStarGiftStatus(starGift: gift, expirationDate: emojiStatus.expirationDate)
|
signal = component.context.engine.accountData.setStarGiftStatus(starGift: gift, expirationDate: emojiStatus.expirationDate)
|
||||||
} else {
|
} else {
|
||||||
@ -1110,7 +1111,16 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
let updatedSection = Section(rawValue: intValue) ?? .profile
|
let updatedSection = Section(rawValue: intValue) ?? .profile
|
||||||
if self.currentSection != updatedSection {
|
if self.currentSection != updatedSection {
|
||||||
if (updatedSection == .name && self.selectedProfileGift != nil) || (updatedSection == .profile && self.selectedNameGift != nil) {
|
if (updatedSection == .name && self.selectedProfileGift != nil) || (updatedSection == .profile && self.selectedNameGift != nil) {
|
||||||
|
switch updatedSection {
|
||||||
|
case .profile:
|
||||||
|
self.selectedNameGift = nil
|
||||||
|
self.updatedPeerNameColor = nil
|
||||||
|
self.updatedPeerNameEmoji = nil
|
||||||
|
case .name:
|
||||||
|
self.selectedProfileGift = nil
|
||||||
|
self.updatedPeerProfileColor = nil
|
||||||
|
self.updatedPeerProfileEmoji = nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.currentSection = updatedSection
|
self.currentSection = updatedSection
|
||||||
self.state?.updated(transition: .easeInOut(duration: 0.3).withUserData(TransitionHint(animateTabChange: true)))
|
self.state?.updated(transition: .easeInOut(duration: 0.3).withUserData(TransitionHint(animateTabChange: true)))
|
||||||
@ -1871,6 +1881,8 @@ public class UserAppearanceScreen: ViewControllerComponentContainer {
|
|||||||
|
|
||||||
self.automaticallyControlPresentationContextLayout = false
|
self.automaticallyControlPresentationContextLayout = false
|
||||||
|
|
||||||
|
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
self.title = ""
|
self.title = ""
|
||||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user