mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-20 18:21:10 +00:00
Various improvements
This commit is contained in:
parent
40b770dde8
commit
b5c3d6f34f
@ -14381,7 +14381,7 @@ Sorry for the inconvenience.";
|
|||||||
"ChannelMessages.Info" = "Allow users to send messages to your channel, with the option to charge a fee for each message.";
|
"ChannelMessages.Info" = "Allow users to send messages to your channel, with the option to charge a fee for each message.";
|
||||||
"ChannelMessages.SwitchTitle" = "Allow Channel Messages";
|
"ChannelMessages.SwitchTitle" = "Allow Channel Messages";
|
||||||
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
|
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
|
||||||
"ChannelMessages.PriceSectionFooter" = "You will receive 85% of the selected fee for each incoming message.";
|
"ChannelMessages.PriceSectionFooterValue" = "You will receive %1$@% of the selected fee for each incoming message.";
|
||||||
|
|
||||||
"ChatList.MonoforumLabel" = "DIRECT";
|
"ChatList.MonoforumLabel" = "DIRECT";
|
||||||
"ChatList.MonoforumEmptyText" = "No messages here yet...";
|
"ChatList.MonoforumEmptyText" = "No messages here yet...";
|
||||||
@ -14408,7 +14408,7 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.SendMessage.AdjustmentPlaceholder" = "Price for each Message";
|
"Stars.SendMessage.AdjustmentPlaceholder" = "Price for each Message";
|
||||||
"Stars.SendMessage.AdjustmentSectionHeader" = "PRICE IN STARS";
|
"Stars.SendMessage.AdjustmentSectionHeader" = "PRICE IN STARS";
|
||||||
"Stars.SendMessage.AdjustmentSectionFooterValue" = "You will receive **%@ Stars**.";
|
"Stars.SendMessage.AdjustmentSectionFooterValue" = "You will receive **%@ Stars**.";
|
||||||
"Stars.SendMessage.AdjustmentSectionFooterEmpty" = "You will receive **80%**.";
|
"Stars.SendMessage.AdjustmentSectionFooterEmptyValue" = "You will receive **%1$@%**.";
|
||||||
"Stars.SendMessage.AdjustmentAction" = "OK";
|
"Stars.SendMessage.AdjustmentAction" = "OK";
|
||||||
|
|
||||||
"Stars.SendMessage.PriceFree" = "Free";
|
"Stars.SendMessage.PriceFree" = "Free";
|
||||||
|
@ -425,6 +425,28 @@ public extension ChatLocation {
|
|||||||
return .replyThread(message: message.normalized)
|
return .replyThread(message: message.normalized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var peerId: PeerId? {
|
||||||
|
switch self {
|
||||||
|
case let .peer(peerId):
|
||||||
|
return peerId
|
||||||
|
case let .replyThread(replyThreadMessage):
|
||||||
|
return replyThreadMessage.peerId
|
||||||
|
case .customChatContents:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var threadId: Int64? {
|
||||||
|
switch self {
|
||||||
|
case .peer:
|
||||||
|
return nil
|
||||||
|
case let .replyThread(replyThreadMessage):
|
||||||
|
return replyThreadMessage.threadId
|
||||||
|
case .customChatContents:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChatControllerActivateInput {
|
public enum ChatControllerActivateInput {
|
||||||
|
@ -11,6 +11,7 @@ public enum ChatListControllerLocation: Equatable {
|
|||||||
|
|
||||||
public protocol ChatListController: ViewController {
|
public protocol ChatListController: ViewController {
|
||||||
var context: AccountContext { get }
|
var context: AccountContext { get }
|
||||||
|
var location: ChatListControllerLocation { get }
|
||||||
var lockViewFrame: CGRect? { get }
|
var lockViewFrame: CGRect? { get }
|
||||||
|
|
||||||
var isSearchActive: Bool { get }
|
var isSearchActive: Bool { get }
|
||||||
@ -25,4 +26,6 @@ public protocol ChatListController: ViewController {
|
|||||||
|
|
||||||
func openStories(peerId: EnginePeer.Id)
|
func openStories(peerId: EnginePeer.Id)
|
||||||
func openStoriesFromNotification(peerId: EnginePeer.Id, storyId: Int32)
|
func openStoriesFromNotification(peerId: EnginePeer.Id, storyId: Int32)
|
||||||
|
|
||||||
|
func resetForumStackIfOpen()
|
||||||
}
|
}
|
||||||
|
@ -3601,6 +3601,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func resetForumStackIfOpen() {
|
||||||
|
if self.secondaryContext != nil {
|
||||||
|
self.setInlineChatList(location: nil, animated: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func setInlineChatList(location: ChatListControllerLocation?, animated: Bool = true) {
|
public func setInlineChatList(location: ChatListControllerLocation?, animated: Bool = true) {
|
||||||
if let location {
|
if let location {
|
||||||
let inlineNode = self.chatListDisplayNode.makeInlineChatList(location: location)
|
let inlineNode = self.chatListDisplayNode.makeInlineChatList(location: location)
|
||||||
|
@ -10,30 +10,6 @@ import ChatInterfaceState
|
|||||||
import ChatContextQuery
|
import ChatContextQuery
|
||||||
import AudioWaveform
|
import AudioWaveform
|
||||||
|
|
||||||
public extension ChatLocation {
|
|
||||||
var peerId: PeerId? {
|
|
||||||
switch self {
|
|
||||||
case let .peer(peerId):
|
|
||||||
return peerId
|
|
||||||
case let .replyThread(replyThreadMessage):
|
|
||||||
return replyThreadMessage.peerId
|
|
||||||
case .customChatContents:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var threadId: Int64? {
|
|
||||||
switch self {
|
|
||||||
case .peer:
|
|
||||||
return nil
|
|
||||||
case let .replyThread(replyThreadMessage):
|
|
||||||
return replyThreadMessage.threadId
|
|
||||||
case .customChatContents:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ChatMediaInputMode {
|
public enum ChatMediaInputMode {
|
||||||
case gif
|
case gif
|
||||||
case other
|
case other
|
||||||
|
@ -182,10 +182,6 @@ func _internal_premiumGiftCodeOptions(account: Account, peerId: EnginePeer.Id?,
|
|||||||
return .single([])
|
return .single([])
|
||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
|
|
||||||
var flags: Int32 = 0
|
|
||||||
if let _ = peerId {
|
|
||||||
flags |= 1 << 0
|
|
||||||
}
|
|
||||||
let remote = account.postbox.transaction { transaction -> Peer? in
|
let remote = account.postbox.transaction { transaction -> Peer? in
|
||||||
if let peerId = peerId {
|
if let peerId = peerId {
|
||||||
return transaction.getPeer(peerId)
|
return transaction.getPeer(peerId)
|
||||||
@ -194,6 +190,10 @@ func _internal_premiumGiftCodeOptions(account: Account, peerId: EnginePeer.Id?,
|
|||||||
}
|
}
|
||||||
|> mapToSignal { peer in
|
|> mapToSignal { peer in
|
||||||
let inputPeer = peer.flatMap(apiInputPeer)
|
let inputPeer = peer.flatMap(apiInputPeer)
|
||||||
|
var flags: Int32 = 0
|
||||||
|
if let _ = inputPeer {
|
||||||
|
flags |= 1 << 0
|
||||||
|
}
|
||||||
return account.network.request(Api.functions.payments.getPremiumGiftCodeOptions(flags: flags, boostPeer: inputPeer))
|
return account.network.request(Api.functions.payments.getPremiumGiftCodeOptions(flags: flags, boostPeer: inputPeer))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<[Api.PremiumGiftCodeOption]?, NoError> in
|
|> `catch` { _ -> Signal<[Api.PremiumGiftCodeOption]?, NoError> in
|
||||||
|
@ -416,6 +416,17 @@ public final class ChatLoadingPlaceholderNode: ASDisplayNode {
|
|||||||
} else if peer is TelegramGroup {
|
} else if peer is TelegramGroup {
|
||||||
chatType = .group
|
chatType = .group
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.isMonoForum {
|
||||||
|
if let mainChannel = chatPresentationInterfaceState.renderedPeer?.chatOrMonoforumMainPeer as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
|
if chatPresentationInterfaceState.chatLocation.threadId == nil {
|
||||||
|
chatType = .group
|
||||||
|
} else {
|
||||||
|
chatType = .user
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chatType = .user
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if case .group = channel.info {
|
if case .group = channel.info {
|
||||||
chatType = .group
|
chatType = .group
|
||||||
} else {
|
} else {
|
||||||
@ -423,6 +434,7 @@ public final class ChatLoadingPlaceholderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.chatType != chatType {
|
if self.chatType != chatType {
|
||||||
self.chatType = chatType
|
self.chatType = chatType
|
||||||
|
@ -2546,7 +2546,13 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
nameNodeOriginY += 5.0
|
nameNodeOriginY += 5.0
|
||||||
}
|
}
|
||||||
|
|
||||||
headerSize.width = max(headerSize.width, nameAvatarSpaceWidth + nameNodeSizeApply.0.width + 8.0 + adminBadgeSizeAndApply.0.size.width + credibilityIconWidth + boostBadgeWidth + closeButtonWidth + bubbleWidthInsets)
|
var headerSizeWidth = nameAvatarSpaceWidth + nameNodeSizeApply.0.width + 8.0 + credibilityIconWidth + boostBadgeWidth + closeButtonWidth + bubbleWidthInsets
|
||||||
|
if hasTitleTopicNavigation {
|
||||||
|
} else {
|
||||||
|
headerSizeWidth += adminBadgeSizeAndApply.0.size.width
|
||||||
|
}
|
||||||
|
|
||||||
|
headerSize.width = max(headerSize.width, headerSizeWidth)
|
||||||
headerSize.height += nameNodeSizeApply.0.height
|
headerSize.height += nameNodeSizeApply.0.height
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3881,12 +3887,14 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
}
|
}
|
||||||
strongSelf.clippingNode.addSubnode(adminBadgeNode)
|
strongSelf.clippingNode.addSubnode(adminBadgeNode)
|
||||||
adminBadgeNode.frame = adminBadgeFrame
|
adminBadgeNode.frame = adminBadgeFrame
|
||||||
|
adminBadgeNode.alpha = hasTitleTopicNavigation ? 0.0 : 1.0
|
||||||
|
|
||||||
if animation.isAnimated {
|
if animation.isAnimated, adminBadgeNode.alpha != 0.0 {
|
||||||
adminBadgeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
adminBadgeNode.layer.animateAlpha(from: 0.0, to: adminBadgeNode.alpha, duration: 0.2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
animation.animator.updateFrame(layer: adminBadgeNode.layer, frame: adminBadgeFrame, completion: nil)
|
animation.animator.updateFrame(layer: adminBadgeNode.layer, frame: adminBadgeFrame, completion: nil)
|
||||||
|
animation.animator.updateAlpha(layer: adminBadgeNode.layer, alpha: hasTitleTopicNavigation ? 0.0 : 1.0, completion: nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strongSelf.adminBadgeNode?.removeFromSupernode()
|
strongSelf.adminBadgeNode?.removeFromSupernode()
|
||||||
|
@ -72,6 +72,7 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
|
|
||||||
private var isOn = false
|
private var isOn = false
|
||||||
private var mode: ForumModeComponent.Mode = .tabs
|
private var mode: ForumModeComponent.Mode = .tabs
|
||||||
|
private var initialOnMode: ForumModeComponent.Mode?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.scrollView = ScrollView()
|
self.scrollView = ScrollView()
|
||||||
@ -143,17 +144,62 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toggleTopicsEnabled(_ enabled: Bool) {
|
func toggleTopicsEnabled(_ enabled: Bool) {
|
||||||
guard let component = self.component, let peer = self.peer else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.isOn = enabled
|
self.isOn = enabled
|
||||||
let displayForumAsTabs = self.mode == .tabs
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func attemptNavigation(complete: @escaping () -> Void) -> Bool {
|
||||||
|
guard let component = self.component, let peer = self.peer else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var isUpdated = false
|
||||||
|
if self.isOn {
|
||||||
|
if let initialOnMode = self.initialOnMode {
|
||||||
|
if initialOnMode != self.mode {
|
||||||
|
isUpdated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isUpdated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.initialOnMode != nil {
|
||||||
|
isUpdated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isUpdated {
|
||||||
|
if let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController {
|
||||||
|
var viewControllers = navigationController.viewControllers
|
||||||
|
|
||||||
|
if self.isOn && self.mode == .list {
|
||||||
|
for i in 0 ..< viewControllers.count {
|
||||||
|
if let chatController = viewControllers[i] as? ChatController, chatController.chatLocation.peerId == component.peerId {
|
||||||
|
let chatListController = component.context.sharedContext.makeChatListController(context: component.context, location: .forum(peerId: component.peerId), controlsHistoryPreload: false, hideNetworkActivityStatus: false, previewing: false, enableDebugActions: false)
|
||||||
|
viewControllers[i] = chatListController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
navigationController.setViewControllers(viewControllers, animated: false)
|
||||||
|
} else {
|
||||||
|
for i in (0 ..< viewControllers.count).reversed() {
|
||||||
|
if let chatListController = viewControllers[i] as? ChatListController, chatListController.location == .forum(peerId: component.peerId) {
|
||||||
|
viewControllers.remove(at: i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
navigationController.setViewControllers(viewControllers, animated: false)
|
||||||
|
|
||||||
|
if let baseController = navigationController as? TelegramRootControllerInterface, let chatListController = baseController.getChatsController() as? ChatListController {
|
||||||
|
chatListController.resetForumStackIfOpen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.isOn {
|
if self.isOn {
|
||||||
if case .legacyGroup = peer {
|
if case .legacyGroup = peer {
|
||||||
let context = component.context
|
let context = component.context
|
||||||
|
let mode = self.mode
|
||||||
let signal: Signal<EnginePeer.Id?, NoError> = context.engine.peers.convertGroupToSupergroup(peerId: peer.id, additionalProcessing: { upgradedPeerId -> Signal<Never, NoError> in
|
let signal: Signal<EnginePeer.Id?, NoError> = context.engine.peers.convertGroupToSupergroup(peerId: peer.id, additionalProcessing: { upgradedPeerId -> Signal<Never, NoError> in
|
||||||
return context.engine.peers.setChannelForumMode(id: upgradedPeerId, isForum: true, displayForumAsTabs: displayForumAsTabs)
|
return context.engine.peers.setChannelForumMode(id: upgradedPeerId, isForum: true, displayForumAsTabs: mode == .tabs)
|
||||||
})
|
})
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { [weak self] error -> Signal<PeerId?, NoError> in
|
|> `catch` { [weak self] error -> Signal<PeerId?, NoError> in
|
||||||
@ -164,7 +210,6 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
case .tooManyChannels:
|
case .tooManyChannels:
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
let oldChannelsController = context.sharedContext.makeOldChannelsController(context: context, updatedPresentationData: nil, intent: .upgrade, completed: { result in
|
let oldChannelsController = context.sharedContext.makeOldChannelsController(context: context, updatedPresentationData: nil, intent: .upgrade, completed: { result in
|
||||||
|
|
||||||
})
|
})
|
||||||
controller.push(oldChannelsController)
|
controller.push(oldChannelsController)
|
||||||
}
|
}
|
||||||
@ -191,14 +236,20 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
self.isOn = false
|
self.isOn = false
|
||||||
self.state?.updated(transition: .easeInOut(duration: 0.2))
|
self.state?.updated(transition: .easeInOut(duration: 0.2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.environment?.controller()?.dismiss()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return false
|
||||||
} else {
|
} else {
|
||||||
let _ = component.context.engine.peers.setChannelForumMode(id: peer.id, isForum: true, displayForumAsTabs: displayForumAsTabs).startStandalone()
|
let _ = component.context.engine.peers.setChannelForumMode(id: component.peerId, isForum: true, displayForumAsTabs: self.mode == .tabs).startStandalone()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let _ = component.context.engine.peers.setChannelForumMode(id: peer.id, isForum: false, displayForumAsTabs: displayForumAsTabs).startStandalone()
|
let _ = component.context.engine.peers.setChannelForumMode(id: component.peerId, isForum: false, displayForumAsTabs: false).startStandalone()
|
||||||
}
|
}
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(component: ForumSettingsScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
func update(component: ForumSettingsScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
||||||
@ -212,7 +263,7 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
|
|
||||||
self.peerDisposable = (self.peerIdPromise.get()
|
self.peerDisposable = (self.peerIdPromise.get()
|
||||||
|> mapToSignal { peerId in
|
|> mapToSignal { peerId in
|
||||||
component.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
component.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -223,6 +274,9 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
self.isOn = channel.flags.contains(.isForum)
|
self.isOn = channel.flags.contains(.isForum)
|
||||||
if self.isOn {
|
if self.isOn {
|
||||||
self.mode = channel.flags.contains(.displayForumAsTabs) ? .tabs : .list
|
self.mode = channel.flags.contains(.displayForumAsTabs) ? .tabs : .list
|
||||||
|
self.initialOnMode = self.mode
|
||||||
|
} else {
|
||||||
|
self.initialOnMode = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.state?.updated()
|
self.state?.updated()
|
||||||
@ -421,8 +475,6 @@ final class ForumSettingsScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
let displayForumAsTabs = self.mode == .tabs
|
|
||||||
let _ = component.context.engine.peers.setChannelForumMode(id: component.peerId, isForum: true, displayForumAsTabs: displayForumAsTabs).startStandalone()
|
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -514,6 +566,14 @@ public final class ForumSettingsScreen: ViewControllerComponentContainer {
|
|||||||
}
|
}
|
||||||
componentView.scrollToTop()
|
componentView.scrollToTop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.attemptNavigation = { [weak self] complete in
|
||||||
|
guard let self, let componentView = self.node.hostView.componentView as? ForumSettingsScreenComponent.View else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentView.attemptNavigation(complete: complete)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
|
@ -29,6 +29,7 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
|||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let usdWithdrawRate: Int64
|
let usdWithdrawRate: Int64
|
||||||
|
let paidMessageCommissionPermille: Int
|
||||||
let peer: EnginePeer?
|
let peer: EnginePeer?
|
||||||
let initialPrice: StarsAmount?
|
let initialPrice: StarsAmount?
|
||||||
let completion: () -> Void
|
let completion: () -> Void
|
||||||
@ -36,12 +37,14 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
|||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
usdWithdrawRate: Int64,
|
usdWithdrawRate: Int64,
|
||||||
|
paidMessageCommissionPermille: Int,
|
||||||
peer: EnginePeer?,
|
peer: EnginePeer?,
|
||||||
initialPrice: StarsAmount?,
|
initialPrice: StarsAmount?,
|
||||||
completion: @escaping () -> Void
|
completion: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.usdWithdrawRate = usdWithdrawRate
|
self.usdWithdrawRate = usdWithdrawRate
|
||||||
|
self.paidMessageCommissionPermille = paidMessageCommissionPermille
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.initialPrice = initialPrice
|
self.initialPrice = initialPrice
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
@ -367,7 +370,7 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentAmount: StarsAmount = StarsAmount(value: Int64(self.starCount), nanos: 0)
|
let currentAmount: StarsAmount = StarsAmount(value: Int64(self.starCount), nanos: 0)
|
||||||
let starsScreen = component.context.sharedContext.makeStarsWithdrawalScreen(context: component.context, subject: .enterAmount(current: currentAmount, minValue: StarsAmount(value: 0, nanos: 0), fractionAfterCommission: 85, kind: .postSuggestion), completion: { [weak self] amount in
|
let starsScreen = component.context.sharedContext.makeStarsWithdrawalScreen(context: component.context, subject: .enterAmount(current: currentAmount, minValue: StarsAmount(value: 0, nanos: 0), fractionAfterCommission: component.paidMessageCommissionPermille / 10, kind: .postSuggestion), completion: { [weak self] amount in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -398,9 +401,9 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
|||||||
)),
|
)),
|
||||||
footer: AnyComponent(MultilineTextComponent(
|
footer: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.ChannelMessages_PriceSectionFooter,
|
string: environment.strings.ChannelMessages_PriceSectionFooterValue("\(component.paidMessageCommissionPermille / 10)").string,
|
||||||
font: Font.regular(13.0),
|
font: Font.regular(13.0),
|
||||||
textColor: environment.theme.list.freeTextColor
|
textColor: self.starCount == 0 ? .clear : environment.theme.list.freeTextColor
|
||||||
)),
|
)),
|
||||||
maximumNumberOfLines: 0
|
maximumNumberOfLines: 0
|
||||||
)),
|
)),
|
||||||
@ -497,6 +500,7 @@ public final class PostSuggestionsSettingsScreen: ViewControllerComponentContain
|
|||||||
super.init(context: context, component: PostSuggestionsSettingsScreenComponent(
|
super.init(context: context, component: PostSuggestionsSettingsScreenComponent(
|
||||||
context: context,
|
context: context,
|
||||||
usdWithdrawRate: configuration.usdWithdrawRate,
|
usdWithdrawRate: configuration.usdWithdrawRate,
|
||||||
|
paidMessageCommissionPermille: Int(configuration.paidMessageCommissionPermille),
|
||||||
peer: peer,
|
peer: peer,
|
||||||
initialPrice: initialPrice,
|
initialPrice: initialPrice,
|
||||||
completion: completion
|
completion: completion
|
||||||
|
@ -295,7 +295,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let amountValue = StarsAmount(value: fullValue / 1_000_000_000, nanos: Int32(fullValue % 1_000_000_000))
|
let amountValue = StarsAmount(value: fullValue / 1_000_000_000, nanos: Int32(fullValue % 1_000_000_000))
|
||||||
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SendMessage_AdjustmentSectionFooterValue("\(amountValue)").string, attributes: amountMarkdownAttributes, textAlignment: .natural))
|
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SendMessage_AdjustmentSectionFooterValue("\(amountValue)").string, attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||||
} else {
|
} else {
|
||||||
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SendMessage_AdjustmentSectionFooterEmpty, attributes: amountMarkdownAttributes, textAlignment: .natural))
|
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SendMessage_AdjustmentSectionFooterEmptyValue("\(fractionAfterCommission)").string, attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||||
}
|
}
|
||||||
amountFooter = AnyComponent(MultilineTextComponent(
|
amountFooter = AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(amountInfoString),
|
text: .plain(amountInfoString),
|
||||||
@ -389,6 +389,16 @@ private final class SheetContent: CombinedComponent {
|
|||||||
buttonAttributedString.addAttribute(.kern, value: 2.0, range: NSRange(range, in: buttonAttributedString.string))
|
buttonAttributedString.addAttribute(.kern, value: 2.0, range: NSRange(range, in: buttonAttributedString.string))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isButtonEnabled = false
|
||||||
|
let amount = state.amount ?? StarsAmount.zero
|
||||||
|
if amount > StarsAmount.zero {
|
||||||
|
isButtonEnabled = true
|
||||||
|
} else if case let .paidMessages(_, minValue, _, _) = context.component.mode {
|
||||||
|
if minValue <= 0 {
|
||||||
|
isButtonEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let button = button.update(
|
let button = button.update(
|
||||||
component: ButtonComponent(
|
component: ButtonComponent(
|
||||||
background: ButtonComponent.Background(
|
background: ButtonComponent.Background(
|
||||||
@ -401,7 +411,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
id: AnyHashable(0),
|
id: AnyHashable(0),
|
||||||
component: AnyComponent(MultilineTextComponent(text: .plain(buttonAttributedString)))
|
component: AnyComponent(MultilineTextComponent(text: .plain(buttonAttributedString)))
|
||||||
),
|
),
|
||||||
isEnabled: (state.amount ?? StarsAmount.zero) > StarsAmount.zero,
|
isEnabled: isButtonEnabled,
|
||||||
displaysProgress: false,
|
displaysProgress: false,
|
||||||
action: { [weak state] in
|
action: { [weak state] in
|
||||||
if let controller = controller() as? StarsWithdrawScreen, let amount = state?.amount {
|
if let controller = controller() as? StarsWithdrawScreen, let amount = state?.amount {
|
||||||
@ -815,18 +825,27 @@ private final class AmountFieldComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
guard let component = self.component else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if string.rangeOfCharacter(from: invalidAmountCharacters) != nil {
|
if string.rangeOfCharacter(from: invalidAmountCharacters) != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var acceptZero = false
|
||||||
|
if let minValue = component.minValue, minValue <= 0 {
|
||||||
|
acceptZero = true
|
||||||
|
}
|
||||||
|
|
||||||
var newText = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
|
var newText = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
|
||||||
if newText == "0" || (newText.count > 1 && newText.hasPrefix("0")) {
|
if (newText == "0" && !acceptZero) || (newText.count > 1 && newText.hasPrefix("0")) {
|
||||||
newText.removeFirst()
|
newText.removeFirst()
|
||||||
textField.text = newText
|
textField.text = newText
|
||||||
self.textChanged(self.textField)
|
self.textChanged(self.textField)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let component = self.component {
|
|
||||||
let amount: Int64?
|
let amount: Int64?
|
||||||
if !newText.isEmpty, let value = Int64(normalizeArabicNumeralString(newText, type: .western)) {
|
if !newText.isEmpty, let value = Int64(normalizeArabicNumeralString(newText, type: .western)) {
|
||||||
amount = value
|
amount = value
|
||||||
@ -839,7 +858,7 @@ private final class AmountFieldComponent: Component {
|
|||||||
self.animateError()
|
self.animateError()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4804,6 +4804,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if strongSelf.navigationBar?.contentNode != nil {
|
if strongSelf.navigationBar?.contentNode != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if strongSelf.chatDisplayNode.leftPanel != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,8 +694,11 @@ extension ChatControllerImpl {
|
|||||||
upgradedToPeerId = migrationReference.peerId
|
upgradedToPeerId = migrationReference.peerId
|
||||||
}
|
}
|
||||||
if let previous = strongSelf.state.peerView, let channel = previous.peers[previous.peerId] as? TelegramChannel, !channel.isForumOrMonoForum, let updatedChannel = peerView.peers[peerView.peerId] as? TelegramChannel, updatedChannel.isForumOrMonoForum {
|
if let previous = strongSelf.state.peerView, let channel = previous.peers[previous.peerId] as? TelegramChannel, !channel.isForumOrMonoForum, let updatedChannel = peerView.peers[peerView.peerId] as? TelegramChannel, updatedChannel.isForumOrMonoForum {
|
||||||
|
if updatedChannel.isForum && updatedChannel.flags.contains(.displayForumAsTabs) {
|
||||||
|
} else {
|
||||||
movedToForumTopics = true
|
movedToForumTopics = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var shouldDismiss = false
|
var shouldDismiss = false
|
||||||
if let previous = strongSelf.state.peerView, let group = previous.peers[previous.peerId] as? TelegramGroup, group.membership != .Removed, let updatedGroup = peerView.peers[peerView.peerId] as? TelegramGroup, updatedGroup.membership == .Removed {
|
if let previous = strongSelf.state.peerView, let group = previous.peers[previous.peerId] as? TelegramGroup, group.membership != .Removed, let updatedGroup = peerView.peers[peerView.peerId] as? TelegramGroup, updatedGroup.membership == .Removed {
|
||||||
@ -761,6 +764,7 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
var starGiftsAvailable = false
|
var starGiftsAvailable = false
|
||||||
var peerDiscussionId: PeerId?
|
var peerDiscussionId: PeerId?
|
||||||
|
var peerMonoforumId: PeerId?
|
||||||
var peerGeoLocation: PeerGeoLocation?
|
var peerGeoLocation: PeerGeoLocation?
|
||||||
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
||||||
if case .broadcast = peer.info {
|
if case .broadcast = peer.info {
|
||||||
@ -771,6 +775,9 @@ extension ChatControllerImpl {
|
|||||||
if case let .known(value) = cachedData.linkedDiscussionPeerId {
|
if case let .known(value) = cachedData.linkedDiscussionPeerId {
|
||||||
peerDiscussionId = value
|
peerDiscussionId = value
|
||||||
}
|
}
|
||||||
|
if !peer.isMonoForum {
|
||||||
|
peerMonoforumId = peer.linkedMonoforumId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var renderedPeer: RenderedPeer?
|
var renderedPeer: RenderedPeer?
|
||||||
var contactStatus: ChatContactStatus?
|
var contactStatus: ChatContactStatus?
|
||||||
@ -921,13 +928,14 @@ extension ChatControllerImpl {
|
|||||||
explicitelyCanPinMessages = true
|
explicitelyCanPinMessages = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.preloadHistoryPeerId != peerDiscussionId {
|
let preloadHistoryPeerId = peerMonoforumId ?? peerDiscussionId
|
||||||
strongSelf.preloadHistoryPeerId = peerDiscussionId
|
if strongSelf.preloadHistoryPeerId != preloadHistoryPeerId {
|
||||||
if let peerDiscussionId = peerDiscussionId, let channel = peerView.peers[peerView.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
strongSelf.preloadHistoryPeerId = preloadHistoryPeerId
|
||||||
|
if let preloadHistoryPeerId, let channel = peerView.peers[peerView.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
||||||
let combinedDisposable = DisposableSet()
|
let combinedDisposable = DisposableSet()
|
||||||
strongSelf.preloadHistoryPeerIdDisposable.set(combinedDisposable)
|
strongSelf.preloadHistoryPeerIdDisposable.set(combinedDisposable)
|
||||||
combinedDisposable.add(context.account.viewTracker.polledChannel(peerId: peerDiscussionId).startStrict())
|
combinedDisposable.add(context.account.viewTracker.polledChannel(peerId: preloadHistoryPeerId).startStrict())
|
||||||
combinedDisposable.add(context.account.addAdditionalPreloadHistoryPeerId(peerId: peerDiscussionId))
|
combinedDisposable.add(context.account.addAdditionalPreloadHistoryPeerId(peerId: preloadHistoryPeerId))
|
||||||
} else {
|
} else {
|
||||||
strongSelf.preloadHistoryPeerIdDisposable.set(nil)
|
strongSelf.preloadHistoryPeerIdDisposable.set(nil)
|
||||||
}
|
}
|
||||||
@ -1559,6 +1567,7 @@ extension ChatControllerImpl {
|
|||||||
strongSelf.state.threadInfo = messageAndTopic.threadData?.info
|
strongSelf.state.threadInfo = messageAndTopic.threadData?.info
|
||||||
|
|
||||||
var peerDiscussionId: PeerId?
|
var peerDiscussionId: PeerId?
|
||||||
|
var peerMonoforumId: PeerId?
|
||||||
var peerGeoLocation: PeerGeoLocation?
|
var peerGeoLocation: PeerGeoLocation?
|
||||||
var currentSendAsPeerId: PeerId?
|
var currentSendAsPeerId: PeerId?
|
||||||
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
||||||
@ -1569,6 +1578,8 @@ extension ChatControllerImpl {
|
|||||||
currentSendAsPeerId = nil
|
currentSendAsPeerId = nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
peerMonoforumId = peer.linkedMonoforumId
|
||||||
|
|
||||||
currentSendAsPeerId = cachedData.sendAsPeerId
|
currentSendAsPeerId = cachedData.sendAsPeerId
|
||||||
if case .group = peer.info {
|
if case .group = peer.info {
|
||||||
peerGeoLocation = cachedData.peerGeoLocation
|
peerGeoLocation = cachedData.peerGeoLocation
|
||||||
@ -1610,10 +1621,11 @@ extension ChatControllerImpl {
|
|||||||
explicitelyCanPinMessages = true
|
explicitelyCanPinMessages = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.preloadHistoryPeerId != peerDiscussionId {
|
let preloadHistoryPeerId = peerMonoforumId ?? peerDiscussionId
|
||||||
strongSelf.preloadHistoryPeerId = peerDiscussionId
|
if strongSelf.preloadHistoryPeerId != preloadHistoryPeerId {
|
||||||
if let peerDiscussionId = peerDiscussionId {
|
strongSelf.preloadHistoryPeerId = preloadHistoryPeerId
|
||||||
strongSelf.preloadHistoryPeerIdDisposable.set(context.account.addAdditionalPreloadHistoryPeerId(peerId: peerDiscussionId))
|
if let preloadHistoryPeerId {
|
||||||
|
strongSelf.preloadHistoryPeerIdDisposable.set(context.account.addAdditionalPreloadHistoryPeerId(peerId: preloadHistoryPeerId))
|
||||||
} else {
|
} else {
|
||||||
strongSelf.preloadHistoryPeerIdDisposable.set(nil)
|
strongSelf.preloadHistoryPeerIdDisposable.set(nil)
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
private var chatTranslationPanel: ChatTranslationPanelNode?
|
private var chatTranslationPanel: ChatTranslationPanelNode?
|
||||||
|
|
||||||
private var leftPanelContainer: ChatControllerTitlePanelNodeContainer
|
private var leftPanelContainer: ChatControllerTitlePanelNodeContainer
|
||||||
private var leftPanel: (component: AnyComponentWithIdentity<ChatSidePanelEnvironment>, view: ComponentView<ChatSidePanelEnvironment>)?
|
private(set) var leftPanel: (component: AnyComponentWithIdentity<ChatSidePanelEnvironment>, view: ComponentView<ChatSidePanelEnvironment>)?
|
||||||
|
|
||||||
private(set) var inputPanelNode: ChatInputPanelNode?
|
private(set) var inputPanelNode: ChatInputPanelNode?
|
||||||
private(set) var inputPanelOverscrollNode: ChatInputPanelOverscrollNode?
|
private(set) var inputPanelOverscrollNode: ChatInputPanelOverscrollNode?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user