Fix issues in old channels revoke UI

This commit is contained in:
Ali 2019-12-16 23:07:41 +04:00
parent db5fb4b642
commit c7e91c9b62
33 changed files with 3648 additions and 3459 deletions

View File

@ -5175,6 +5175,8 @@ Any member of this group will be able to see messages in the channel.";
"OldChannels.Title" = "Limit Reached"; "OldChannels.Title" = "Limit Reached";
"OldChannels.NoticeTitle" = "Too Many Groups and Channels"; "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.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.ChannelsHeader" = "MOST INACTIVE";
"OldChannels.Leave" = "Leave"; "OldChannels.Leave" = "Leave";

View File

@ -177,7 +177,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, source: ChatC
if case .search = source { if case .search = source {
if let channel = peer as? TelegramChannel { 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 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)? var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }

View File

@ -3786,11 +3786,11 @@ 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 let index = node.index {
if node.apparentHeight > self.visibleSize.height - self.insets.top - self.insets.bottom { if node.apparentHeight > self.visibleSize.height - self.insets.top - self.insets.bottom {
if node.frame.maxY > self.visibleSize.height - 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 { }/* else if node.frame.minY < self.insets.top {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(0.0), 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(0.0), animated: true, curve: ListViewAnimationCurve.Default(duration: 0.25), directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}*/ }*/
@ -3799,9 +3799,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
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 }) 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 { } else {
if node.frame.minY < self.insets.top { 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 { } 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) { public func ensureItemNodeVisible(_ itemNode: ListViewItemNode, animated: Bool = true, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
(self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated) (self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated, curve: curve)
} }
public func afterLayout(_ f: @escaping () -> Void) { public func afterLayout(_ f: @escaping () -> Void) {

View File

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

View File

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

View File

@ -10,6 +10,7 @@ import TelegramPresentationData
import AccountContext import AccountContext
import AlertUI import AlertUI
import PresentationDataUtils import PresentationDataUtils
import PeerInfoUI
public final class JoinLinkPreviewController: ViewController { public final class JoinLinkPreviewController: ViewController {
private var controllerNode: JoinLinkPreviewControllerNode { private var controllerNode: JoinLinkPreviewControllerNode {
@ -21,14 +22,18 @@ public final class JoinLinkPreviewController: ViewController {
private let context: AccountContext private let context: AccountContext
private let link: String private let link: String
private let navigateToPeer: (PeerId) -> Void private let navigateToPeer: (PeerId) -> Void
private let parentNavigationController: NavigationController?
private var resolvedState: ExternalJoiningChatState?
private var presentationData: PresentationData private var presentationData: PresentationData
private let disposable = MetaDisposable() 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.context = context
self.link = link self.link = link
self.navigateToPeer = navigateToPeer self.navigateToPeer = navigateToPeer
self.parentNavigationController = parentNavigationController
self.resolvedState = resolvedState
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -59,9 +64,18 @@ public final class JoinLinkPreviewController: ViewController {
self?.join() self?.join()
} }
self.displayNodeDidLoad() 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 |> deliverOnMainQueue).start(next: { [weak self] result in
if let strongSelf = self { if let strongSelf = self {
strongSelf.resolvedState = result
switch result { switch result {
case let .invite(title, photoRepresentation, participantsCount, participants): case let .invite(title, photoRepresentation, participantsCount, participants):
let data = JoinLinkPreviewData(isGroup: participants != nil, isJoined: false) let data = JoinLinkPreviewData(isGroup: participants != nil, isJoined: false)
@ -112,7 +126,19 @@ public final class JoinLinkPreviewController: ViewController {
}, error: { [weak self] error in }, error: { [weak self] error in
if let strongSelf = self { if let strongSelf = self {
if case .tooMuchJoined = error { 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() strongSelf.dismiss()
} }
} }

View File

@ -791,6 +791,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
var dismissImpl: (() -> Void)? var dismissImpl: (() -> Void)?
var dismissInputImpl: (() -> Void)? var dismissInputImpl: (() -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var errorImpl: (() -> Void)? var errorImpl: (() -> Void)?
var scrollToRankImpl: (() -> 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] { if case .restricted = error, let admin = adminView.peers[adminView.peerId] {
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0 text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
} else if case .tooMuchJoined = error { } 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) 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 presentControllerImpl = { [weak controller] value, presentationArguments in
controller?.present(value, in: .window(.root), with: presentationArguments) controller?.present(value, in: .window(.root), with: presentationArguments)
} }
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
let hapticFeedback = HapticFeedback() let hapticFeedback = HapticFeedback()
errorImpl = { [weak controller] in errorImpl = { [weak controller] in

View File

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

View File

@ -315,8 +315,13 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
var updatedPeerId: PeerId? = nil var updatedPeerId: PeerId? = nil
if let legacyGroup = groupPeer as? TelegramGroup { if let legacyGroup = groupPeer as? TelegramGroup {
applySignal = convertGroupToSupergroup(account: context.account, peerId: legacyGroup.id) applySignal = convertGroupToSupergroup(account: context.account, peerId: legacyGroup.id)
|> mapError { _ -> ChannelDiscussionGroupError in |> mapError { error -> ChannelDiscussionGroupError in
return .generic switch error {
case .tooManyChannels:
return .tooManyChannels
default:
return .generic
}
} }
|> deliverOnMainQueue |> deliverOnMainQueue
|> mapToSignal { resultPeerId -> Signal<Bool, ChannelDiscussionGroupError> in |> mapToSignal { resultPeerId -> Signal<Bool, ChannelDiscussionGroupError> in
@ -378,6 +383,8 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
applyGroupDisposable.set((applySignal applyGroupDisposable.set((applySignal
|> deliverOnMainQueue).start(error: { error in |> deliverOnMainQueue).start(error: { error in
switch error { switch error {
case .tooManyChannels:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
case .generic, .hasNotPermissions: case .generic, .hasNotPermissions:
let presentationData = context.sharedContext.currentPresentationData.with { $0 } 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) 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 dismissImpl: (() -> Void)?
var proceedImpl: (() -> Void)? var proceedImpl: (() -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
let disposable = MetaDisposable() 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: { 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 { } else if let peer = peer as? TelegramGroup {
signal = convertGroupToSupergroup(account: context.account, peerId: peer.id) signal = convertGroupToSupergroup(account: context.account, peerId: peer.id)
|> map(Optional.init) |> map(Optional.init)
|> mapError { _ in ChannelOwnershipTransferError.generic } |> mapError { error -> ChannelOwnershipTransferError in
switch error {
case .tooManyChannels:
return .tooMuchJoined
default:
return .generic
}
}
|> deliverOnMainQueue |> deliverOnMainQueue
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ChannelOwnershipTransferError> in |> mapToSignal { upgradedPeerId -> Signal<PeerId?, ChannelOwnershipTransferError> in
guard let upgradedPeerId = upgradedPeerId else { guard let upgradedPeerId = upgradedPeerId else {
@ -479,6 +488,9 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
var errorTextAndActions: (String, [TextAlertAction])? var errorTextAndActions: (String, [TextAlertAction])?
switch error { switch error {
case .tooMuchJoined:
pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade))
return
case .invalidPassword: case .invalidPassword:
contentNode?.animateError() contentNode?.animateError()
case .limitExceeded: case .limitExceeded:
@ -502,6 +514,11 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
} }
})) }))
} }
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
return controller return controller
} }

View File

@ -472,6 +472,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
var presentControllerImpl: ((ViewController, Any?) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)? var pushControllerImpl: ((ViewController) -> Void)?
var dismissInputImpl: (() -> Void)? var dismissInputImpl: (() -> Void)?
var resetSlowmodeVisualValueImpl: (() -> Void)?
let actionsDisposable = DisposableSet() let actionsDisposable = DisposableSet()
@ -728,17 +729,15 @@ public func channelPermissionsController(context: AccountContext, peerId origina
presentControllerImpl?(progress, nil) presentControllerImpl?(progress, nil)
let signal = convertGroupToSupergroup(account: context.account, peerId: view.peerId) let signal = convertGroupToSupergroup(account: context.account, peerId: view.peerId)
|> mapError { _ -> UpdateChannelSlowModeError in |> mapError { error -> UpdateChannelSlowModeError in
return .generic switch error {
} case .tooManyChannels:
|> map(Optional.init) return .tooManyChannels
|> `catch` { _ -> Signal<PeerId?, UpdateChannelSlowModeError> in default:
return .single(nil) return .generic
}
} }
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, UpdateChannelSlowModeError> in |> 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) 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 |> mapToSignal { _ -> Signal<PeerId?, UpdateChannelSlowModeError> in
return .complete() return .complete()
@ -752,8 +751,21 @@ public func channelPermissionsController(context: AccountContext, peerId origina
upgradedToSupergroupImpl?(peerId, {}) upgradedToSupergroupImpl?(peerId, {})
} }
progress?.dismiss() progress?.dismiss()
}, error: { [weak progress] _ in }, error: { [weak progress] error in
progress?.dismiss() 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 dismissInputImpl = { [weak controller] in
controller?.view.endEditing(true) 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 upgradedToSupergroupImpl = { [weak controller] upgradedPeerId, f in
guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else { guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else {
return return

View File

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

View File

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

View File

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

View File

@ -61,11 +61,11 @@ func localizedOldChannelDate(peer: InactiveChannel, strings: PresentationStrings
private final class OldChannelsItemArguments { private final class OldChannelsItemArguments {
let context: AccountContext let context: AccountContext
let togglePeer: (PeerId) -> Void let togglePeer: (PeerId, Bool) -> Void
init( init(
context: AccountContext, context: AccountContext,
togglePeer: @escaping (PeerId) -> Void togglePeer: @escaping (PeerId, Bool) -> Void
) { ) {
self.context = context self.context = context
self.togglePeer = togglePeer self.togglePeer = togglePeer
@ -174,7 +174,7 @@ private enum OldChannelsEntry: ItemListNodeEntry {
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
case let .peer(_, peer, selected): 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 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) }, setPeerIdWithRevealedOptions: nil, deletePeer: nil, itemHighlighting: nil, contextAction: nil)
} }
} }
@ -185,13 +185,23 @@ private struct OldChannelsState: Equatable {
var isSearching: Bool = false 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] = [] var entries: [OldChannelsEntry] = []
if let peers = peers, !peers.isEmpty { let noticeText: String
entries.append(.info(presentationData.strings.OldChannels_NoticeTitle, presentationData.strings.OldChannels_NoticeText)) 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(.peersHeader(presentationData.strings.OldChannels_ChannelsHeader)) entries.append(.peersHeader(presentationData.strings.OldChannels_ChannelsHeader))
for peer in peers { for peer in peers {
entries.append(.peer(entries.count, peer, state.selectedPeers.contains(peer.peer.id))) 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 initialState = OldChannelsState()
let statePromise = ValuePromise(initialState, ignoreRepeated: true) let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState) let stateValue = Atomic(value: initialState)
@ -329,23 +345,30 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
var dismissImpl: (() -> Void)? var dismissImpl: (() -> Void)?
var setDisplayNavigationBarImpl: ((Bool) -> Void)? var setDisplayNavigationBarImpl: ((Bool) -> Void)?
var ensurePeerVisibleImpl: ((PeerId) -> Void)?
let actionsDisposable = DisposableSet() let actionsDisposable = DisposableSet()
let arguments = OldChannelsItemArguments( let arguments = OldChannelsItemArguments(
context: context, context: context,
togglePeer: { peerId in togglePeer: { peerId, ensureVisible in
var hasSelectedPeers = false var hasSelectedPeers = false
var didSelect = false
updateState { state in updateState { state in
var state = state var state = state
if state.selectedPeers.contains(peerId) { if state.selectedPeers.contains(peerId) {
state.selectedPeers.remove(peerId) state.selectedPeers.remove(peerId)
} else { } else {
state.selectedPeers.insert(peerId) state.selectedPeers.insert(peerId)
didSelect = true
} }
hasSelectedPeers = !state.selectedPeers.isEmpty hasSelectedPeers = !state.selectedPeers.isEmpty
return state return state
} }
updateHasSelectedPeersImpl?(hasSelectedPeers) updateHasSelectedPeersImpl?(hasSelectedPeers)
if didSelect && ensureVisible {
ensurePeerVisibleImpl?(peerId)
}
} }
) )
@ -395,7 +418,7 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
setDisplayNavigationBarImpl?(false) setDisplayNavigationBarImpl?(false)
} }
}, peers: peersPromise.get() |> map { $0 ?? [] }, selectedPeerIds: selectedPeerIds, togglePeer: { peerId in }, peers: peersPromise.get() |> map { $0 ?? [] }, selectedPeerIds: selectedPeerIds, togglePeer: { peerId in
arguments.togglePeer(peerId) arguments.togglePeer(peerId, false)
}) })
let peersAreEmpty = peers == nil let peersAreEmpty = peers == nil
@ -407,7 +430,7 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) 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)) return (controllerState, (listState, arguments))
} }
@ -430,19 +453,22 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
return context.account.postbox.transaction { transaction -> Void in return context.account.postbox.transaction { transaction -> Void in
if let peers = peers { if let peers = peers {
for peer in peers { for peer in peers {
if transaction.getPeer(peer.peer.id) == nil { if state.selectedPeers.contains(peer.peer.id) {
updatePeers(transaction: transaction, peers: [peer.peer], update: { _, updated in if transaction.getPeer(peer.peer.id) == nil {
return updated 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() |> deliverOnMainQueue).start(completed: {
completed(true)
dismissImpl?() dismissImpl?()
})
} }
dismissImpl = { [weak controller] in dismissImpl = { [weak controller] in
@ -451,6 +477,16 @@ public func oldChannelsController(context: AccountContext) -> ViewController {
setDisplayNavigationBarImpl = { [weak controller] display in setDisplayNavigationBarImpl = { [weak controller] display in
controller?.setDisplayNavigationBar(display, transition: .animated(duration: 0.5, curve: .spring)) 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 return controller
} }

View File

@ -195,8 +195,16 @@ private final class OldChannelsSearchContainerNode: SearchDisplayControllerConte
self.addSubnode(self.listNode) self.addSubnode(self.listNode)
let interaction = OldChannelsSearchInteraction(togglePeer: { peerId in let interaction = OldChannelsSearchInteraction(togglePeer: { [weak self] peerId in
togglePeer(peerId) 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) 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) let pathsTo = self.storePathsForId(to)
link(pathsFrom.partial, pathsTo.partial) link(pathsFrom.partial, pathsTo.partial)
link(pathsFrom.complete, pathsTo.complete) 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> { 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 return account.postbox.transaction { transaction -> Signal<PeerId, CreateChannelError> in
var flags: Int32 = 0 var flags: Int32 = 0
if isSupergroup { if isSupergroup {

View File

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

View File

@ -36,6 +36,7 @@ public enum ChannelDiscussionGroupError {
case generic case generic
case groupHistoryIsCurrentlyPrivate case groupHistoryIsCurrentlyPrivate
case hasNotPermissions case hasNotPermissions
case tooManyChannels
} }
public func updateGroupDiscussionForChannel(network: Network, postbox: Postbox, channelId: PeerId?, groupId: PeerId?) -> Signal<Bool, ChannelDiscussionGroupError> { 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 { public enum UpdateChannelSlowModeError {
case generic case generic
case tooManyChannels
} }
public func updateChannelSlowModeInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, timeout: Int32?) -> Signal<Void, UpdateChannelSlowModeError> { 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 let text: String
switch error { switch error {
case .tooMuchJoined: 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 return
default: default:
if let channel = peer as? TelegramChannel, case .broadcast = channel.info { if let channel = peer as? TelegramChannel, case .broadcast = channel.info {

View File

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

View File

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

View File

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

View File

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

View File

@ -64,7 +64,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
case let .join(link): case let .join(link):
controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in
openResolvedPeerImpl(peerId, .chat(textInputState: nil, subject: nil)) openResolvedPeerImpl(peerId, .chat(textInputState: nil, subject: nil))
}), in: .window(.root)) }, parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root))
case let .wallet(address, amount, comment): case let .wallet(address, amount, comment):
context.sharedContext.openWallet(context: context, walletContext: .send(address: address, amount: amount, comment: comment)) { c in context.sharedContext.openWallet(context: context, walletContext: .send(address: address, amount: amount, comment: comment)) { c in
(controller.navigationController as? NavigationController)?.pushViewController(c) (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_SecureStorageReset_Title: String { return self._s[218]! }
public var Wallet_Receive_CommentHeader: String { return self._s[219]! } public var Wallet_Receive_CommentHeader: String { return self._s[219]! }
public var Wallet_Info_ReceiveGrams: String { return self._s[220]! } public var Wallet_Info_ReceiveGrams: String { return self._s[220]! }
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value) let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
} }
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value) let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)