mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-29 03:21:29 +00:00
Merge commit '51ad5a5efa60aa8e3df243e744f3b47437a1ecd5'
This commit is contained in:
commit
a05ef5e022
@ -1547,6 +1547,7 @@ public protocol AccountContext: AnyObject {
|
||||
var inAppPurchaseManager: InAppPurchaseManager? { get }
|
||||
var starsContext: StarsContext? { get }
|
||||
var tonContext: StarsContext? { get }
|
||||
var giftAuctionsManager: GiftAuctionsManager? { get }
|
||||
|
||||
var currentLimitsConfiguration: Atomic<LimitsConfiguration> { get }
|
||||
var currentContentSettings: Atomic<ContentSettings> { get }
|
||||
|
||||
@ -6,7 +6,6 @@ import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import TelegramUIPreferences
|
||||
import TelegramPresentationData
|
||||
import LegacyComponents
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import ComponentFlow
|
||||
@ -97,7 +96,6 @@ private final class AutodownloadDataUsagePickerItemNode: ListViewItemNode {
|
||||
private let mediumTextNode: TextNode
|
||||
private let highTextNode: TextNode
|
||||
private let customTextNode: TextNode
|
||||
// private var sliderView: TGPhotoEditorSliderView?
|
||||
private let slider = ComponentView<Empty>()
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
@ -156,76 +154,7 @@ private final class AutodownloadDataUsagePickerItemNode: ListViewItemNode {
|
||||
// }
|
||||
}
|
||||
|
||||
// func updateSliderView() {
|
||||
// if let sliderView = self.sliderView, let item = self.item {
|
||||
// sliderView.maximumValue = 2.0 + (item.customPosition != nil ? 1 : 0)
|
||||
// sliderView.positionsCount = 3 + (item.customPosition != nil ? 1 : 0)
|
||||
// var value = item.value.rawValue
|
||||
// if let customPosition = item.customPosition {
|
||||
// if case .custom = item.value {
|
||||
// value = customPosition
|
||||
// } else {
|
||||
// if value >= customPosition {
|
||||
// value += 1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sliderView.value = CGFloat(value)
|
||||
//
|
||||
// sliderView.isUserInteractionEnabled = item.enabled
|
||||
// sliderView.alpha = item.enabled ? 1.0 : 0.4
|
||||
// sliderView.layer.allowsGroupOpacity = !item.enabled
|
||||
//
|
||||
// self.updateAccessibilityLabels()
|
||||
// }
|
||||
// }
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
// let sliderView = TGPhotoEditorSliderView()
|
||||
// sliderView.enablePanHandling = true
|
||||
// sliderView.trackCornerRadius = 2.0
|
||||
// sliderView.lineSize = 4.0
|
||||
// sliderView.dotSize = 5.0
|
||||
// sliderView.minimumValue = 0.0
|
||||
// sliderView.maximumValue = 2.0 + (self.item?.customPosition != nil ? 1 : 0)
|
||||
// sliderView.startValue = 0.0
|
||||
// sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||
// sliderView.positionsCount = 3 + (self.item?.customPosition != nil ? 1 : 0)
|
||||
// sliderView.useLinesForPositions = true
|
||||
// if let item = self.item, let params = self.layoutParams {
|
||||
// var value = item.value.rawValue
|
||||
// if let customPosition = item.customPosition {
|
||||
// if case .custom = item.value {
|
||||
// value = customPosition
|
||||
// } else {
|
||||
// if value >= customPosition {
|
||||
// value += 1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sliderView.value = CGFloat(value)
|
||||
// sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
// sliderView.backColor = item.theme.list.itemSwitchColors.frameColor
|
||||
// sliderView.startColor = item.theme.list.itemSwitchColors.frameColor
|
||||
// sliderView.trackColor = item.theme.list.itemAccentColor
|
||||
// sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
|
||||
//
|
||||
// sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: 37.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 15.0 * 2.0, height: 44.0))
|
||||
// sliderView.hitTestEdgeInsets = UIEdgeInsets(top: -sliderView.frame.minX, left: 0.0, bottom: 0.0, right: -sliderView.frame.minX)
|
||||
// }
|
||||
// self.view.addSubview(sliderView)
|
||||
// sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
|
||||
// self.sliderView = sliderView
|
||||
//
|
||||
// self.updateSliderView()
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: AutodownloadDataUsagePickerItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
// let currentItem = self.item
|
||||
let makeLowTextLayout = TextNode.asyncLayout(self.lowTextNode)
|
||||
let makeMediumTextLayout = TextNode.asyncLayout(self.mediumTextNode)
|
||||
let makeHighTextLayout = TextNode.asyncLayout(self.highTextNode)
|
||||
@ -381,21 +310,11 @@ private final class AutodownloadDataUsagePickerItemNode: ListViewItemNode {
|
||||
strongSelf.view.addSubview(sliderView)
|
||||
}
|
||||
sliderView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - sliderSize.width) / 2.0), y: 37.0), size: sliderSize)
|
||||
sliderView.isUserInteractionEnabled = item.enabled
|
||||
sliderView.alpha = item.enabled ? 1.0 : 0.4
|
||||
sliderView.layer.allowsGroupOpacity = !item.enabled
|
||||
}
|
||||
|
||||
// if let sliderView = strongSelf.sliderView {
|
||||
// if themeUpdated {
|
||||
// sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
// sliderView.backColor = item.theme.list.itemSwitchColors.frameColor
|
||||
// sliderView.trackColor = item.theme.list.itemSwitchColors.frameColor
|
||||
// sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
|
||||
// }
|
||||
//
|
||||
// sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: 37.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 15.0 * 2.0, height: 44.0))
|
||||
// sliderView.hitTestEdgeInsets = UIEdgeInsets(top: -sliderView.frame.minX, left: 0.0, bottom: 0.0, right: -sliderView.frame.minX)
|
||||
//
|
||||
// strongSelf.updateSliderView()
|
||||
// }
|
||||
strongSelf.activateArea.accessibilityLabel = item.strings.AutoDownloadSettings_DataUsage
|
||||
|
||||
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
|
||||
@ -430,28 +349,5 @@ private final class AutodownloadDataUsagePickerItemNode: ListViewItemNode {
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
// @objc func sliderValueChanged() {
|
||||
// guard let sliderView = self.sliderView else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// let position = Int(sliderView.value)
|
||||
// var value: AutomaticDownloadDataUsage?
|
||||
//
|
||||
// if let customPosition = self.item?.customPosition {
|
||||
// if position == customPosition {
|
||||
// value = .custom
|
||||
// } else {
|
||||
// value = AutomaticDownloadDataUsage(rawValue: position > customPosition ? (position - 1) : position)
|
||||
// }
|
||||
// } else {
|
||||
// value = AutomaticDownloadDataUsage(rawValue: position)
|
||||
// }
|
||||
//
|
||||
// if let value = value {
|
||||
// self.item?.updated(value)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@ -5,10 +5,11 @@ import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import LegacyComponents
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import AppBundle
|
||||
import ComponentFlow
|
||||
import SliderComponent
|
||||
|
||||
class EnergyUsageBatteryLevelItem: ListViewItem, ItemListItem {
|
||||
let systemStyle: ItemListSystemStyle
|
||||
@ -77,11 +78,11 @@ class EnergyUsageBatteryLevelItemNode: ListViewItemNode {
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
private let maskNode: ASImageNode
|
||||
|
||||
private var sliderView: TGPhotoEditorSliderView?
|
||||
private let leftTextNode: ImmediateTextNode
|
||||
private let rightTextNode: ImmediateTextNode
|
||||
private let centerTextNode: ImmediateTextNode
|
||||
private let centerMeasureTextNode: ImmediateTextNode
|
||||
private let slider = ComponentView<Empty>()
|
||||
|
||||
private let batteryImage: UIImage?
|
||||
private let batteryBackgroundNode: ASImageNode
|
||||
@ -120,42 +121,8 @@ class EnergyUsageBatteryLevelItemNode: ListViewItemNode {
|
||||
self.addSubnode(self.batteryForegroundNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let sliderView = TGPhotoEditorSliderView()
|
||||
sliderView.enableEdgeTap = true
|
||||
sliderView.enablePanHandling = true
|
||||
sliderView.trackCornerRadius = 1.0
|
||||
sliderView.lineSize = 4.0
|
||||
sliderView.minimumValue = 0.0
|
||||
sliderView.startValue = 0.0
|
||||
sliderView.maximumValue = 1.0
|
||||
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||
sliderView.displayEdges = true
|
||||
if let item = self.item, let params = self.layoutParams {
|
||||
sliderView.value = rescaleBatteryValueToSlider(CGFloat(item.value) / 100.0)
|
||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
sliderView.backColor = item.theme.list.itemSwitchColors.frameColor
|
||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||
sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
|
||||
|
||||
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
|
||||
}
|
||||
self.view.addSubview(sliderView)
|
||||
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
|
||||
self.sliderView = sliderView
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: EnergyUsageBatteryLevelItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let currentItem = self.item
|
||||
|
||||
return { item, params, neighbors in
|
||||
var themeUpdated = false
|
||||
if currentItem?.theme !== item.theme {
|
||||
themeUpdated = true
|
||||
}
|
||||
|
||||
let contentSize: CGSize
|
||||
let insets: UIEdgeInsets
|
||||
let separatorHeight = UIScreenPixel
|
||||
@ -312,15 +279,30 @@ class EnergyUsageBatteryLevelItemNode: ListViewItemNode {
|
||||
strongSelf.batteryForegroundNode.frame = strongSelf.batteryBackgroundNode.frame
|
||||
}
|
||||
|
||||
if let sliderView = strongSelf.sliderView {
|
||||
if themeUpdated {
|
||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
||||
sliderView.trackColor = item.theme.list.itemAccentColor.withAlphaComponent(0.45)
|
||||
sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
|
||||
let sliderSize = strongSelf.slider.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
SliderComponent(
|
||||
content: .continuous(.init(
|
||||
value: rescaleBatteryValueToSlider(CGFloat(item.value) / 100.0),
|
||||
minValue: nil,
|
||||
valueUpdated: { [weak self] value in
|
||||
self?.item?.updated(Int32(rescaleSliderToBatteryValue(value) * 100.0))
|
||||
}
|
||||
)),
|
||||
useNative: true,
|
||||
trackBackgroundColor: item.theme.list.itemSwitchColors.frameColor,
|
||||
trackForegroundColor: item.theme.list.itemAccentColor
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: params.width - params.leftInset - params.rightInset - 15.0 * 2.0, height: 44.0)
|
||||
)
|
||||
if let sliderView = strongSelf.slider.view {
|
||||
if sliderView.superview == nil {
|
||||
strongSelf.view.addSubview(sliderView)
|
||||
}
|
||||
|
||||
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0 + verticalInset), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
|
||||
sliderView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - sliderSize.width) / 2.0), y: 36.0 + verticalInset), size: sliderSize)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -334,12 +316,5 @@ class EnergyUsageBatteryLevelItemNode: ListViewItemNode {
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
@objc func sliderValueChanged() {
|
||||
guard let sliderView = self.sliderView else {
|
||||
return
|
||||
}
|
||||
self.item?.updated(Int32(rescaleSliderToBatteryValue(sliderView.value) * 100.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -183,11 +183,14 @@ private final class LocalizationListSearchContainerNode: SearchDisplayController
|
||||
let foundItems = self.searchQuery.get()
|
||||
|> mapToSignal { query -> Signal<[LocalizationInfo]?, NoError> in
|
||||
if let query = query, !query.isEmpty {
|
||||
let normalizedQuery = query.lowercased()
|
||||
let normalizedQuery = query.folding(options: [.diacriticInsensitive, .widthInsensitive, .caseInsensitive], locale: nil)
|
||||
var result: [LocalizationInfo] = []
|
||||
var uniqueIds = Set<String>()
|
||||
for info in listState.availableSavedLocalizations + listState.availableOfficialLocalizations {
|
||||
if info.title.lowercased().hasPrefix(normalizedQuery) || info.localizedTitle.lowercased().hasPrefix(normalizedQuery) {
|
||||
let title = info.title.folding(options: [.diacriticInsensitive, .widthInsensitive, .caseInsensitive], locale: nil)
|
||||
let localizedTitle = info.localizedTitle.folding(options: [.diacriticInsensitive, .widthInsensitive, .caseInsensitive], locale: nil)
|
||||
|
||||
if title.hasPrefix(normalizedQuery) || localizedTitle.hasPrefix(normalizedQuery) {
|
||||
if uniqueIds.contains(info.languageCode) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ public final class GiftAuctionContext {
|
||||
|
||||
private let queue: Queue = .mainQueue()
|
||||
private let account: Account
|
||||
private let giftId: Int64
|
||||
let giftId: Int64
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
@ -73,10 +73,17 @@ public final class GiftAuctionContext {
|
||||
return self.stateValue.get()
|
||||
}
|
||||
|
||||
public init(account: Account, giftId: Int64) {
|
||||
public convenience init(account: Account, giftId: Int64) {
|
||||
self.init(account: account, giftId: giftId, initialAuctionState: nil, initialMyState: nil)
|
||||
}
|
||||
|
||||
init(account: Account, giftId: Int64, initialAuctionState: State.AuctionState?, initialMyState: State.MyState?) {
|
||||
self.account = account
|
||||
self.giftId = giftId
|
||||
|
||||
self.auctionState = initialAuctionState
|
||||
self.myState = initialMyState
|
||||
|
||||
self.load()
|
||||
|
||||
self.updateAuctionStateDisposable = (self.account.stateManager.updatedStarGiftAuctionState()
|
||||
@ -265,3 +272,79 @@ func _internal_getGiftAuctionAcquiredGifts(account: Account, giftId: Int64) -> S
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_getActiveGiftAuctions(account: Account, hash: Int64) -> Signal<[GiftAuctionContext]?, NoError> {
|
||||
return account.network.request(Api.functions.payments.getStarGiftActiveAuctions(hash: hash))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result in
|
||||
return account.postbox.transaction { transaction -> [GiftAuctionContext]? in
|
||||
switch result {
|
||||
case let .starGiftActiveAuctions(auctions, users):
|
||||
let parsedPeers = AccumulatedPeers(users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
||||
|
||||
var auctionContexts: [GiftAuctionContext] = []
|
||||
for auction in auctions {
|
||||
switch auction {
|
||||
case let .starGiftActiveAuctionState(giftId, auctionState, userState):
|
||||
auctionContexts.append(GiftAuctionContext(
|
||||
account: account,
|
||||
giftId: giftId,
|
||||
initialAuctionState: GiftAuctionContext.State.AuctionState(apiAuctionState: auctionState),
|
||||
initialMyState: GiftAuctionContext.State.MyState(apiAuctionUserState: userState)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return auctionContexts
|
||||
case .starGiftActiveAuctionsNotModified:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GiftAuctionsManager {
|
||||
private let account: Account
|
||||
private var auctionContexts: [Int64 : GiftAuctionContext] = [:]
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
public init(account: Account) {
|
||||
self.account = account
|
||||
|
||||
self.reload()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
public func reload() {
|
||||
self.disposable.set((_internal_getActiveGiftAuctions(account: self.account, hash: 0)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] activeAuctions in
|
||||
guard let self, let activeAuctions else {
|
||||
return
|
||||
}
|
||||
var auctionContexts: [Int64 : GiftAuctionContext] = [:]
|
||||
for auction in activeAuctions {
|
||||
auctionContexts[auction.giftId] = auction
|
||||
}
|
||||
self.auctionContexts = auctionContexts
|
||||
}))
|
||||
}
|
||||
|
||||
public func auctionContextForGift(giftId: Int64) -> GiftAuctionContext {
|
||||
if let current = self.auctionContexts[giftId] {
|
||||
return current
|
||||
} else {
|
||||
let auctionContext = GiftAuctionContext(account: self.account, giftId: giftId)
|
||||
self.auctionContexts[giftId] = auctionContext
|
||||
return auctionContext
|
||||
}
|
||||
}
|
||||
|
||||
func storeAuctionContext(auctionContext: GiftAuctionContext) {
|
||||
self.auctionContexts[auctionContext.giftId] = auctionContext
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,13 +262,16 @@ final class CameraLiveStreamComponent: Component {
|
||||
public final class StreamAsComponent: Component {
|
||||
let context: AccountContext
|
||||
let peerId: EnginePeer.Id
|
||||
let isCustomTarget: Bool
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
peerId: EnginePeer.Id
|
||||
peerId: EnginePeer.Id,
|
||||
isCustomTarget: Bool
|
||||
) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.isCustomTarget = isCustomTarget
|
||||
}
|
||||
|
||||
public static func ==(lhs: StreamAsComponent, rhs: StreamAsComponent) -> Bool {
|
||||
@ -278,6 +281,9 @@ public final class StreamAsComponent: Component {
|
||||
if lhs.peerId != rhs.peerId {
|
||||
return false
|
||||
}
|
||||
if lhs.isCustomTarget != rhs.isCustomTarget {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -321,7 +327,8 @@ public final class StreamAsComponent: Component {
|
||||
})
|
||||
}
|
||||
|
||||
self.avatarNode.frame = CGRect(origin: .zero, size: CGSize(width: 32.0, height: 32.0))
|
||||
let avatarSize = CGSize(width: 32.0, height: 32.0)
|
||||
self.avatarNode.frame = CGRect(origin: .zero, size: avatarSize)
|
||||
if let peer = self.peer {
|
||||
self.avatarNode.setPeer(
|
||||
context: component.context,
|
||||
@ -341,7 +348,7 @@ public final class StreamAsComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 38.0, height: availableSize.height)
|
||||
)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: 42.0, y: 1.0), size: titleSize)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: 42.0, y: component.isCustomTarget ? floorToScreenPixels((avatarSize.height - titleSize.height) / 2.0) : 1.0), size: titleSize)
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
self.addSubview(titleView)
|
||||
@ -349,29 +356,34 @@ public final class StreamAsComponent: Component {
|
||||
titleView.frame = titleFrame
|
||||
}
|
||||
|
||||
let subtitleSize = self.subtitle.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "change", font: Font.regular(11.0), textColor: UIColor(white: 1.0, alpha: 0.8), paragraphAlignment: .left))
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 50.0, height: availableSize.height)
|
||||
)
|
||||
let subtitleFrame = CGRect(origin: CGPoint(x: 42.0, y: titleFrame.maxY + 2.0), size: subtitleSize)
|
||||
if let subtitleView = self.subtitle.view {
|
||||
if subtitleView.superview == nil {
|
||||
self.addSubview(subtitleView)
|
||||
var maxWidth = titleFrame.maxX
|
||||
if !component.isCustomTarget {
|
||||
//TODO:localize
|
||||
let subtitleSize = self.subtitle.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "change", font: Font.regular(11.0), textColor: UIColor(white: 1.0, alpha: 0.8), paragraphAlignment: .left))
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 50.0, height: availableSize.height)
|
||||
)
|
||||
let subtitleFrame = CGRect(origin: CGPoint(x: 42.0, y: titleFrame.maxY + 2.0), size: subtitleSize)
|
||||
if let subtitleView = self.subtitle.view {
|
||||
if subtitleView.superview == nil {
|
||||
self.addSubview(subtitleView)
|
||||
}
|
||||
subtitleView.frame = subtitleFrame
|
||||
}
|
||||
subtitleView.frame = subtitleFrame
|
||||
|
||||
if let icon = self.arrow.image {
|
||||
self.arrow.frame = CGRect(origin: CGPoint(x: subtitleFrame.maxX + 1.0, y: floorToScreenPixels(subtitleFrame.midY - icon.size.height / 2.0) + 1.0), size: icon.size).insetBy(dx: 1.0, dy: 1.0)
|
||||
}
|
||||
maxWidth = max(maxWidth, subtitleFrame.maxX + 16.0)
|
||||
}
|
||||
|
||||
if let icon = self.arrow.image {
|
||||
self.arrow.frame = CGRect(origin: CGPoint(x: subtitleFrame.maxX + 1.0, y: floorToScreenPixels(subtitleFrame.midY - icon.size.height / 2.0) + 1.0), size: icon.size).insetBy(dx: 1.0, dy: 1.0)
|
||||
}
|
||||
|
||||
return CGSize(width: max(titleFrame.maxX, subtitleFrame.maxX + 16.0), height: 32.0)
|
||||
return CGSize(width: maxWidth, height: avatarSize.height)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -305,6 +305,8 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
private var storiesBlockedPeers: BlockedPeersContext?
|
||||
|
||||
fileprivate var sendAsPeerId: EnginePeer.Id?
|
||||
fileprivate var isCustomTarget = false
|
||||
|
||||
private var privacy: EngineStoryPrivacy = EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: [])
|
||||
private var allowComments = true
|
||||
private var isForwardingDisabled = false
|
||||
@ -363,6 +365,13 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
self.setupRecentAssetSubscription()
|
||||
}
|
||||
|
||||
if let controller = getController() {
|
||||
if let customTarget = controller.customTarget {
|
||||
self.sendAsPeerId = customTarget
|
||||
self.isCustomTarget = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -943,6 +952,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
context: self.context,
|
||||
mode: .create(
|
||||
sendAsPeerId: self.sendAsPeerId,
|
||||
isCustomTarget: self.isCustomTarget,
|
||||
privacy: self.privacy,
|
||||
allowComments: self.allowComments,
|
||||
isForwardingDisabled: self.isForwardingDisabled,
|
||||
@ -1510,7 +1520,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
context: component.context,
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
peerId: component.context.account.peerId,
|
||||
peerId: state.sendAsPeerId ?? component.context.account.peerId,
|
||||
story: state.liveStreamStory,
|
||||
statusBarHeight: environment.statusBarHeight,
|
||||
inputHeight: environment.inputHeight,
|
||||
@ -1538,13 +1548,18 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
let streamAsButton = streamAsButton.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
StreamAsComponent(context: component.context, peerId: state.sendAsPeerId ?? component.context.account.peerId)
|
||||
StreamAsComponent(
|
||||
context: component.context,
|
||||
peerId: state.sendAsPeerId ?? component.context.account.peerId,
|
||||
isCustomTarget: state.isCustomTarget
|
||||
)
|
||||
),
|
||||
action: { [weak state] in
|
||||
if let state {
|
||||
state.presentStreamAsPeer()
|
||||
}
|
||||
},
|
||||
isEnabled: !state.isCustomTarget,
|
||||
animateAlpha: true,
|
||||
animateScale: false
|
||||
),
|
||||
@ -3836,6 +3851,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
|
||||
private let context: AccountContext
|
||||
fileprivate let mode: Mode
|
||||
fileprivate let customTarget: EnginePeer.Id?
|
||||
fileprivate let holder: CameraHolder?
|
||||
fileprivate let transitionIn: TransitionIn?
|
||||
fileprivate let transitionOut: (Bool) -> TransitionOut?
|
||||
@ -3901,6 +3917,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
public init(
|
||||
context: AccountContext,
|
||||
mode: Mode,
|
||||
customTarget: EnginePeer.Id? = nil,
|
||||
holder: CameraHolder? = nil,
|
||||
transitionIn: TransitionIn?,
|
||||
transitionOut: @escaping (Bool) -> TransitionOut?,
|
||||
@ -3908,6 +3925,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
||||
) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.customTarget = customTarget
|
||||
self.holder = holder
|
||||
self.transitionIn = transitionIn
|
||||
self.transitionOut = transitionOut
|
||||
|
||||
@ -909,8 +909,8 @@ private final class GiftSetupScreenComponent: Component {
|
||||
self.hideName = true
|
||||
}
|
||||
|
||||
if case let .starGift(gift, _) = component.subject, gift.flags.contains(.isAuction) {
|
||||
let giftAuction = GiftAuctionContext(account: component.context.account, giftId: gift.id)
|
||||
if case let .starGift(gift, _) = component.subject, gift.flags.contains(.isAuction), let giftAuctionsManager = component.context.giftAuctionsManager {
|
||||
let giftAuction = giftAuctionsManager.auctionContextForGift(giftId: gift.id)
|
||||
self.giftAuction = giftAuction
|
||||
self.giftAuctionDisposable = (giftAuction.state
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
|
||||
@ -304,10 +304,10 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
subtitle: subtitle.flatMap { PeerListItemComponent.Subtitle(text: $0, color: .neutral) },
|
||||
subtitleAccessory: .none,
|
||||
presence: nil,
|
||||
rightAccessory: .disclosure,
|
||||
rightAccessory: screenState.isCustomTarget ? .none : .disclosure,
|
||||
selectionState: .none,
|
||||
hasNext: false,
|
||||
action: { [weak self] _, _, _ in
|
||||
action: screenState.isCustomTarget ? nil : { [weak self] _, _, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -316,12 +316,21 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
)
|
||||
))]
|
||||
|
||||
let streamAsSectionHeader = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "START LIVE AS",
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: theme.list.freeTextColor
|
||||
)),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
|
||||
let streamAsSectionSize = self.streamAsSection.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(ListSectionComponent(
|
||||
theme: theme,
|
||||
style: .glass,
|
||||
header: nil,
|
||||
header: streamAsSectionHeader,
|
||||
footer: nil,
|
||||
items: streamAsSectionItems
|
||||
)),
|
||||
@ -1040,7 +1049,7 @@ final class LiveStreamSettingsScreenComponent: Component {
|
||||
|
||||
public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
public enum Mode {
|
||||
case create(sendAsPeerId: EnginePeer.Id?, privacy: EngineStoryPrivacy, allowComments: Bool, isForwardingDisabled: Bool, pin: Bool, paidMessageStars: Int64)
|
||||
case create(sendAsPeerId: EnginePeer.Id?, isCustomTarget: Bool, privacy: EngineStoryPrivacy, allowComments: Bool, isForwardingDisabled: Bool, pin: Bool, paidMessageStars: Int64)
|
||||
case edit(PresentationGroupCall)
|
||||
}
|
||||
|
||||
@ -1107,6 +1116,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
var isEdit: Bool
|
||||
var maxPaidMessageStars: Int64
|
||||
var sendAsPeerId: EnginePeer.Id?
|
||||
var isCustomTarget: Bool
|
||||
var privacy: EngineStoryPrivacy
|
||||
var allowComments: Bool
|
||||
var isForwardingDisabled: Bool
|
||||
@ -1123,6 +1133,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
isEdit: Bool,
|
||||
maxPaidMessageStars: Int64,
|
||||
sendAsPeerId: EnginePeer.Id?,
|
||||
isCustomTarget: Bool,
|
||||
privacy: EngineStoryPrivacy,
|
||||
allowComments: Bool,
|
||||
isForwardingDisabled: Bool,
|
||||
@ -1138,6 +1149,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
self.isEdit = isEdit
|
||||
self.maxPaidMessageStars = maxPaidMessageStars
|
||||
self.sendAsPeerId = sendAsPeerId
|
||||
self.isCustomTarget = isCustomTarget
|
||||
self.privacy = privacy
|
||||
self.allowComments = allowComments
|
||||
self.isForwardingDisabled = isForwardingDisabled
|
||||
@ -1353,6 +1365,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
let isEdit: Bool
|
||||
let maxPaidMessageStars: Int64 = 10000
|
||||
let sendAsPeerId: EnginePeer.Id?
|
||||
let isCustomTarget: Bool
|
||||
let privacy: EngineStoryPrivacy
|
||||
let allowComments: Bool
|
||||
let isForwardingDisabled: Bool
|
||||
@ -1362,6 +1375,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
if let current = self.stateValue {
|
||||
isEdit = current.isEdit
|
||||
sendAsPeerId = current.sendAsPeerId
|
||||
isCustomTarget = current.isCustomTarget
|
||||
privacy = current.privacy
|
||||
allowComments = current.allowComments
|
||||
isForwardingDisabled = current.isForwardingDisabled
|
||||
@ -1369,9 +1383,10 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
paidMessageStars = current.paidMessageStars
|
||||
} else {
|
||||
switch mode {
|
||||
case let .create(sendAsPeerIdValue, privacyValue, allowCommentsValue, isForwardingDisabledValue, pinValue, paidMessageStarsValue):
|
||||
case let .create(sendAsPeerIdValue, isCustomTargetValue, privacyValue, allowCommentsValue, isForwardingDisabledValue, pinValue, paidMessageStarsValue):
|
||||
isEdit = false
|
||||
sendAsPeerId = sendAsPeerIdValue
|
||||
isCustomTarget = isCustomTargetValue
|
||||
privacy = privacyValue
|
||||
allowComments = allowCommentsValue
|
||||
isForwardingDisabled = isForwardingDisabledValue
|
||||
@ -1381,6 +1396,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
let _ = call
|
||||
isEdit = true
|
||||
sendAsPeerId = nil
|
||||
isCustomTarget = false
|
||||
privacy = EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: [])
|
||||
allowComments = true
|
||||
isForwardingDisabled = false
|
||||
@ -1393,6 +1409,7 @@ public class LiveStreamSettingsScreen: ViewControllerComponentContainer {
|
||||
isEdit: isEdit,
|
||||
maxPaidMessageStars: maxPaidMessageStars,
|
||||
sendAsPeerId: sendAsPeerId,
|
||||
isCustomTarget: isCustomTarget,
|
||||
privacy: privacy,
|
||||
allowComments: allowComments,
|
||||
isForwardingDisabled: isForwardingDisabled,
|
||||
|
||||
@ -2762,7 +2762,7 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
containerInset += 10.0
|
||||
}
|
||||
|
||||
var navigationHeight: CGFloat = 66.0
|
||||
var navigationHeight: CGFloat = 72.0
|
||||
let navigationSideInset: CGFloat = 16.0
|
||||
let buttonSideInset: CGFloat = 36.0
|
||||
var navigationButtonsWidth: CGFloat = 0.0
|
||||
|
||||
@ -128,6 +128,7 @@ public final class AccountContextImpl: AccountContext {
|
||||
public let inAppPurchaseManager: InAppPurchaseManager?
|
||||
public let starsContext: StarsContext?
|
||||
public let tonContext: StarsContext?
|
||||
public let giftAuctionsManager: GiftAuctionsManager?
|
||||
|
||||
public let peerChannelMemberCategoriesContextsManager = PeerChannelMemberCategoriesContextsManager()
|
||||
|
||||
@ -299,6 +300,7 @@ public final class AccountContextImpl: AccountContext {
|
||||
self.inAppPurchaseManager = InAppPurchaseManager(engine: .authorized(self.engine))
|
||||
self.starsContext = self.engine.payments.peerStarsContext()
|
||||
self.tonContext = self.engine.payments.peerTonContext()
|
||||
self.giftAuctionsManager = GiftAuctionsManager(account: account)
|
||||
} else {
|
||||
self.prefetchManager = nil
|
||||
self.wallpaperUploadManager = nil
|
||||
@ -306,6 +308,7 @@ public final class AccountContextImpl: AccountContext {
|
||||
self.inAppPurchaseManager = nil
|
||||
self.starsContext = nil
|
||||
self.tonContext = nil
|
||||
self.giftAuctionsManager = nil
|
||||
}
|
||||
|
||||
self.account.stateManager.starsContext = self.starsContext
|
||||
|
||||
@ -316,6 +316,17 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
transitionOut: nil
|
||||
)
|
||||
|
||||
let mediaEditorCustomTarget = customTarget.flatMap { value -> EnginePeer.Id? in
|
||||
switch value {
|
||||
case .myStories:
|
||||
return nil
|
||||
case let .peer(id):
|
||||
return id
|
||||
case let .botPreview(id, _):
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
var presentImpl: ((ViewController) -> Void)?
|
||||
var returnToCameraImpl: (() -> Void)?
|
||||
var dismissCameraImpl: (() -> Void)?
|
||||
@ -323,6 +334,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
let cameraController = CameraScreenImpl(
|
||||
context: context,
|
||||
mode: .story,
|
||||
customTarget: mediaEditorCustomTarget,
|
||||
transitionIn: transitionIn.flatMap {
|
||||
if let sourceView = $0.sourceView {
|
||||
return CameraScreenImpl.TransitionIn(
|
||||
@ -410,17 +422,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
transitionIn = .camera
|
||||
}
|
||||
|
||||
let mediaEditorCustomTarget = customTarget.flatMap { value -> EnginePeer.Id? in
|
||||
switch value {
|
||||
case .myStories:
|
||||
return nil
|
||||
case let .peer(id):
|
||||
return id
|
||||
case let .botPreview(id, _):
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
let controller = MediaEditorScreenImpl(
|
||||
context: context,
|
||||
mode: .storyEditor(remainingCount: storyRemainingCount ?? 1),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user