Merge branch 'beta'

This commit is contained in:
Ali 2019-12-16 23:09:46 +04:00
commit 5893e47f23
33 changed files with 3573 additions and 3384 deletions

View File

@ -5197,6 +5197,8 @@ Any member of this group will be able to see messages in the channel.";
"OldChannels.Title" = "Limit Reached";
"OldChannels.NoticeTitle" = "Too Many Groups and Channels";
"OldChannels.NoticeText" = "Sorry, you are member of too many groups and channels.\nPlease leave some before joining new one.";
"OldChannels.NoticeCreateText" = "Sorry, you are member of too many groups and channels.\nPlease leave some before creating a new one.";
"OldChannels.NoticeUpgradeText" = "Sorry, you are a member of too many groups and channels.\nFor technical reasons, you need to leave some first before changing this setting in your groups.";
"OldChannels.ChannelsHeader" = "MOST INACTIVE";
"OldChannels.Leave" = "Leave";

View File

@ -177,7 +177,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, source: ChatC
if case .search = source {
if let channel = peer as? TelegramChannel {
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_JoinChannel, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in
var createSignal = joinChannel(account: context.account, peerId: peerId)
var createSignal = context.peerChannelMemberCategoriesContextsManager.join(account: context.account, peerId: peerId)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }

View File

@ -3794,22 +3794,22 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
public func ensureItemNodeVisible(_ node: ListViewItemNode, animated: Bool = true, overflow: CGFloat = 0.0) {
public func ensureItemNodeVisible(_ node: ListViewItemNode, animated: Bool = true, overflow: CGFloat = 0.0, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
if let index = node.index {
if node.apparentHeight > self.visibleSize.height - self.insets.top - self.insets.bottom {
if node.frame.maxY > self.visibleSize.height - self.insets.bottom {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: ListViewAnimationCurve.Default(duration: 0.25), directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else if node.frame.minY < self.insets.top && overflow > 0.0 {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: true, curve: ListViewAnimationCurve.Default(duration: 0.25), directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: true, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}
} else {
if self.experimentalSnapScrollToItem {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.visible, animated: animated, curve: ListViewAnimationCurve.Default(duration: nil), directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else {
if node.frame.minY < self.insets.top {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(overflow), animated: animated, curve: ListViewAnimationCurve.Default(duration: 0.25), directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else if node.frame.maxY > self.visibleSize.height - self.insets.bottom {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: ListViewAnimationCurve.Default(duration: 0.25), directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}
}
}

View File

@ -537,8 +537,8 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
}
}
public func ensureItemNodeVisible(_ itemNode: ListViewItemNode, animated: Bool = true) {
(self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated)
public func ensureItemNodeVisible(_ itemNode: ListViewItemNode, animated: Bool = true, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
(self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated, curve: curve)
}
public func afterLayout(_ f: @escaping () -> Void) {

View File

@ -418,6 +418,9 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
if let searchNode = self.searchNode {
var layout = layout
layout = layout.addedInsets(insets: additionalInsets)
searchNode.updateLayout(layout: layout, navigationBarHeight: navigationBarHeight, transition: transition)
}
@ -652,7 +655,6 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
emptyStateNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak emptyStateNode] _ in
emptyStateNode?.removeFromSupernode()
})
self.listNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.emptyStateNode = nil
}
}

View File

@ -18,6 +18,7 @@ static_library(
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/ShareController:ShareController",
"//submodules/SelectablePeerNode:SelectablePeerNode",
"//submodules/PeerInfoUI:PeerInfoUI",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -10,6 +10,7 @@ import TelegramPresentationData
import AccountContext
import AlertUI
import PresentationDataUtils
import PeerInfoUI
public final class JoinLinkPreviewController: ViewController {
private var controllerNode: JoinLinkPreviewControllerNode {
@ -21,14 +22,18 @@ public final class JoinLinkPreviewController: ViewController {
private let context: AccountContext
private let link: String
private let navigateToPeer: (PeerId) -> Void
private let parentNavigationController: NavigationController?
private var resolvedState: ExternalJoiningChatState?
private var presentationData: PresentationData
private let disposable = MetaDisposable()
public init(context: AccountContext, link: String, navigateToPeer: @escaping (PeerId) -> Void) {
public init(context: AccountContext, link: String, navigateToPeer: @escaping (PeerId) -> Void, parentNavigationController: NavigationController?, resolvedState: ExternalJoiningChatState? = nil) {
self.context = context
self.link = link
self.navigateToPeer = navigateToPeer
self.parentNavigationController = parentNavigationController
self.resolvedState = resolvedState
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -59,9 +64,18 @@ public final class JoinLinkPreviewController: ViewController {
self?.join()
}
self.displayNodeDidLoad()
self.disposable.set((joinLinkInformation(self.link, account: self.context.account)
let signal: Signal<ExternalJoiningChatState, NoError>
if let resolvedState = self.resolvedState {
signal = .single(resolvedState)
} else {
signal = joinLinkInformation(self.link, account: self.context.account)
}
self.disposable.set((signal
|> deliverOnMainQueue).start(next: { [weak self] result in
if let strongSelf = self {
strongSelf.resolvedState = result
switch result {
case let .invite(title, photoRepresentation, participantsCount, participants):
let data = JoinLinkPreviewData(isGroup: participants != nil, isJoined: false)
@ -112,7 +126,19 @@ public final class JoinLinkPreviewController: ViewController {
}, error: { [weak self] error in
if let strongSelf = self {
if case .tooMuchJoined = error {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Join_ChannelsTooMuch, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
if let parentNavigationController = strongSelf.parentNavigationController {
let context = strongSelf.context
let link = strongSelf.link
let navigateToPeer = strongSelf.navigateToPeer
let resolvedState = strongSelf.resolvedState
parentNavigationController.pushViewController(oldChannelsController(context: strongSelf.context, intent: .join, completed: { [weak parentNavigationController] value in
if value {
(parentNavigationController?.viewControllers.last as? ViewController)?.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: navigateToPeer, parentNavigationController: parentNavigationController, resolvedState: resolvedState), in: .window(.root))
}
}))
} else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Join_ChannelsTooMuch, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
strongSelf.dismiss()
}
}

View File

@ -791,6 +791,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
var dismissImpl: (() -> Void)?
var dismissInputImpl: (() -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var errorImpl: (() -> Void)?
var scrollToRankImpl: (() -> Void)?
@ -1152,7 +1153,8 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
if case .restricted = error, let admin = adminView.peers[adminView.peerId] {
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
} else if case .tooMuchJoined = error {
text = presentationData.strings.Group_ErrorSupergroupConversionNotPossible
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
return
}
presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}
@ -1192,6 +1194,9 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
presentControllerImpl = { [weak controller] value, presentationArguments in
controller?.present(value, in: .window(.root), with: presentationArguments)
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
let hapticFeedback = HapticFeedback()
errorImpl = { [weak controller] in

View File

@ -390,6 +390,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
var dismissImpl: (() -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
let peerView = Promise<PeerView>()
peerView.set(context.account.viewTracker.peerView(peerId))
@ -654,7 +655,15 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
if peerId.namespace == Namespaces.Peer.CloudGroup {
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
|> `catch` { error -> Signal<PeerId?, NoError> in
switch error {
case .tooManyChannels:
Queue.mainQueue().async {
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
}
default:
break
}
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in
@ -679,6 +688,12 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
upgradedToSupergroup(upgradedPeerId, {
dismissImpl?()
})
} else {
updateState { current in
var current = current
current.updating = false
return current
}
}
}, error: { _ in
updateState { current in
@ -748,5 +763,8 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
presentControllerImpl = { [weak controller] value, presentationArguments in
controller?.present(value, in: .window(.root), with: presentationArguments)
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
return controller
}

View File

@ -315,8 +315,13 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
var updatedPeerId: PeerId? = nil
if let legacyGroup = groupPeer as? TelegramGroup {
applySignal = convertGroupToSupergroup(account: context.account, peerId: legacyGroup.id)
|> mapError { _ -> ChannelDiscussionGroupError in
return .generic
|> mapError { error -> ChannelDiscussionGroupError in
switch error {
case .tooManyChannels:
return .tooManyChannels
default:
return .generic
}
}
|> deliverOnMainQueue
|> mapToSignal { resultPeerId -> Signal<Bool, ChannelDiscussionGroupError> in
@ -378,6 +383,8 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
applyGroupDisposable.set((applySignal
|> deliverOnMainQueue).start(error: { error in
switch error {
case .tooManyChannels:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
case .generic, .hasNotPermissions:
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)

View File

@ -413,6 +413,8 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
var dismissImpl: (() -> Void)?
var proceedImpl: (() -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
let disposable = MetaDisposable()
let contentNode = ChannelOwnershipTransferAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: presentationData.strings, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
@ -453,7 +455,14 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
} else if let peer = peer as? TelegramGroup {
signal = convertGroupToSupergroup(account: context.account, peerId: peer.id)
|> map(Optional.init)
|> mapError { _ in ChannelOwnershipTransferError.generic }
|> mapError { error -> ChannelOwnershipTransferError in
switch error {
case .tooManyChannels:
return .tooMuchJoined
default:
return .generic
}
}
|> deliverOnMainQueue
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ChannelOwnershipTransferError> in
guard let upgradedPeerId = upgradedPeerId else {
@ -479,6 +488,9 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
var errorTextAndActions: (String, [TextAlertAction])?
switch error {
case .tooMuchJoined:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
return
case .invalidPassword:
contentNode?.animateError()
case .limitExceeded:
@ -502,6 +514,11 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
}
}))
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
return controller
}

View File

@ -472,6 +472,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var dismissInputImpl: (() -> Void)?
var resetSlowmodeVisualValueImpl: (() -> Void)?
let actionsDisposable = DisposableSet()
@ -728,17 +729,15 @@ public func channelPermissionsController(context: AccountContext, peerId origina
presentControllerImpl?(progress, nil)
let signal = convertGroupToSupergroup(account: context.account, peerId: view.peerId)
|> mapError { _ -> UpdateChannelSlowModeError in
return .generic
}
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, UpdateChannelSlowModeError> in
return .single(nil)
|> mapError { error -> UpdateChannelSlowModeError in
switch error {
case .tooManyChannels:
return .tooManyChannels
default:
return .generic
}
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, UpdateChannelSlowModeError> in
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
return updateChannelSlowModeInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: upgradedPeerId, timeout: modifiedSlowmodeTimeout == 0 ? nil : value)
|> mapToSignal { _ -> Signal<PeerId?, UpdateChannelSlowModeError> in
return .complete()
@ -752,8 +751,21 @@ public func channelPermissionsController(context: AccountContext, peerId origina
upgradedToSupergroupImpl?(peerId, {})
}
progress?.dismiss()
}, error: { [weak progress] _ in
}, error: { [weak progress] error in
progress?.dismiss()
updateState { state in
var state = state
state.modifiedSlowmodeTimeout = nil
return state
}
resetSlowmodeVisualValueImpl?()
switch error {
case .tooManyChannels:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
default:
break
}
}))
}
})
@ -853,6 +865,16 @@ public func channelPermissionsController(context: AccountContext, peerId origina
dismissInputImpl = { [weak controller] in
controller?.view.endEditing(true)
}
resetSlowmodeVisualValueImpl = { [weak controller] in
guard let controller = controller else {
return
}
controller.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatSlowmodeItemNode {
itemNode.forceSetValue(0)
}
}
}
upgradedToSupergroupImpl = { [weak controller] upgradedPeerId, f in
guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else {
return

View File

@ -829,6 +829,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
var displayPrivateLinkMenuImpl: ((String) -> Void)?
var scrollToPublicLinkTextImpl: (() -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var clearHighlightImpl: (() -> Void)?
let actionsDisposable = DisposableSet()
@ -1094,14 +1095,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
_ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start()
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
return updateAddressName(account: context.account, domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
@ -1110,6 +1104,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
return .complete()
}
|> then(.single(upgradedPeerId))
|> castError(ConvertGroupToSupergroupError.self)
}
|> deliverOnMainQueue
@ -1122,11 +1117,16 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
} else {
dismissImpl?()
}
}, error: { _ in
}, error: { error in
updateState { state in
return state.withUpdatedUpdatingAddressName(false)
}
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
switch error {
case .tooManyChannels:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
default:
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}
}))
}
@ -1328,6 +1328,9 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
clearHighlightImpl = { [weak controller] in
controller?.clearItemNodesHighlight(animated: true)
}

View File

@ -105,6 +105,12 @@ class ChatSlowmodeItemNode: ListViewItemNode {
self.textNodes.forEach(self.addSubnode)
}
func forceSetValue(_ value: Int32) {
if let sliderView = self.sliderView {
sliderView.value = CGFloat(value)
}
}
func updateSliderView() {
if let sliderView = self.sliderView, let item = self.item {
sliderView.maximumValue = CGFloat(allowedValues.count - 1)

View File

@ -1772,7 +1772,15 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
case .groupFull:
let signal = convertGroupToSupergroup(account: context.account, peerId: peerView.peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
|> `catch` { error -> Signal<PeerId?, NoError> in
switch error {
case .tooManyChannels:
Queue.mainQueue().async {
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
}
default:
break
}
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in

View File

@ -124,6 +124,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
statePromise.set(stateValue.modify { f($0) })
}
var pushControllerImpl: ((ViewController) -> Void)?
var dismissImpl: (() -> Void)?
let actionsDisposable = DisposableSet()
@ -161,14 +162,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
if let value = value, value != defaultValue {
if peerId.namespace == Namespaces.Peer.CloudGroup {
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
return updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: upgradedPeerId, historyAvailableForNewMembers: value)
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
@ -177,6 +171,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
return .complete()
}
|> then(.single(upgradedPeerId))
|> castError(ConvertGroupToSupergroupError.self)
}
|> deliverOnMainQueue
applyDisposable.set((signal
@ -186,6 +181,13 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
dismissImpl?()
})
}
}, error: { error in
switch error {
case .tooManyChannels:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
default:
break
}
}))
} else {
applyDisposable.set((updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: peerId, historyAvailableForNewMembers: value)
@ -213,5 +215,8 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
controller?.view.endEditing(true)
controller?.dismiss()
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
return controller
}

View File

@ -61,11 +61,11 @@ func localizedOldChannelDate(peer: InactiveChannel, strings: PresentationStrings
private final class OldChannelsItemArguments {
let context: AccountContext
let togglePeer: (PeerId) -> Void
let togglePeer: (PeerId, Bool) -> Void
init(
context: AccountContext,
togglePeer: @escaping (PeerId) -> Void
togglePeer: @escaping (PeerId, Bool) -> Void
) {
self.context = context
self.togglePeer = togglePeer
@ -174,7 +174,7 @@ private enum OldChannelsEntry: ItemListNodeEntry {
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
case let .peer(_, peer, selected):
return ContactsPeerItem(presentationData: presentationData, style: .blocks, sectionId: self.section, sortOrder: .firstLast, displayOrder: .firstLast, context: arguments.context, peerMode: .peer, peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .custom(localizedOldChannelDate(peer: peer, strings: presentationData.strings)), badge: nil, enabled: true, selection: ContactsPeerItemSelection.selectable(selected: selected), editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), options: [], actionIcon: .none, index: nil, header: nil, action: { _ in
arguments.togglePeer(peer.peer.id)
arguments.togglePeer(peer.peer.id, true)
}, setPeerIdWithRevealedOptions: nil, deletePeer: nil, itemHighlighting: nil, contextAction: nil)
}
}
@ -185,13 +185,23 @@ private struct OldChannelsState: Equatable {
var isSearching: Bool = false
}
private func oldChannelsEntries(presentationData: PresentationData, state: OldChannelsState, peers: [InactiveChannel]?) -> [OldChannelsEntry] {
private func oldChannelsEntries(presentationData: PresentationData, state: OldChannelsState, peers: [InactiveChannel]?, intent: OldChannelsControllerIntent) -> [OldChannelsEntry] {
var entries: [OldChannelsEntry] = []
let noticeText: String
switch intent {
case .join:
noticeText = presentationData.strings.OldChannels_NoticeText
case .create:
noticeText = presentationData.strings.OldChannels_NoticeCreateText
case .upgrade:
noticeText = presentationData.strings.OldChannels_NoticeUpgradeText
}
entries.append(.info(presentationData.strings.OldChannels_NoticeTitle, noticeText))
if let peers = peers, !peers.isEmpty {
entries.append(.info(presentationData.strings.OldChannels_NoticeTitle, presentationData.strings.OldChannels_NoticeText))
entries.append(.peersHeader(presentationData.strings.OldChannels_ChannelsHeader))
for peer in peers {
entries.append(.peer(entries.count, peer, state.selectedPeers.contains(peer.peer.id)))
}
@ -316,7 +326,13 @@ private final class OldChannelsControllerImpl: ItemListController {
}
}
public func oldChannelsController(context: AccountContext) -> ViewController {
public enum OldChannelsControllerIntent {
case join
case create
case upgrade
}
public func oldChannelsController(context: AccountContext, intent: OldChannelsControllerIntent, completed: @escaping (Bool) -> Void = { _ in }) -> ViewController {
let initialState = OldChannelsState()
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState)
@ -329,23 +345,30 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
var dismissImpl: (() -> Void)?
var setDisplayNavigationBarImpl: ((Bool) -> Void)?
var ensurePeerVisibleImpl: ((PeerId) -> Void)?
let actionsDisposable = DisposableSet()
let arguments = OldChannelsItemArguments(
context: context,
togglePeer: { peerId in
togglePeer: { peerId, ensureVisible in
var hasSelectedPeers = false
var didSelect = false
updateState { state in
var state = state
if state.selectedPeers.contains(peerId) {
state.selectedPeers.remove(peerId)
} else {
state.selectedPeers.insert(peerId)
didSelect = true
}
hasSelectedPeers = !state.selectedPeers.isEmpty
return state
}
updateHasSelectedPeersImpl?(hasSelectedPeers)
if didSelect && ensureVisible {
ensurePeerVisibleImpl?(peerId)
}
}
)
@ -395,7 +418,7 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
setDisplayNavigationBarImpl?(false)
}
}, peers: peersPromise.get() |> map { $0 ?? [] }, selectedPeerIds: selectedPeerIds, togglePeer: { peerId in
arguments.togglePeer(peerId)
arguments.togglePeer(peerId, false)
})
let peersAreEmpty = peers == nil
@ -407,7 +430,7 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
}
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: oldChannelsEntries(presentationData: presentationData, state: state, peers: peers), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up), crossfadeState: peersAreEmptyUpdated, animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: oldChannelsEntries(presentationData: presentationData, state: state, peers: peers, intent: intent), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up), crossfadeState: peersAreEmptyUpdated, animateChanges: false)
return (controllerState, (listState, arguments))
}
@ -430,19 +453,22 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
return context.account.postbox.transaction { transaction -> Void in
if let peers = peers {
for peer in peers {
if transaction.getPeer(peer.peer.id) == nil {
updatePeers(transaction: transaction, peers: [peer.peer], update: { _, updated in
return updated
})
if state.selectedPeers.contains(peer.peer.id) {
if transaction.getPeer(peer.peer.id) == nil {
updatePeers(transaction: transaction, peers: [peer.peer], update: { _, updated in
return updated
})
}
removePeerChat(account: context.account, transaction: transaction, mediaBox: context.account.postbox.mediaBox, peerId: peer.peer.id, reportChatSpam: false, deleteGloballyIfPossible: false)
}
removePeerChat(account: context.account, transaction: transaction, mediaBox: context.account.postbox.mediaBox, peerId: peer.peer.id, reportChatSpam: false, deleteGloballyIfPossible: false)
}
}
}
}
|> deliverOnMainQueue).start()
dismissImpl?()
|> deliverOnMainQueue).start(completed: {
completed(true)
dismissImpl?()
})
}
dismissImpl = { [weak controller] in
@ -451,6 +477,16 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
setDisplayNavigationBarImpl = { [weak controller] display in
controller?.setDisplayNavigationBar(display, transition: .animated(duration: 0.5, curve: .spring))
}
ensurePeerVisibleImpl = { [weak controller] peerId in
guard let controller = controller else {
return
}
controller.forEachItemNode { itemNode in
if let itemNode = itemNode as? ContactsPeerItemNode, let peer = itemNode.chatPeer, peer.id == peerId {
controller.ensureItemNodeVisible(itemNode, curve: .Spring(duration: 0.3))
}
}
}
return controller
}

View File

@ -195,8 +195,16 @@ private final class OldChannelsSearchContainerNode: SearchDisplayControllerConte
self.addSubnode(self.listNode)
let interaction = OldChannelsSearchInteraction(togglePeer: { peerId in
let interaction = OldChannelsSearchInteraction(togglePeer: { [weak self] peerId in
togglePeer(peerId)
if let strongSelf = self {
strongSelf.listNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ContactsPeerItemNode, let peer = itemNode.chatPeer, peer.id == peerId {
strongSelf.listNode.ensureItemNodeVisible(itemNode, curve: .Spring(duration: 0.3))
}
}
}
})
let queryAndFoundItems: Signal<(String, [OldChannelsSearchEntry])?, NoError> = combineLatest(self.searchQuery.get(), peers, selectedPeerIds)

View File

@ -234,6 +234,8 @@ public final class MediaBox {
let pathsTo = self.storePathsForId(to)
link(pathsFrom.partial, pathsTo.partial)
link(pathsFrom.complete, pathsTo.complete)
unlink(pathsFrom.partial)
unlink(pathsFrom.complete)
}
}

View File

@ -13,6 +13,10 @@ public enum CreateChannelError {
}
private func createChannel(account: Account, title: String, description: String?, isSupergroup:Bool, location: (latitude: Double, longitude: Double, address: String)? = nil) -> Signal<PeerId, CreateChannelError> {
#if DEBUG
return .fail(.tooMuchJoined)
#endif
return account.postbox.transaction { transaction -> Signal<PeerId, CreateChannelError> in
var flags: Int32 = 0
if isSupergroup {

View File

@ -28,6 +28,9 @@ public enum ExternalJoiningChatState {
}
public func joinChatInteractively(with hash: String, account: Account) -> Signal <PeerId?, JoinLinkError> {
#if DEBUG
return .fail(.tooMuchJoined)
#endif
return account.network.request(Api.functions.messages.importChatInvite(hash: hash))
|> mapError { error -> JoinLinkError in
if error.errorDescription == "CHANNELS_TOO_MUCH" {

View File

@ -36,6 +36,7 @@ public enum ChannelDiscussionGroupError {
case generic
case groupHistoryIsCurrentlyPrivate
case hasNotPermissions
case tooManyChannels
}
public func updateGroupDiscussionForChannel(network: Network, postbox: Postbox, channelId: PeerId?, groupId: PeerId?) -> Signal<Bool, ChannelDiscussionGroupError> {

View File

@ -6,6 +6,7 @@ import SyncCore
public enum UpdateChannelSlowModeError {
case generic
case tooManyChannels
}
public func updateChannelSlowModeInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, timeout: Int32?) -> Signal<Void, UpdateChannelSlowModeError> {

View File

@ -137,7 +137,11 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
let text: String
switch error {
case .tooMuchJoined:
strongSelf.interfaceInteraction?.getNavigationController()?.pushViewController(oldChannelsController(context: context))
strongSelf.interfaceInteraction?.getNavigationController()?.pushViewController(oldChannelsController(context: context, intent: .join, completed: { value in
if value {
self?.buttonPressed()
}
}))
return
default:
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {

View File

@ -787,7 +787,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
if let strongSelf = self {
strongSelf.openPeer(peerId: peerId, peer: nil)
}
}), nil)
}, parentNavigationController: strongSelf.getNavigationController()), nil)
case let .localization(identifier):
strongSelf.presentController(LanguageLinkPreviewController(context: strongSelf.context, identifier: identifier), nil)
case .proxy, .confirmationCode, .cancelAccountReset, .share:

View File

@ -205,6 +205,7 @@ public func createChannelController(context: AccountContext) -> ViewController {
}
var replaceControllerImpl: ((ViewController) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var endEditingImpl: (() -> Void)?
@ -273,7 +274,8 @@ public func createChannelController(context: AccountContext) -> ViewController {
case .generic, .tooMuchLocationBasedGroups:
text = presentationData.strings.Login_UnknownError
case .tooMuchJoined:
text = presentationData.strings.CreateGroup_ChannelsTooMuch
pushControllerImpl?(oldChannelsController(context: context, intent: .create))
return
case .restricted:
text = presentationData.strings.Common_ActionNotAllowedError
default:
@ -384,6 +386,9 @@ public func createChannelController(context: AccountContext) -> ViewController {
replaceControllerImpl = { [weak controller] value in
(controller?.navigationController as? NavigationController)?.replaceAllButRootController(value, animated: true)
}
pushControllerImpl = { [weak controller] value in
controller?.push(value)
}
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}

View File

@ -530,7 +530,8 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
case .restricted:
text = presentationData.strings.Common_ActionNotAllowedError
case .tooMuchJoined:
text = presentationData.strings.CreateGroup_ChannelsTooMuch
pushImpl?(oldChannelsController(context: context, intent: .create))
return
case .tooMuchLocationBasedGroups:
text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch
default:

View File

@ -136,7 +136,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
dismissInput()
present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in
openPeer(peerId, .chat(textInputState: nil, subject: nil))
}), nil)
}, parentNavigationController: navigationController), nil)
case let .localization(identifier):
dismissInput()
present(LanguageLinkPreviewController(context: context, identifier: identifier), nil)

View File

@ -64,7 +64,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
case let .join(link):
controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in
openResolvedPeerImpl(peerId, .chat(textInputState: nil, subject: nil))
}), in: .window(.root))
}, parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root))
case let .wallet(address, amount, comment):
context.sharedContext.openWallet(context: context, walletContext: .send(address: address, amount: amount, comment: comment)) { c in
(controller.navigationController as? NavigationController)?.pushViewController(c)

View File

@ -448,12 +448,12 @@ public final class WalletStrings: Equatable {
public var Wallet_SecureStorageReset_Title: String { return self._s[218]! }
public var Wallet_Receive_CommentHeader: String { return self._s[219]! }
public var Wallet_Info_ReceiveGrams: String { return self._s[220]! }
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
}
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)