mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Various improvements
This commit is contained in:
parent
9b0bcee0a7
commit
6ff961d250
@ -995,6 +995,11 @@ public enum SendInviteLinkScreenSubject {
|
||||
case groupCall(link: String)
|
||||
}
|
||||
|
||||
public enum StarsWithdrawalScreenSubject {
|
||||
case withdraw
|
||||
case enterAmount(current: StarsAmount)
|
||||
}
|
||||
|
||||
public protocol SharedAccountContext: AnyObject {
|
||||
var sharedContainerPath: String { get }
|
||||
var basePath: String { get }
|
||||
@ -1179,7 +1184,7 @@ public protocol SharedAccountContext: AnyObject {
|
||||
func makeStarsStatisticsScreen(context: AccountContext, peerId: EnginePeer.Id, revenueContext: StarsRevenueStatsContext) -> ViewController
|
||||
func makeStarsAmountScreen(context: AccountContext, initialValue: Int64?, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsWithdrawalScreen(context: AccountContext, stats: StarsRevenueStats, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsWithdrawalScreen(context: AccountContext, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsWithdrawalScreen(context: AccountContext, subject: StarsWithdrawalScreenSubject, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarGiftResellScreen(context: AccountContext, update: Bool, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsGiftScreen(context: AccountContext, message: EngineMessage) -> ViewController
|
||||
func makeStarsGiveawayBoostScreen(context: AccountContext, peerId: EnginePeer.Id, boost: ChannelBoostersContext.State.Boost) -> ViewController
|
||||
|
@ -38,9 +38,10 @@ private final class ChannelPermissionsControllerArguments {
|
||||
let updateSlowmode: (Int32) -> Void
|
||||
let updateUnrestrictBoosters: (Int32) -> Void
|
||||
let updateStarsAmount: (StarsAmount?, Bool) -> Void
|
||||
let openSetCustomStarsAmount: () -> Void
|
||||
let toggleIsOptionExpanded: (TelegramChatBannedRightsFlags) -> Void
|
||||
|
||||
init(context: AccountContext, updatePermission: @escaping (TelegramChatBannedRightsFlags, Bool) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, addPeer: @escaping () -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, openPeer: @escaping (ChannelParticipant) -> Void, openPeerInfo: @escaping (EnginePeer) -> Void, openKicked: @escaping () -> Void, presentRestrictedPermissionAlert: @escaping (TelegramChatBannedRightsFlags) -> Void, presentConversionToBroadcastGroup: @escaping () -> Void, openChannelExample: @escaping () -> Void, updateSlowmode: @escaping (Int32) -> Void, updateUnrestrictBoosters: @escaping (Int32) -> Void, updateStarsAmount: @escaping (StarsAmount?, Bool) -> Void, toggleIsOptionExpanded: @escaping (TelegramChatBannedRightsFlags) -> Void) {
|
||||
init(context: AccountContext, updatePermission: @escaping (TelegramChatBannedRightsFlags, Bool) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, addPeer: @escaping () -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, openPeer: @escaping (ChannelParticipant) -> Void, openPeerInfo: @escaping (EnginePeer) -> Void, openKicked: @escaping () -> Void, presentRestrictedPermissionAlert: @escaping (TelegramChatBannedRightsFlags) -> Void, presentConversionToBroadcastGroup: @escaping () -> Void, openChannelExample: @escaping () -> Void, updateSlowmode: @escaping (Int32) -> Void, updateUnrestrictBoosters: @escaping (Int32) -> Void, updateStarsAmount: @escaping (StarsAmount?, Bool) -> Void, openSetCustomStarsAmount: @escaping () -> Void, toggleIsOptionExpanded: @escaping (TelegramChatBannedRightsFlags) -> Void) {
|
||||
self.context = context
|
||||
self.updatePermission = updatePermission
|
||||
self.addPeer = addPeer
|
||||
@ -55,6 +56,7 @@ private final class ChannelPermissionsControllerArguments {
|
||||
self.updateSlowmode = updateSlowmode
|
||||
self.updateUnrestrictBoosters = updateUnrestrictBoosters
|
||||
self.updateStarsAmount = updateStarsAmount
|
||||
self.openSetCustomStarsAmount = openSetCustomStarsAmount
|
||||
self.toggleIsOptionExpanded = toggleIsOptionExpanded
|
||||
}
|
||||
}
|
||||
@ -427,7 +429,7 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
||||
case let .messagePrice(_, value, maxValue, price):
|
||||
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: true, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value, apply in
|
||||
arguments.updateStarsAmount(StarsAmount(value: value, nanos: 0), apply)
|
||||
})
|
||||
}, openSetCustom: nil)
|
||||
case let .messagePriceInfo(_, value):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
|
||||
case let .unrestrictBoostersSwitch(_, title, value):
|
||||
@ -1267,6 +1269,7 @@ public func channelPermissionsController(context: AccountContext, updatedPresent
|
||||
|> deliverOnMainQueue).start())
|
||||
})
|
||||
}
|
||||
}, openSetCustomStarsAmount: {
|
||||
}, toggleIsOptionExpanded: { flags in
|
||||
updateState { state in
|
||||
var state = state
|
||||
|
@ -20,6 +20,7 @@ private final class IncomingMessagePrivacyScreenArguments {
|
||||
let infoLinkAction: () -> Void
|
||||
let openExceptions: () -> Void
|
||||
let openPremiumInfo: () -> Void
|
||||
let openSetCustomStarsAmount: () -> Void
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
@ -27,7 +28,8 @@ private final class IncomingMessagePrivacyScreenArguments {
|
||||
disabledValuePressed: @escaping () -> Void,
|
||||
infoLinkAction: @escaping () -> Void,
|
||||
openExceptions: @escaping () -> Void,
|
||||
openPremiumInfo: @escaping () -> Void
|
||||
openPremiumInfo: @escaping () -> Void,
|
||||
openSetCustomStarsAmount: @escaping () -> Void
|
||||
) {
|
||||
self.context = context
|
||||
self.updateValue = updateValue
|
||||
@ -35,6 +37,7 @@ private final class IncomingMessagePrivacyScreenArguments {
|
||||
self.infoLinkAction = infoLinkAction
|
||||
self.openExceptions = openExceptions
|
||||
self.openPremiumInfo = openPremiumInfo
|
||||
self.openSetCustomStarsAmount = openSetCustomStarsAmount
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +154,8 @@ private enum GlobalAutoremoveEntry: ItemListNodeEntry {
|
||||
case let .price(value, maxValue, price, isEnabled):
|
||||
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: isEnabled, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value, _ in
|
||||
arguments.updateValue(.paidMessages(StarsAmount(value: value, nanos: 0)))
|
||||
}, openSetCustom: {
|
||||
arguments.openSetCustomStarsAmount()
|
||||
}, openPremiumInfo: {
|
||||
arguments.openPremiumInfo()
|
||||
})
|
||||
@ -365,6 +370,20 @@ public func incomingMessagePrivacyScreen(context: AccountContext, value: GlobalP
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
pushControllerImpl?(controller)
|
||||
},
|
||||
openSetCustomStarsAmount: {
|
||||
var currentAmount: StarsAmount = StarsAmount(value: 1, nanos: 0)
|
||||
if case let .paidMessages(value) = stateValue.with({ $0 }).updatedValue {
|
||||
currentAmount = value
|
||||
}
|
||||
let starsScreen = context.sharedContext.makeStarsWithdrawalScreen(context: context, subject: .enterAmount(current: currentAmount), completion: { amount in
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.updatedValue = .paidMessages(StarsAmount(value: amount, nanos: 0))
|
||||
return state
|
||||
}
|
||||
})
|
||||
pushControllerImpl?(starsScreen)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -121,6 +121,7 @@ swift_library(
|
||||
"//submodules/FastBlur",
|
||||
"//submodules/InviteLinksUI",
|
||||
"//third-party/td:TdBinding",
|
||||
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -26,6 +26,7 @@ import TooltipUI
|
||||
import BlurredBackgroundComponent
|
||||
import CallsEmoji
|
||||
import InviteLinksUI
|
||||
import AnimatedTextComponent
|
||||
|
||||
extension VideoChatCall {
|
||||
var myAudioLevelAndSpeaking: Signal<(Float, Bool), NoError> {
|
||||
@ -262,6 +263,9 @@ final class VideoChatScreenComponent: Component {
|
||||
var invitedPeers: [InvitedPeer] = []
|
||||
var invitedPeersDisposable: Disposable?
|
||||
|
||||
var lastTitleEvent: String?
|
||||
var lastTitleEventTimer: Foundation.Timer?
|
||||
|
||||
var speakingParticipantPeers: [EnginePeer] = []
|
||||
var visibleParticipants: Set<EnginePeer.Id> = Set()
|
||||
|
||||
@ -320,6 +324,7 @@ final class VideoChatScreenComponent: Component {
|
||||
self.inviteDisposable.dispose()
|
||||
self.conferenceCallStateDisposable?.dispose()
|
||||
self.encryptionKeyEmojiDisposable?.dispose()
|
||||
self.lastTitleEventTimer?.invalidate()
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
@ -1600,12 +1605,13 @@ final class VideoChatScreenComponent: Component {
|
||||
})
|
||||
|
||||
self.memberEventsDisposable?.dispose()
|
||||
if groupCall.peerId != nil {
|
||||
self.memberEventsDisposable = (groupCall.memberEvents
|
||||
|> deliverOnMainQueue).start(next: { [weak self] event in
|
||||
guard let self, let members = self.members, let environment = self.environment, case let .group(groupCall) = self.currentCall else {
|
||||
return
|
||||
}
|
||||
self.memberEventsDisposable = (groupCall.memberEvents
|
||||
|> deliverOnMainQueue).start(next: { [weak self] event in
|
||||
guard let self, let members = self.members, let environment = self.environment, case let .group(groupCall) = self.currentCall else {
|
||||
return
|
||||
}
|
||||
|
||||
if groupCall.peerId != nil {
|
||||
if event.joined {
|
||||
var displayEvent = false
|
||||
if case let .channel(channel) = self.peer, case .broadcast = channel.info {
|
||||
@ -1624,8 +1630,30 @@ final class VideoChatScreenComponent: Component {
|
||||
self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: event.peer, title: nil, text: text, action: nil, duration: 3), action: { _ in return false })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if event.joined {
|
||||
self.lastTitleEvent = "\(event.peer.compactDisplayTitle) joined"
|
||||
} else {
|
||||
self.lastTitleEvent = "\(event.peer.compactDisplayTitle) left"
|
||||
}
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
}
|
||||
|
||||
self.lastTitleEventTimer?.invalidate()
|
||||
self.lastTitleEventTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 3.5, repeats: false, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.lastTitleEventTimer = nil
|
||||
self.lastTitleEvent = nil
|
||||
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
case let .conferenceSource(conferenceSource):
|
||||
self.membersDisposable?.dispose()
|
||||
self.membersDisposable = (View.groupCallMembersForConferenceSource(conferenceSource: conferenceSource)
|
||||
@ -1887,14 +1915,17 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
let maxSingleColumnWidth: CGFloat = 620.0
|
||||
let isTwoColumnLayout: Bool
|
||||
let isLandscape: Bool
|
||||
if availableSize.width > maxSingleColumnWidth {
|
||||
if let mappedParticipants, mappedParticipants.participants.contains(where: { $0.videoDescription != nil || $0.presentationDescription != nil }) {
|
||||
isTwoColumnLayout = true
|
||||
} else {
|
||||
isTwoColumnLayout = false
|
||||
}
|
||||
isLandscape = true
|
||||
} else {
|
||||
isTwoColumnLayout = false
|
||||
isLandscape = false
|
||||
}
|
||||
|
||||
var containerOffset: CGFloat = 0.0
|
||||
@ -1935,24 +1966,32 @@ final class VideoChatScreenComponent: Component {
|
||||
}
|
||||
})
|
||||
|
||||
let landscapeControlsWidth: CGFloat = 88.0
|
||||
let landscapeControlsOffsetX: CGFloat = 18.0
|
||||
let landscapeControlsWidth: CGFloat = 104.0
|
||||
var landscapeControlsOffsetX: CGFloat = 0.0
|
||||
let landscapeControlsSpacing: CGFloat = 30.0
|
||||
|
||||
let leftInset: CGFloat = max(environment.safeInsets.left, 14.0)
|
||||
var leftInset: CGFloat = max(environment.safeInsets.left, 14.0)
|
||||
|
||||
var rightInset: CGFloat = max(environment.safeInsets.right, 14.0)
|
||||
var buttonsOnTheSide = false
|
||||
if availableSize.width > maxSingleColumnWidth && !environment.metrics.isTablet {
|
||||
leftInset += 2.0
|
||||
rightInset += 2.0
|
||||
|
||||
buttonsOnTheSide = true
|
||||
rightInset += landscapeControlsWidth
|
||||
if case .landscapeLeft = environment.orientation {
|
||||
rightInset = max(rightInset, environment.safeInsets.left + landscapeControlsWidth)
|
||||
landscapeControlsOffsetX = -environment.safeInsets.left
|
||||
} else {
|
||||
rightInset = max(rightInset, landscapeControlsWidth)
|
||||
}
|
||||
}
|
||||
|
||||
let topInset: CGFloat = environment.statusBarHeight + 2.0
|
||||
let navigationBarHeight: CGFloat = 61.0
|
||||
var navigationHeight = topInset + navigationBarHeight
|
||||
|
||||
let navigationButtonAreaWidth: CGFloat = 40.0
|
||||
let navigationButtonAreaWidth: CGFloat = 34.0
|
||||
let navigationButtonDiameter: CGFloat = 28.0
|
||||
|
||||
let navigationLeftButtonSize = self.navigationLeftButton.update(
|
||||
@ -2013,7 +2052,10 @@ final class VideoChatScreenComponent: Component {
|
||||
alphaTransition.setAlpha(view: navigationLeftButtonView, alpha: self.isAnimatedOutFromPrivateCall ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
let navigationRightButtonFrame = CGRect(origin: CGPoint(x: availableSize.width - rightInset - navigationButtonAreaWidth + floor((navigationButtonAreaWidth - navigationRightButtonSize.width) * 0.5), y: topInset + floor((navigationBarHeight - navigationRightButtonSize.height) * 0.5)), size: navigationRightButtonSize)
|
||||
var navigationRightButtonFrame = CGRect(origin: CGPoint(x: availableSize.width - rightInset - navigationButtonAreaWidth + floor((navigationButtonAreaWidth - navigationRightButtonSize.width) * 0.5), y: topInset + floor((navigationBarHeight - navigationRightButtonSize.height) * 0.5)), size: navigationRightButtonSize)
|
||||
if buttonsOnTheSide {
|
||||
navigationRightButtonFrame.origin.x += 42.0
|
||||
}
|
||||
if let navigationRightButtonView = self.navigationRightButton.view {
|
||||
if navigationRightButtonView.superview == nil {
|
||||
self.containerView.addSubview(navigationRightButtonView)
|
||||
@ -2022,6 +2064,7 @@ final class VideoChatScreenComponent: Component {
|
||||
alphaTransition.setAlpha(view: navigationRightButtonView, alpha: self.isAnimatedOutFromPrivateCall ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
var navigationSidebarButtonFrame: CGRect?
|
||||
if isTwoColumnLayout {
|
||||
var navigationSidebarButtonTransition = transition
|
||||
let navigationSidebarButton: ComponentView<Empty>
|
||||
@ -2057,7 +2100,8 @@ final class VideoChatScreenComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter)
|
||||
)
|
||||
let navigationSidebarButtonFrame = CGRect(origin: CGPoint(x: navigationRightButtonFrame.minX - 32.0 - navigationSidebarButtonSize.width, y: topInset + floor((navigationBarHeight - navigationSidebarButtonSize.height) * 0.5)), size: navigationSidebarButtonSize)
|
||||
let navigationSidebarButtonFrameValue = CGRect(origin: CGPoint(x: navigationRightButtonFrame.minX - 21.0 - navigationSidebarButtonSize.width, y: topInset + floor((navigationBarHeight - navigationSidebarButtonSize.height) * 0.5)), size: navigationSidebarButtonSize)
|
||||
navigationSidebarButtonFrame = navigationSidebarButtonFrameValue
|
||||
if let navigationSidebarButtonView = navigationSidebarButton.view {
|
||||
var animateIn = false
|
||||
if navigationSidebarButtonView.superview == nil {
|
||||
@ -2066,7 +2110,7 @@ final class VideoChatScreenComponent: Component {
|
||||
self.containerView.insertSubview(navigationSidebarButtonView, aboveSubview: navigationRightButtonView)
|
||||
}
|
||||
}
|
||||
navigationSidebarButtonTransition.setFrame(view: navigationSidebarButtonView, frame: navigationSidebarButtonFrame)
|
||||
navigationSidebarButtonTransition.setFrame(view: navigationSidebarButtonView, frame: navigationSidebarButtonFrameValue)
|
||||
if animateIn {
|
||||
transition.animateScale(view: navigationSidebarButtonView, from: 0.001, to: 1.0)
|
||||
transition.animateAlpha(view: navigationSidebarButtonView, from: 0.0, to: 1.0)
|
||||
@ -2082,17 +2126,27 @@ final class VideoChatScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let idleTitleStatusText: String
|
||||
var idleTitleStatusText: [AnimatedTextComponent.Item] = []
|
||||
if let callState = self.callState {
|
||||
if callState.networkState == .connected, let members = self.members {
|
||||
idleTitleStatusText = environment.strings.VoiceChat_Panel_Members(Int32(max(1, members.totalCount)))
|
||||
//TODO:localize
|
||||
let totalCount = max(1, members.totalCount)
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(0), isUnbreakable: false, content: .number(totalCount, minDigits: 0)))
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(1), isUnbreakable: false, content: .text(totalCount == 1 ? " participant" : " participants")))
|
||||
if let lastTitleEvent = self.lastTitleEvent {
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(6), isUnbreakable: false, content: .text(", \(lastTitleEvent)")))
|
||||
} else if !self.invitedPeers.isEmpty {
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(3), isUnbreakable: true, content: .text(", ")))
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(4), isUnbreakable: false, content: .number(self.invitedPeers.count, minDigits: 0)))
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(5), isUnbreakable: false, content: .text(" invited")))
|
||||
}
|
||||
} else if callState.scheduleTimestamp != nil {
|
||||
idleTitleStatusText = environment.strings.VoiceChat_Scheduled
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(0), isUnbreakable: false, content: .text(environment.strings.VoiceChat_Scheduled)))
|
||||
} else {
|
||||
idleTitleStatusText = environment.strings.VoiceChat_Connecting
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(0), isUnbreakable: false, content: .text(environment.strings.VoiceChat_Connecting)))
|
||||
}
|
||||
} else {
|
||||
idleTitleStatusText = " "
|
||||
idleTitleStatusText.append(AnimatedTextComponent.Item(id: AnyHashable(0), isUnbreakable: false, content: .text(" ")))
|
||||
}
|
||||
|
||||
let canManageCall = self.callState?.canManageCall ?? false
|
||||
@ -2108,6 +2162,7 @@ final class VideoChatScreenComponent: Component {
|
||||
title: self.callState?.title ?? self.peer?.debugDisplayTitle ?? environment.strings.VideoChat_GroupCallTitle,
|
||||
status: idleTitleStatusText,
|
||||
isRecording: self.callState?.recordingStartTimestamp != nil,
|
||||
isLandscape: isLandscape,
|
||||
strings: environment.strings,
|
||||
tapAction: self.callState?.recordingStartTimestamp != nil ? { [weak self] in
|
||||
guard let self, let environment = self.environment, let currentCall = self.currentCall else {
|
||||
@ -2146,7 +2201,12 @@ final class VideoChatScreenComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: maxTitleWidth, height: 100.0)
|
||||
)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: leftInset + floor((availableSize.width - leftInset - rightInset - titleSize.width) * 0.5), y: topInset + floor((navigationBarHeight - titleSize.height) * 0.5)), size: titleSize)
|
||||
var titleFrame = CGRect(origin: CGPoint(x: 0.0, y: topInset + floor((navigationBarHeight - titleSize.height) * 0.5)), size: titleSize)
|
||||
if isLandscape {
|
||||
titleFrame.origin.x = navigationLeftButtonFrame.maxX + 20.0
|
||||
} else {
|
||||
titleFrame.origin.x = leftInset + floor((availableSize.width - leftInset - rightInset - titleSize.width) * 0.5)
|
||||
}
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
self.containerView.addSubview(titleView)
|
||||
@ -2155,6 +2215,27 @@ final class VideoChatScreenComponent: Component {
|
||||
alphaTransition.setAlpha(view: titleView, alpha: self.isAnimatedOutFromPrivateCall ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
let areButtonsCollapsed: Bool
|
||||
let mainColumnWidth: CGFloat
|
||||
let mainColumnSideInset: CGFloat
|
||||
|
||||
if isTwoColumnLayout {
|
||||
areButtonsCollapsed = false
|
||||
|
||||
mainColumnWidth = min(isLandscape ? 340.0 : 320.0, availableSize.width - leftInset - rightInset - 340.0)
|
||||
mainColumnSideInset = 0.0
|
||||
} else {
|
||||
areButtonsCollapsed = self.expandedParticipantsVideoState != nil
|
||||
|
||||
if availableSize.width > maxSingleColumnWidth {
|
||||
mainColumnWidth = 420.0
|
||||
mainColumnSideInset = 0.0
|
||||
} else {
|
||||
mainColumnWidth = availableSize.width
|
||||
mainColumnSideInset = max(leftInset, rightInset)
|
||||
}
|
||||
}
|
||||
|
||||
var encryptionKeyFrame: CGRect?
|
||||
var isConference = false
|
||||
if case let .group(groupCall) = self.currentCall {
|
||||
@ -2163,7 +2244,9 @@ final class VideoChatScreenComponent: Component {
|
||||
isConference = true
|
||||
}
|
||||
if isConference {
|
||||
navigationHeight -= 2.0
|
||||
if !isLandscape {
|
||||
navigationHeight -= 2.0
|
||||
}
|
||||
let encryptionKey: ComponentView<Empty>
|
||||
var encryptionKeyTransition = transition
|
||||
if let current = self.encryptionKey {
|
||||
@ -2194,11 +2277,34 @@ final class VideoChatScreenComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: min(400.0, availableSize.width - leftInset - rightInset - 16.0 * 2.0), height: 10000.0)
|
||||
)
|
||||
let encryptionKeyFrameValue = CGRect(origin: CGPoint(x: leftInset + floor((availableSize.width - leftInset - rightInset - encryptionKeySize.width) * 0.5), y: navigationHeight), size: encryptionKeySize)
|
||||
var encryptionKeyFrameValue = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: encryptionKeySize)
|
||||
if isLandscape {
|
||||
let maxEncryptionKeyX: CGFloat
|
||||
if let navigationSidebarButtonFrame {
|
||||
maxEncryptionKeyX = navigationSidebarButtonFrame.minX - 8.0 - encryptionKeySize.width
|
||||
} else {
|
||||
maxEncryptionKeyX = navigationRightButtonFrame.minX - 8.0 - encryptionKeySize.width
|
||||
}
|
||||
|
||||
let idealEncryptionKeyX: CGFloat
|
||||
if isTwoColumnLayout {
|
||||
idealEncryptionKeyX = availableSize.width - rightInset - mainColumnWidth
|
||||
} else {
|
||||
idealEncryptionKeyX = maxEncryptionKeyX - 13.0
|
||||
}
|
||||
|
||||
encryptionKeyFrameValue.origin.x = min(idealEncryptionKeyX, maxEncryptionKeyX)
|
||||
encryptionKeyFrameValue.origin.y = navigationLeftButtonFrame.minY + floorToScreenPixels((navigationLeftButtonFrame.height - encryptionKeySize.height) * 0.5)
|
||||
} else {
|
||||
encryptionKeyFrameValue.origin.x = leftInset + floor((availableSize.width - leftInset - rightInset - encryptionKeySize.width) * 0.5)
|
||||
encryptionKeyFrameValue.origin.y = navigationHeight
|
||||
}
|
||||
encryptionKeyFrame = encryptionKeyFrameValue
|
||||
|
||||
navigationHeight += encryptionKeySize.height
|
||||
navigationHeight += 16.0
|
||||
if !isLandscape {
|
||||
navigationHeight += encryptionKeySize.height
|
||||
navigationHeight += 16.0
|
||||
}
|
||||
} else if let encryptionKey = self.encryptionKey {
|
||||
self.encryptionKey = nil
|
||||
encryptionKey.view?.removeFromSuperview()
|
||||
@ -2207,27 +2313,6 @@ final class VideoChatScreenComponent: Component {
|
||||
self.encryptionKeyBackground = nil
|
||||
}
|
||||
|
||||
let areButtonsCollapsed: Bool
|
||||
let mainColumnWidth: CGFloat
|
||||
let mainColumnSideInset: CGFloat
|
||||
|
||||
if isTwoColumnLayout {
|
||||
areButtonsCollapsed = false
|
||||
|
||||
mainColumnWidth = 320.0
|
||||
mainColumnSideInset = 0.0
|
||||
} else {
|
||||
areButtonsCollapsed = self.expandedParticipantsVideoState != nil
|
||||
|
||||
if availableSize.width > maxSingleColumnWidth {
|
||||
mainColumnWidth = 420.0
|
||||
mainColumnSideInset = 0.0
|
||||
} else {
|
||||
mainColumnWidth = availableSize.width
|
||||
mainColumnSideInset = max(leftInset, rightInset)
|
||||
}
|
||||
}
|
||||
|
||||
let actionButtonDiameter: CGFloat = 56.0
|
||||
let expandedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter
|
||||
var collapsedMicrophoneButtonDiameter: CGFloat = 116.0
|
||||
@ -2285,7 +2370,7 @@ final class VideoChatScreenComponent: Component {
|
||||
|
||||
if buttonsOnTheSide {
|
||||
collapsedMicrophoneButtonFrame.origin.y = floor((availableSize.height - actionButtonDiameter) * 0.5)
|
||||
collapsedMicrophoneButtonFrame.origin.x = availableSize.width - environment.safeInsets.right - landscapeControlsWidth + landscapeControlsOffsetX
|
||||
collapsedMicrophoneButtonFrame.origin.x = availableSize.width - landscapeControlsWidth + landscapeControlsOffsetX + floor((landscapeControlsWidth - actionButtonDiameter) * 0.5)
|
||||
|
||||
if isMainColumnHidden {
|
||||
collapsedMicrophoneButtonFrame.origin.x += mainColumnWidth + landscapeControlsWidth
|
||||
|
@ -6,19 +6,22 @@ import MultilineTextComponent
|
||||
import TelegramPresentationData
|
||||
import HierarchyTrackingLayer
|
||||
import ChatTitleActivityNode
|
||||
import AnimatedTextComponent
|
||||
|
||||
final class VideoChatTitleComponent: Component {
|
||||
let title: String
|
||||
let status: String
|
||||
let status: [AnimatedTextComponent.Item]
|
||||
let isRecording: Bool
|
||||
let isLandscape: Bool
|
||||
let strings: PresentationStrings
|
||||
let tapAction: (() -> Void)?
|
||||
let longTapAction: (() -> Void)?
|
||||
|
||||
init(
|
||||
title: String,
|
||||
status: String,
|
||||
status: [AnimatedTextComponent.Item],
|
||||
isRecording: Bool,
|
||||
isLandscape: Bool,
|
||||
strings: PresentationStrings,
|
||||
tapAction: (() -> Void)?,
|
||||
longTapAction: (() -> Void)?
|
||||
@ -26,6 +29,7 @@ final class VideoChatTitleComponent: Component {
|
||||
self.title = title
|
||||
self.status = status
|
||||
self.isRecording = isRecording
|
||||
self.isLandscape = isLandscape
|
||||
self.strings = strings
|
||||
self.tapAction = tapAction
|
||||
self.longTapAction = longTapAction
|
||||
@ -41,6 +45,9 @@ final class VideoChatTitleComponent: Component {
|
||||
if lhs.isRecording != rhs.isRecording {
|
||||
return false
|
||||
}
|
||||
if lhs.isLandscape != rhs.isLandscape {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
@ -211,12 +218,14 @@ final class VideoChatTitleComponent: Component {
|
||||
)
|
||||
|
||||
let statusComponent: AnyComponent<Empty>
|
||||
statusComponent = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: component.status, font: Font.regular(13.0), textColor: UIColor(white: 1.0, alpha: 0.5)))
|
||||
statusComponent = AnyComponent(AnimatedTextComponent(
|
||||
font: Font.regular(13.0),
|
||||
color: UIColor(white: 1.0, alpha: 0.5),
|
||||
items: component.status
|
||||
))
|
||||
|
||||
let statusSize = self.status.update(
|
||||
transition: .immediate,
|
||||
transition: transition,
|
||||
component: statusComponent,
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||
@ -224,7 +233,10 @@ final class VideoChatTitleComponent: Component {
|
||||
|
||||
let size = CGSize(width: availableSize.width, height: titleSize.height + spacing + statusSize.height)
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) * 0.5), y: 0.0), size: titleSize)
|
||||
var titleFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: titleSize)
|
||||
if !component.isLandscape {
|
||||
titleFrame.origin.x = floor((size.width - titleSize.width) * 0.5)
|
||||
}
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
titleView.layer.anchorPoint = CGPoint()
|
||||
@ -235,13 +247,17 @@ final class VideoChatTitleComponent: Component {
|
||||
titleView.bounds = CGRect(origin: CGPoint(), size: titleFrame.size)
|
||||
}
|
||||
|
||||
let statusFrame = CGRect(origin: CGPoint(x: floor((size.width - statusSize.width) * 0.5), y: titleFrame.maxY + spacing), size: statusSize)
|
||||
var statusFrame = CGRect(origin: CGPoint(x: 0.0, y: titleFrame.maxY + spacing), size: statusSize)
|
||||
if !component.isLandscape {
|
||||
statusFrame.origin.x = floor((size.width - statusSize.width) * 0.5)
|
||||
}
|
||||
if let statusView = self.status.view {
|
||||
if statusView.superview == nil {
|
||||
statusView.layer.anchorPoint = CGPoint()
|
||||
statusView.isUserInteractionEnabled = false
|
||||
self.addSubview(statusView)
|
||||
}
|
||||
transition.setPosition(view: statusView, position: statusFrame.center)
|
||||
transition.setPosition(view: statusView, position: statusFrame.origin)
|
||||
statusView.bounds = CGRect(origin: CGPoint(), size: statusFrame.size)
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,6 @@ func closeButtonImage(dark: Bool) -> UIImage? {
|
||||
return generateImage(CGSize(width: 28.0, height: 28.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setFillColor(UIColor(rgb: dark ? 0x1c1c1e : 0x2c2c2e).cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setLineWidth(2.0)
|
||||
context.setLineCap(.round)
|
||||
context.setStrokeColor(UIColor.white.cgColor)
|
||||
|
@ -26,9 +26,10 @@ public final class MessagePriceItem: ListViewItem, ItemListItem {
|
||||
let price: String
|
||||
public let sectionId: ItemListSectionId
|
||||
let updated: (Int64, Bool) -> Void
|
||||
let openSetCustom: (() -> Void)?
|
||||
let openPremiumInfo: (() -> Void)?
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, isEnabled: Bool, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64, Bool) -> Void, openPremiumInfo: (() -> Void)? = nil) {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, isEnabled: Bool, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64, Bool) -> Void, openSetCustom: (() -> Void)? = nil, openPremiumInfo: (() -> Void)? = nil) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.isEnabled = isEnabled
|
||||
@ -38,6 +39,7 @@ public final class MessagePriceItem: ListViewItem, ItemListItem {
|
||||
self.price = price
|
||||
self.sectionId = sectionId
|
||||
self.updated = updated
|
||||
self.openSetCustom = openSetCustom
|
||||
self.openPremiumInfo = openPremiumInfo
|
||||
}
|
||||
|
||||
@ -161,6 +163,8 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
private var sliderView: TGPhotoEditorSliderView?
|
||||
private let leftTextNode: ImmediateTextNode
|
||||
private let rightTextNode: ImmediateTextNode
|
||||
private let centerTextButtonNode: HighlightableButtonNode
|
||||
private let centerTextButtonBackground: UIImageView
|
||||
private let centerLeftTextNode: ImmediateTextNode
|
||||
private let centerRightTextNode: ImmediateTextNode
|
||||
private let lockIconNode: ASImageNode
|
||||
@ -186,8 +190,13 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
|
||||
self.leftTextNode = ImmediateTextNode()
|
||||
self.rightTextNode = ImmediateTextNode()
|
||||
|
||||
self.centerTextButtonNode = HighlightableButtonNode()
|
||||
self.centerTextButtonBackground = UIImageView()
|
||||
self.centerLeftTextNode = ImmediateTextNode()
|
||||
self.centerLeftTextNode.isUserInteractionEnabled = false
|
||||
self.centerRightTextNode = ImmediateTextNode()
|
||||
self.centerRightTextNode.isUserInteractionEnabled = false
|
||||
|
||||
self.lockIconNode = ASImageNode()
|
||||
self.lockIconNode.displaysAsynchronously = false
|
||||
@ -198,9 +207,13 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
|
||||
self.addSubnode(self.leftTextNode)
|
||||
self.addSubnode(self.rightTextNode)
|
||||
self.addSubnode(self.centerLeftTextNode)
|
||||
self.addSubnode(self.centerRightTextNode)
|
||||
self.addSubnode(self.centerTextButtonNode)
|
||||
self.centerTextButtonNode.view.addSubview(self.centerTextButtonBackground)
|
||||
self.centerTextButtonNode.addSubnode(self.centerLeftTextNode)
|
||||
self.centerTextButtonNode.addSubnode(self.centerRightTextNode)
|
||||
self.addSubnode(self.lockIconNode)
|
||||
|
||||
self.centerTextButtonNode.addTarget(self, action: #selector(self.centerTextButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -231,7 +244,11 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
|
||||
self.sliderView = sliderView
|
||||
}
|
||||
|
||||
|
||||
@objc private func centerTextButtonPressed() {
|
||||
self.item?.openSetCustom?()
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: MessagePriceItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let currentItem = self.item
|
||||
|
||||
@ -312,8 +329,8 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
let centralLeftText = item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
let leftTextSize = strongSelf.leftTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
|
||||
let rightTextSize = strongSelf.rightTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
|
||||
@ -328,10 +345,28 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
|
||||
let totalCenterWidth = centerLeftTextSize.width + centerSpacing + centerRightTextSize.width
|
||||
let centerLeftFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - totalCenterWidth) / 2.0), y: 11.0), size: centerLeftTextSize)
|
||||
strongSelf.centerLeftTextNode.frame = centerLeftFrame
|
||||
|
||||
let centerRightFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - totalCenterWidth) / 2.0) + totalCenterWidth - centerRightTextSize.width, y: 14.0 - UIScreenPixel), size: centerRightTextSize)
|
||||
strongSelf.centerRightTextNode.frame = centerRightFrame
|
||||
|
||||
let centerButtonFrame = CGRect(origin: CGPoint(x: centerLeftFrame.minX, y: centerLeftFrame.minY), size: CGSize(width: centerRightFrame.maxX - centerLeftFrame.minX, height: centerLeftFrame.height)).insetBy(dx: -8.0, dy: -4.0)
|
||||
|
||||
strongSelf.centerTextButtonNode.frame = centerButtonFrame
|
||||
|
||||
strongSelf.centerTextButtonBackground.frame = CGRect(origin: CGPoint(x: 0.0, y: UIScreenPixel), size: centerButtonFrame.size)
|
||||
if strongSelf.centerTextButtonBackground.image == nil {
|
||||
strongSelf.centerTextButtonBackground.image = generateStretchableFilledCircleImage(diameter: 16.0, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
strongSelf.centerTextButtonBackground.tintColor = item.theme.list.itemAccentColor.withMultipliedAlpha(0.1)
|
||||
|
||||
if item.openSetCustom != nil {
|
||||
strongSelf.centerTextButtonNode.isEnabled = true
|
||||
strongSelf.centerTextButtonBackground.isHidden = false
|
||||
} else {
|
||||
strongSelf.centerTextButtonNode.isEnabled = false
|
||||
strongSelf.centerTextButtonBackground.isHidden = true
|
||||
}
|
||||
|
||||
strongSelf.centerLeftTextNode.frame = centerLeftFrame.offsetBy(dx: -centerButtonFrame.minX, dy: -centerButtonFrame.minY)
|
||||
strongSelf.centerRightTextNode.frame = centerRightFrame.offsetBy(dx: -centerButtonFrame.minX, dy: -centerButtonFrame.minY)
|
||||
|
||||
if let sliderView = strongSelf.sliderView {
|
||||
if themeUpdated {
|
||||
@ -343,12 +378,17 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
|
||||
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))
|
||||
|
||||
sliderView.interactionEnded = { [weak self] in
|
||||
sliderView.interactionEnded = {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.item?.updated(Int64(self.amount.realValue), true)
|
||||
}
|
||||
|
||||
if !sliderView.isTracking {
|
||||
strongSelf.amount = Amount(realValue: Int(item.value), maxRealValue: Int(item.maxValue), maxSliderValue: 999, isLogarithmic: true)
|
||||
sliderView.value = CGFloat(strongSelf.amount.sliderValue)
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.lockIconNode.isHidden = item.isEnabled
|
||||
|
@ -156,6 +156,15 @@ private final class SheetContent: CombinedComponent {
|
||||
minAmount = StarsAmount(value: resaleConfiguration.starGiftResaleMinAmount, nanos: 0)
|
||||
maxAmount = StarsAmount(value: resaleConfiguration.starGiftResaleMaxAmount, nanos: 0)
|
||||
amountLabel = nil
|
||||
case .paidMessages:
|
||||
//TODO:localize
|
||||
titleString = "Price per Message"
|
||||
amountTitle = "PRICE IN STARS"
|
||||
amountPlaceholder = "Enter Price"
|
||||
|
||||
minAmount = StarsAmount(value: 1, nanos: 0)
|
||||
maxAmount = StarsAmount(value: resaleConfiguration.paidMessageMaxAmount, nanos: 0)
|
||||
amountLabel = nil
|
||||
}
|
||||
|
||||
let title = title.update(
|
||||
@ -280,6 +289,19 @@ private final class SheetContent: CombinedComponent {
|
||||
text: .plain(amountInfoString),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
case .paidMessages:
|
||||
let amountInfoString: NSAttributedString
|
||||
if let value = state.amount?.value, value > 0 {
|
||||
let fullValue: Int64 = Int64(value) * 1_000_000_000 * 80 / 100
|
||||
let amountValue = StarsAmount(value: fullValue / 1_000_000_000, nanos: Int32(fullValue % 1_000_000_000))
|
||||
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString("You will receive **\(amountValue) Stars**.", attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||
} else {
|
||||
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString("You will receive **80%**.", attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||
}
|
||||
amountFooter = AnyComponent(MultilineTextComponent(
|
||||
text: .plain(amountInfoString),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
default:
|
||||
amountFooter = nil
|
||||
}
|
||||
@ -340,6 +362,9 @@ private final class SheetContent: CombinedComponent {
|
||||
} else {
|
||||
buttonString = "Sell"
|
||||
}
|
||||
} else if case .paidMessages = component.mode {
|
||||
//TODO:localize
|
||||
buttonString = "OK"
|
||||
} else if let amount = state.amount {
|
||||
buttonString = "\(environment.strings.Stars_Withdraw_Withdraw) # \(presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator))"
|
||||
} else {
|
||||
@ -432,6 +457,8 @@ private final class SheetContent: CombinedComponent {
|
||||
amount = nil
|
||||
case .starGiftResell:
|
||||
amount = nil
|
||||
case let .paidMessages(initialValue):
|
||||
amount = StarsAmount(value: initialValue, nanos: 0)
|
||||
}
|
||||
|
||||
self.amount = amount
|
||||
@ -553,6 +580,7 @@ public final class StarsWithdrawScreen: ViewControllerComponentContainer {
|
||||
case paidMedia(Int64?)
|
||||
case reaction(Int64?)
|
||||
case starGiftResell(Bool)
|
||||
case paidMessages(Int64)
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
@ -3664,8 +3664,15 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
return StarsWithdrawScreen(context: context, mode: .withdraw(stats), completion: completion)
|
||||
}
|
||||
|
||||
public func makeStarsWithdrawalScreen(context: AccountContext, completion: @escaping (Int64) -> Void) -> ViewController {
|
||||
return StarsWithdrawScreen(context: context, mode: .accountWithdraw, completion: completion)
|
||||
public func makeStarsWithdrawalScreen(context: AccountContext, subject: StarsWithdrawalScreenSubject, completion: @escaping (Int64) -> Void) -> ViewController {
|
||||
let mode: StarsWithdrawScreen.Mode
|
||||
switch subject {
|
||||
case .withdraw:
|
||||
mode = .accountWithdraw
|
||||
case let .enterAmount(current):
|
||||
mode = .paidMessages(current.value)
|
||||
}
|
||||
return StarsWithdrawScreen(context: context, mode: mode, completion: completion)
|
||||
}
|
||||
|
||||
public func makeStarGiftResellScreen(context: AccountContext, update: Bool, completion: @escaping (Int64) -> Void) -> ViewController {
|
||||
|
Loading…
x
Reference in New Issue
Block a user