mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 13:13:55 +00:00
Merge commit '313505ae6b9ebfd7fa9f862284cb3edcccea027a'
This commit is contained in:
commit
aa87d2695a
@ -4328,6 +4328,8 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Conversation.OpenBotLinkOpen" = "Open";
|
||||
|
||||
"TextFormat.Link" = "Link";
|
||||
"TextFormat.Strikethrough" = "Strikethrough";
|
||||
"TextFormat.Underline" = "Underline";
|
||||
|
||||
"TextFormat.AddLinkTitle" = "Add Link";
|
||||
"TextFormat.AddLinkText" = "The link will be displayed as \"%@\".";
|
||||
@ -4458,3 +4460,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Activity.RemindAboutGroup" = "Send message to %@";
|
||||
"Activity.RemindAboutUser" = "Send message to %@";
|
||||
"Activity.RemindAboutChannel" = "Read %@";
|
||||
|
||||
"CreateGroup.ChannelsTooMuch" = "Sorry, you are a member of too many groups and channels. Please leave some before creating a new one.";
|
||||
"Join.ChannelsTooMuch" = "Sorry, you are a member of too many groups and channels. Please leave some before joining one.";
|
||||
"Invite.ChannelsTooMuch" = "Sorry, the target user is a member of too many groups and channels. Please ask them to leave some first.";
|
||||
|
||||
@ -75,6 +75,7 @@ public enum AddChannelMemberError {
|
||||
case generic
|
||||
case restricted
|
||||
case limitExceeded
|
||||
case tooMuchJoined
|
||||
case bot(PeerId)
|
||||
}
|
||||
|
||||
@ -97,6 +98,8 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
||||
|> map { [$0] }
|
||||
|> `catch` { error -> Signal<[Api.Updates], AddChannelMemberError> in
|
||||
switch error.errorDescription {
|
||||
case "CHANNELS_TOO_MUCH":
|
||||
return .fail(.tooMuchJoined)
|
||||
case "USERS_TOO_MUCH":
|
||||
return .fail(.limitExceeded)
|
||||
case "USER_PRIVACY_RESTRICTED":
|
||||
@ -190,6 +193,8 @@ public func addChannelMembers(account: Account, peerId: PeerId, memberIds: [Peer
|
||||
let signal = account.network.request(Api.functions.channels.inviteToChannel(channel: inputChannel, users: inputUsers))
|
||||
|> mapError { error -> AddChannelMemberError in
|
||||
switch error.errorDescription {
|
||||
case "CHANNELS_TOO_MUCH":
|
||||
return .tooMuchJoined
|
||||
case "USER_PRIVACY_RESTRICTED":
|
||||
return .restricted
|
||||
case "USERS_TOO_MUCH":
|
||||
|
||||
@ -18,6 +18,7 @@ import Foundation
|
||||
public enum CreateChannelError {
|
||||
case generic
|
||||
case restricted
|
||||
case tooMuchJoined
|
||||
case tooMuchLocationBasedGroups
|
||||
case serverProvided(String)
|
||||
}
|
||||
@ -43,6 +44,8 @@ private func createChannel(account: Account, title: String, description: String?
|
||||
|> mapError { error -> CreateChannelError in
|
||||
if error.errorCode == 406 {
|
||||
return .serverProvided(error.errorDescription)
|
||||
} else if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||
return .tooMuchJoined
|
||||
} else if error.errorDescription == "CHANNELS_ADMIN_LOCATED_TOO_MUCH" {
|
||||
return .tooMuchLocationBasedGroups
|
||||
} else if error.errorDescription == "USER_RESTRICTED" {
|
||||
|
||||
@ -21,6 +21,7 @@ public enum ChannelOwnershipTransferError {
|
||||
case adminsTooMuch
|
||||
case userPublicChannelsTooMuch
|
||||
case userLocatedGroupsTooMuch
|
||||
case tooMuchJoined
|
||||
case restricted
|
||||
case userBlocked
|
||||
}
|
||||
@ -64,6 +65,8 @@ public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Networ
|
||||
return .restricted
|
||||
} else if error.errorDescription == "USER_BLOCKED" {
|
||||
return .userBlocked
|
||||
} else if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||
return .tooMuchJoined
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ public enum CreateGroupError {
|
||||
case generic
|
||||
case privacy
|
||||
case restricted
|
||||
case tooMuchJoined
|
||||
case tooMuchLocationBasedGroups
|
||||
case serverProvided(String)
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import Foundation
|
||||
|
||||
public enum JoinChannelError {
|
||||
case generic
|
||||
case tooMuchJoined
|
||||
}
|
||||
|
||||
public func joinChannel(account: Account, peerId: PeerId) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
|
||||
@ -20,8 +21,12 @@ public func joinChannel(account: Account, peerId: PeerId) -> Signal<RenderedChan
|
||||
|> mapToSignal { peer -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||
if let inputChannel = apiInputChannel(peer) {
|
||||
return account.network.request(Api.functions.channels.joinChannel(channel: inputChannel))
|
||||
|> mapError { _ -> JoinChannelError in
|
||||
return .generic
|
||||
|> mapError { error -> JoinChannelError in
|
||||
if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||
return .tooMuchJoined
|
||||
} else {
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||
account.stateManager.addUpdates(updates)
|
||||
|
||||
@ -14,6 +14,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public enum JoinLinkError {
|
||||
case generic
|
||||
case tooMuchJoined
|
||||
}
|
||||
|
||||
func apiUpdatesGroups(_ updates: Api.Updates) -> [Api.Chat] {
|
||||
switch updates {
|
||||
case let .updates( _, _, chats, _, _):
|
||||
@ -31,31 +36,31 @@ public enum ExternalJoiningChatState {
|
||||
case invalidHash
|
||||
}
|
||||
|
||||
public func joinChatInteractively(with hash: String, account: Account) -> Signal <PeerId?, NoError> {
|
||||
public func joinChatInteractively(with hash: String, account: Account) -> Signal <PeerId?, JoinLinkError> {
|
||||
return account.network.request(Api.functions.messages.importChatInvite(hash: hash))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<PeerId?, NoError> in
|
||||
if let updates = updates {
|
||||
account.stateManager.addUpdates(updates)
|
||||
if let peerId = apiUpdatesGroups(updates).first?.peerId {
|
||||
return account.postbox.multiplePeersView([peerId])
|
||||
|> filter { view in
|
||||
return view.peers[peerId] != nil
|
||||
}
|
||||
|> take(1)
|
||||
|> map { _ in
|
||||
return peerId
|
||||
}
|
||||
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil))
|
||||
}
|
||||
return .single(nil)
|
||||
|> mapError { error -> JoinLinkError in
|
||||
if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||
return .tooMuchJoined
|
||||
} else {
|
||||
return .single(nil)
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<PeerId?, JoinLinkError> in
|
||||
account.stateManager.addUpdates(updates)
|
||||
if let peerId = apiUpdatesGroups(updates).first?.peerId {
|
||||
return account.postbox.multiplePeersView([peerId])
|
||||
|> introduceError(JoinLinkError.self)
|
||||
|> filter { view in
|
||||
return view.peers[peerId] != nil
|
||||
}
|
||||
|> take(1)
|
||||
|> map { _ in
|
||||
return peerId
|
||||
}
|
||||
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil) |> introduceError(JoinLinkError.self))
|
||||
}
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|
||||
public func joinLinkInformation(_ hash: String, account: Account) -> Signal<ExternalJoiningChatState, NoError> {
|
||||
|
||||
@ -237,11 +237,11 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
|
||||
} else if layerSupport >= 73 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer73, locallyRequestedLayer: 73, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer73, actionGloballyUniqueId: arc4random64(), layerSupport: 73), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer73, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
} else if layerSupport >= 46 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer46, locallyRequestedLayer: 46, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer46, actionGloballyUniqueId: arc4random64(), layerSupport: 73), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer46, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
} else {
|
||||
throw MessageParsingError.contentParsingError
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 102
|
||||
return 101
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
||||
self.apply = apply
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 2
|
||||
self.titleNode.maximumNumberOfLines = 3
|
||||
|
||||
var starNodes: [ASButtonNode] = []
|
||||
for _ in 0 ..< 5 {
|
||||
@ -110,7 +110,7 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
||||
}
|
||||
|
||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.Calls_RatingTitle, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.strings.Calls_RatingTitle, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
for node in self.starNodes {
|
||||
node.setImage(generateTintedImage(image: UIImage(bundleImageName: "Call/Star"), color: theme.accentColor), for: [])
|
||||
@ -140,7 +140,7 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
||||
|
||||
var origin: CGPoint = CGPoint(x: 0.0, y: 20.0)
|
||||
|
||||
let titleSize = self.titleNode.measure(size)
|
||||
let titleSize = self.titleNode.measure(CGSize(width: size.width - 32.0, height: size.height))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
|
||||
origin.y += titleSize.height + 13.0
|
||||
|
||||
@ -156,10 +156,10 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
||||
effectiveActionLayout = .vertical
|
||||
}
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
||||
case .vertical:
|
||||
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
||||
case .horizontal:
|
||||
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
||||
case .vertical:
|
||||
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,24 +198,24 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
||||
if separatorIndex >= 0 {
|
||||
let separatorNode = self.actionVerticalSeparators[separatorIndex]
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
||||
case .vertical:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
case .horizontal:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
||||
case .vertical:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
}
|
||||
}
|
||||
separatorIndex += 1
|
||||
|
||||
let currentActionWidth: CGFloat
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
if nodeIndex == self.actionNodes.count - 1 {
|
||||
currentActionWidth = resultSize.width - actionOffset
|
||||
} else {
|
||||
currentActionWidth = actionWidth
|
||||
}
|
||||
case .vertical:
|
||||
currentActionWidth = resultSize.width
|
||||
case .horizontal:
|
||||
if nodeIndex == self.actionNodes.count - 1 {
|
||||
currentActionWidth = resultSize.width - actionOffset
|
||||
} else {
|
||||
currentActionWidth = actionWidth
|
||||
}
|
||||
case .vertical:
|
||||
currentActionWidth = resultSize.width
|
||||
}
|
||||
|
||||
let actionNodeFrame: CGRect
|
||||
|
||||
@ -376,6 +376,8 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
||||
switch error {
|
||||
case .limitExceeded:
|
||||
text = presentationData.strings.Channel_ErrorAddTooMuch
|
||||
case .tooMuchJoined:
|
||||
text = presentationData.strings.Invite_ChannelsTooMuch
|
||||
case .generic:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
case .restricted:
|
||||
|
||||
@ -126,15 +126,20 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
||||
strongSelf.activityIndicator.stopAnimating()
|
||||
}
|
||||
}
|
||||
}).start(error: { [weak self] _ in
|
||||
}).start(error: { [weak self] error in
|
||||
guard let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState, let peer = presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
let text: String
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
text = presentationInterfaceState.strings.Channel_ErrorAccessDenied
|
||||
} else {
|
||||
text = presentationInterfaceState.strings.Group_ErrorAccessDenied
|
||||
switch error {
|
||||
case .tooMuchJoined:
|
||||
text = presentationInterfaceState.strings.Join_ChannelsTooMuch
|
||||
default:
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
text = presentationInterfaceState.strings.Channel_ErrorAccessDenied
|
||||
} else {
|
||||
text = presentationInterfaceState.strings.Group_ErrorAccessDenied
|
||||
}
|
||||
}
|
||||
strongSelf.interfaceInteraction?.presentController(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationInterfaceState.strings.Common_OK, action: {})]), nil)
|
||||
}))
|
||||
|
||||
@ -97,10 +97,11 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
||||
private var searchContentNode: NavigationBarSearchContentNode?
|
||||
|
||||
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.chatListDisplayNode.chatListNode.updateSelectedChatLocation(data as? ChatLocation, progress: progress, transition: transition)
|
||||
if self.isNodeLoaded {
|
||||
self.chatListDisplayNode.chatListNode.updateSelectedChatLocation(data as? ChatLocation, progress: progress, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false) {
|
||||
self.context = context
|
||||
self.controlsHistoryPreload = controlsHistoryPreload
|
||||
|
||||
@ -534,7 +534,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
} else {
|
||||
if self.highlightedBackgroundNode.supernode != nil {
|
||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: highlightProgress, completion: { [weak self] completed in
|
||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: 1.0 - highlightProgress, completion: { [weak self] completed in
|
||||
if let strongSelf = self {
|
||||
if completed {
|
||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||
|
||||
@ -13,6 +13,8 @@ final class ChatTextInputMenu {
|
||||
private var stringItalic: String = "Italic"
|
||||
private var stringMonospace: String = "Monospace"
|
||||
private var stringLink: String = "Link"
|
||||
private var stringStrikethrough: String = "Strikethrough"
|
||||
private var stringUnderline: String = "Underline"
|
||||
|
||||
private(set) var state: ChatTextInputMenuState = .inactive {
|
||||
didSet {
|
||||
@ -27,7 +29,9 @@ final class ChatTextInputMenu {
|
||||
UIMenuItem(title: self.stringBold, action: Selector(("formatAttributesBold:"))),
|
||||
UIMenuItem(title: self.stringItalic, action: Selector(("formatAttributesItalic:"))),
|
||||
UIMenuItem(title: self.stringMonospace, action: Selector(("formatAttributesMonospace:"))),
|
||||
UIMenuItem(title: self.stringLink, action: Selector(("formatAttributesLink:")))
|
||||
UIMenuItem(title: self.stringLink, action: Selector(("formatAttributesLink:"))),
|
||||
UIMenuItem(title: self.stringStrikethrough, action: Selector(("formatAttributesStrikethrough:"))),
|
||||
UIMenuItem(title: self.stringUnderline, action: Selector(("formatAttributesUnderline:")))
|
||||
]
|
||||
UIMenuController.shared.isMenuVisible = true
|
||||
UIMenuController.shared.update()
|
||||
@ -56,6 +60,8 @@ final class ChatTextInputMenu {
|
||||
self.stringItalic = strings.TextFormat_Italic
|
||||
self.stringMonospace = strings.TextFormat_Monospace
|
||||
self.stringLink = strings.TextFormat_Link
|
||||
self.stringStrikethrough = strings.TextFormat_Strikethrough
|
||||
self.stringUnderline = strings.TextFormat_Underline
|
||||
}
|
||||
|
||||
func activate() {
|
||||
|
||||
@ -230,6 +230,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
private var currentPlaceholder: String?
|
||||
|
||||
private var presentationInterfaceState: ChatPresentationInterfaceState?
|
||||
private var initializedPlaceholder = false
|
||||
|
||||
private var keepSendButtonEnabled = false
|
||||
private var extendedSearchLayout = false
|
||||
@ -684,7 +685,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if let peer = interfaceState.renderedPeer?.peer, previousState?.renderedPeer?.peer == nil || !peer.isEqual(previousState!.renderedPeer!.peer!) || previousState?.interfaceState.silentPosting != interfaceState.interfaceState.silentPosting || themeUpdated {
|
||||
if let peer = interfaceState.renderedPeer?.peer, previousState?.renderedPeer?.peer == nil || !peer.isEqual(previousState!.renderedPeer!.peer!) || previousState?.interfaceState.silentPosting != interfaceState.interfaceState.silentPosting || themeUpdated || !self.initializedPlaceholder {
|
||||
self.initializedPlaceholder = true
|
||||
|
||||
let placeholder: String
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
if interfaceState.interfaceState.silentPosting {
|
||||
@ -1342,7 +1345,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
} else {
|
||||
return ASEditableTextNodeTargetForAction(target: nil)
|
||||
}
|
||||
} else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) {
|
||||
} else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) {
|
||||
if case .format = self.inputMenu.state {
|
||||
return ASEditableTextNodeTargetForAction(target: self)
|
||||
} else {
|
||||
@ -1385,6 +1388,20 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
self.interfaceInteraction?.openLinkEditing()
|
||||
}
|
||||
|
||||
@objc func formatAttributesStrikethrough(_ sender: Any) {
|
||||
self.inputMenu.back()
|
||||
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
|
||||
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.strikethrough), inputMode)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func formatAttributesUnderline(_ sender: Any) {
|
||||
self.inputMenu.back()
|
||||
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
|
||||
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.underline), inputMode)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
self.updateActivity()
|
||||
var cleanText = text
|
||||
|
||||
@ -77,12 +77,12 @@ public class ContactsController: ViewController {
|
||||
|
||||
var switchToChatsController: (() -> Void)?
|
||||
|
||||
|
||||
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.contactsNode.contactListNode.updateSelectedChatLocation(data as? ChatLocation, progress: progress, transition: transition)
|
||||
if self.isNodeLoaded {
|
||||
self.contactsNode.contactListNode.updateSelectedChatLocation(data as? ChatLocation, progress: progress, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public init(context: AccountContext) {
|
||||
self.context = context
|
||||
|
||||
|
||||
@ -424,7 +424,7 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: highlightProgress)
|
||||
} else {
|
||||
if self.highlightedBackgroundNode.supernode != nil {
|
||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: highlightProgress, completion: { [weak self] completed in
|
||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: 1.0 - highlightProgress, completion: { [weak self] completed in
|
||||
if let strongSelf = self {
|
||||
if completed {
|
||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||
|
||||
@ -262,6 +262,8 @@ public func createChannelController(context: AccountContext) -> ViewController {
|
||||
switch error {
|
||||
case .generic, .tooMuchLocationBasedGroups:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
case .tooMuchJoined:
|
||||
text = presentationData.strings.CreateGroup_ChannelsTooMuch
|
||||
case .restricted:
|
||||
text = presentationData.strings.Common_ActionNotAllowedError
|
||||
default:
|
||||
|
||||
@ -356,6 +356,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
||||
return .generic
|
||||
case .restricted:
|
||||
return .restricted
|
||||
case .tooMuchJoined:
|
||||
return .tooMuchJoined
|
||||
case .tooMuchLocationBasedGroups:
|
||||
return .tooMuchLocationBasedGroups
|
||||
case let .serverProvided(error):
|
||||
@ -381,6 +383,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
||||
return .generic
|
||||
case .restricted:
|
||||
return .restricted
|
||||
case .tooMuchJoined:
|
||||
return .tooMuchJoined
|
||||
case .tooMuchLocationBasedGroups:
|
||||
return .tooMuchLocationBasedGroups
|
||||
case let .serverProvided(error):
|
||||
@ -448,6 +452,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
case .restricted:
|
||||
text = presentationData.strings.Common_ActionNotAllowedError
|
||||
case .tooMuchJoined:
|
||||
text = presentationData.strings.CreateGroup_ChannelsTooMuch
|
||||
case .tooMuchLocationBasedGroups:
|
||||
text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch
|
||||
default:
|
||||
|
||||
@ -54,7 +54,7 @@ final class DeviceLocationManager: NSObject, CLLocationManagerDelegate {
|
||||
}
|
||||
self.manager.delegate = self
|
||||
self.manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
||||
self.manager.distanceFilter = 20.0
|
||||
self.manager.distanceFilter = 10.0
|
||||
self.manager.activityType = .other
|
||||
self.manager.pausesLocationUpdatesAutomatically = false
|
||||
}
|
||||
|
||||
@ -1815,13 +1815,13 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
|> deliverOnMainQueue).start(error: { error in
|
||||
if peers.count == 1, case .restricted = error {
|
||||
switch peers[0] {
|
||||
case let .peer(peerId):
|
||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(peer.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
})
|
||||
default:
|
||||
break
|
||||
case let .peer(peerId):
|
||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(peer.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,13 @@ public final class JoinLinkPreviewController: ViewController {
|
||||
strongSelf.dismiss()
|
||||
}
|
||||
}
|
||||
}, 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))
|
||||
strongSelf.dismiss()
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
|
||||
private let separatorNode: ASDisplayNode
|
||||
|
||||
private var validLayout: (CGSize, CGFloat, CGFloat)?
|
||||
private var peersAndMode: ([Peer], LocationBroadcastNavigationAccessoryPanelMode)?
|
||||
private var peersAndMode: ([Peer], LocationBroadcastNavigationAccessoryPanelMode, Bool)?
|
||||
|
||||
init(accountPeerId: PeerId, theme: PresentationTheme, strings: PresentationStrings, tapAction: @escaping () -> Void, close: @escaping () -> Void) {
|
||||
self.accountPeerId = accountPeerId
|
||||
@ -108,7 +108,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
|
||||
|
||||
let titleString = NSAttributedString(string: self.strings.Conversation_LiveLocation, font: titleFont, textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
var subtitleString: NSAttributedString?
|
||||
if let (peers, mode) = self.peersAndMode {
|
||||
if let (peers, mode, canClose) = self.peersAndMode {
|
||||
switch mode {
|
||||
case .summary:
|
||||
let text: String
|
||||
@ -119,6 +119,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
|
||||
}
|
||||
subtitleString = NSAttributedString(string: text, font: subtitleFont, textColor: self.theme.rootController.navigationBar.secondaryTextColor)
|
||||
case .peer:
|
||||
self.closeButton.isHidden = !canClose
|
||||
let filteredPeers = peers.filter {
|
||||
$0.id != self.accountPeerId
|
||||
}
|
||||
@ -172,8 +173,8 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel)))
|
||||
}
|
||||
|
||||
func update(peers: [Peer], mode: LocationBroadcastNavigationAccessoryPanelMode) {
|
||||
self.peersAndMode = (peers, mode)
|
||||
func update(peers: [Peer], mode: LocationBroadcastNavigationAccessoryPanelMode, canClose: Bool) {
|
||||
self.peersAndMode = (peers, mode, canClose)
|
||||
if let layout = validLayout {
|
||||
self.updateLayout(size: layout.0, leftInset: layout.1, rightInset: layout.2, transition: .immediate)
|
||||
}
|
||||
|
||||
@ -327,23 +327,6 @@ final class PeerChannelMemberCategoriesContextsManager {
|
||||
|> mapToSignal { _ -> Signal<Void, AddChannelMemberError> in
|
||||
return .complete()
|
||||
}
|
||||
|
||||
/*return addChannelMembers(account: account, peerId: peerId, memberIds: memberIds)
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
strongSelf.impl.with { impl in
|
||||
for (contextPeerId, context) in impl.contexts {
|
||||
if peerId == contextPeerId {
|
||||
context.reset(.recent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, AddChannelMemberError> in
|
||||
return .single(Void())
|
||||
}*/
|
||||
}
|
||||
|
||||
func recentOnline(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId) -> Signal<Int32, NoError> {
|
||||
|
||||
Binary file not shown.
@ -1347,15 +1347,9 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
context.sharedContext.switchToAccount(id: id)
|
||||
})
|
||||
}
|
||||
var didAppear = false
|
||||
controller.didAppear = { [weak controller] _ in
|
||||
controller.didAppear = { _ in
|
||||
updatePassport()
|
||||
updateNotifyExceptions()
|
||||
|
||||
if !didAppear {
|
||||
(controller?.displayNode as? ItemListControllerNode<SettingsEntry>)?.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
didAppear = true
|
||||
}
|
||||
}
|
||||
controller.previewItemWithTag = { tag in
|
||||
if let tag = tag as? SettingsEntryTag, case let .account(id) = tag {
|
||||
|
||||
@ -184,24 +184,24 @@ public class TelegramController: ViewController, KeyShortcutResponder {
|
||||
peers?.append(author)
|
||||
}
|
||||
}
|
||||
return (peers, nil)
|
||||
return (peers, outgoingMessages)
|
||||
}
|
||||
default:
|
||||
self.locationBroadcastMode = .summary
|
||||
signal = liveLocationManager.summaryManager.broadcastingToMessages()
|
||||
|> map { messages -> ([Peer]?, [MessageId: Message]?) in
|
||||
if messages.isEmpty {
|
||||
return (nil, nil)
|
||||
} else {
|
||||
var peers: [Peer] = []
|
||||
for message in messages.values.sorted(by: { $0.index < $1.index }) {
|
||||
if let peer = message.peers[message.id.peerId] {
|
||||
peers.append(peer)
|
||||
}
|
||||
|> map { messages -> ([Peer]?, [MessageId: Message]?) in
|
||||
if messages.isEmpty {
|
||||
return (nil, nil)
|
||||
} else {
|
||||
var peers: [Peer] = []
|
||||
for message in messages.values.sorted(by: { $0.index < $1.index }) {
|
||||
if let peer = message.peers[message.id.peerId] {
|
||||
peers.append(peer)
|
||||
}
|
||||
return (peers, messages)
|
||||
}
|
||||
return (peers, messages)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -223,7 +223,16 @@ public class TelegramController: ViewController, KeyShortcutResponder {
|
||||
if wasEmpty != (peers == nil) {
|
||||
strongSelf.requestLayout(transition: .animated(duration: 0.4, curve: .spring))
|
||||
} else if let peers = peers, let locationBroadcastMode = strongSelf.locationBroadcastMode {
|
||||
strongSelf.locationBroadcastAccessoryPanel?.update(peers: peers, mode: locationBroadcastMode)
|
||||
var canClose = true
|
||||
if case let .peer(peerId) = strongSelf.locationBroadcastPanelSource, let messages = messages {
|
||||
canClose = false
|
||||
for messageId in messages.keys {
|
||||
if messageId.peerId == peerId {
|
||||
canClose = true
|
||||
}
|
||||
}
|
||||
}
|
||||
strongSelf.locationBroadcastAccessoryPanel?.update(peers: peers, mode: locationBroadcastMode, canClose: canClose)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,7 +410,18 @@ public class TelegramController: ViewController, KeyShortcutResponder {
|
||||
}
|
||||
self.locationBroadcastAccessoryPanel = locationBroadcastAccessoryPanel
|
||||
locationBroadcastAccessoryPanel.frame = panelFrame
|
||||
locationBroadcastAccessoryPanel.update(peers: locationBroadcastPeers, mode: locationBroadcastMode)
|
||||
|
||||
var canClose = true
|
||||
if case let .peer(peerId) = self.locationBroadcastPanelSource, let messages = self.locationBroadcastMessages {
|
||||
canClose = false
|
||||
for messageId in messages.keys {
|
||||
if messageId.peerId == peerId {
|
||||
canClose = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locationBroadcastAccessoryPanel.update(peers: locationBroadcastPeers, mode: locationBroadcastMode, canClose: canClose)
|
||||
locationBroadcastAccessoryPanel.updateLayout(size: panelFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: .immediate)
|
||||
if transition.isAnimated {
|
||||
locationBroadcastAccessoryPanel.animateIn(transition)
|
||||
|
||||
@ -890,7 +890,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
transformedSuperFrame = transformedSuperFrame.offsetBy(dx: videoNode.position.x - previousFrame.center.x, dy: videoNode.position.y - previousFrame.center.y)
|
||||
}
|
||||
|
||||
let initialScale = min(videoNode.layer.bounds.width / node.0.view.bounds.width, videoNode.layer.bounds.height / node.0.view.bounds.height)
|
||||
let initialScale: CGFloat = 1.0 //min(videoNode.layer.bounds.width / node.0.view.bounds.width, videoNode.layer.bounds.height / node.0.view.bounds.height)
|
||||
let targetScale = max(transformedFrame.size.width / videoNode.layer.bounds.size.width, transformedFrame.size.height / videoNode.layer.bounds.size.height)
|
||||
|
||||
videoNode.backgroundColor = .clear
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user