mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 21:16:35 +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";
|
"Conversation.OpenBotLinkOpen" = "Open";
|
||||||
|
|
||||||
"TextFormat.Link" = "Link";
|
"TextFormat.Link" = "Link";
|
||||||
|
"TextFormat.Strikethrough" = "Strikethrough";
|
||||||
|
"TextFormat.Underline" = "Underline";
|
||||||
|
|
||||||
"TextFormat.AddLinkTitle" = "Add Link";
|
"TextFormat.AddLinkTitle" = "Add Link";
|
||||||
"TextFormat.AddLinkText" = "The link will be displayed as \"%@\".";
|
"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.RemindAboutGroup" = "Send message to %@";
|
||||||
"Activity.RemindAboutUser" = "Send message to %@";
|
"Activity.RemindAboutUser" = "Send message to %@";
|
||||||
"Activity.RemindAboutChannel" = "Read %@";
|
"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 generic
|
||||||
case restricted
|
case restricted
|
||||||
case limitExceeded
|
case limitExceeded
|
||||||
|
case tooMuchJoined
|
||||||
case bot(PeerId)
|
case bot(PeerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +98,8 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
|||||||
|> map { [$0] }
|
|> map { [$0] }
|
||||||
|> `catch` { error -> Signal<[Api.Updates], AddChannelMemberError> in
|
|> `catch` { error -> Signal<[Api.Updates], AddChannelMemberError> in
|
||||||
switch error.errorDescription {
|
switch error.errorDescription {
|
||||||
|
case "CHANNELS_TOO_MUCH":
|
||||||
|
return .fail(.tooMuchJoined)
|
||||||
case "USERS_TOO_MUCH":
|
case "USERS_TOO_MUCH":
|
||||||
return .fail(.limitExceeded)
|
return .fail(.limitExceeded)
|
||||||
case "USER_PRIVACY_RESTRICTED":
|
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))
|
let signal = account.network.request(Api.functions.channels.inviteToChannel(channel: inputChannel, users: inputUsers))
|
||||||
|> mapError { error -> AddChannelMemberError in
|
|> mapError { error -> AddChannelMemberError in
|
||||||
switch error.errorDescription {
|
switch error.errorDescription {
|
||||||
|
case "CHANNELS_TOO_MUCH":
|
||||||
|
return .tooMuchJoined
|
||||||
case "USER_PRIVACY_RESTRICTED":
|
case "USER_PRIVACY_RESTRICTED":
|
||||||
return .restricted
|
return .restricted
|
||||||
case "USERS_TOO_MUCH":
|
case "USERS_TOO_MUCH":
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import Foundation
|
|||||||
public enum CreateChannelError {
|
public enum CreateChannelError {
|
||||||
case generic
|
case generic
|
||||||
case restricted
|
case restricted
|
||||||
|
case tooMuchJoined
|
||||||
case tooMuchLocationBasedGroups
|
case tooMuchLocationBasedGroups
|
||||||
case serverProvided(String)
|
case serverProvided(String)
|
||||||
}
|
}
|
||||||
@ -43,6 +44,8 @@ private func createChannel(account: Account, title: String, description: String?
|
|||||||
|> mapError { error -> CreateChannelError in
|
|> mapError { error -> CreateChannelError in
|
||||||
if error.errorCode == 406 {
|
if error.errorCode == 406 {
|
||||||
return .serverProvided(error.errorDescription)
|
return .serverProvided(error.errorDescription)
|
||||||
|
} else if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||||
|
return .tooMuchJoined
|
||||||
} else if error.errorDescription == "CHANNELS_ADMIN_LOCATED_TOO_MUCH" {
|
} else if error.errorDescription == "CHANNELS_ADMIN_LOCATED_TOO_MUCH" {
|
||||||
return .tooMuchLocationBasedGroups
|
return .tooMuchLocationBasedGroups
|
||||||
} else if error.errorDescription == "USER_RESTRICTED" {
|
} else if error.errorDescription == "USER_RESTRICTED" {
|
||||||
|
|||||||
@ -21,6 +21,7 @@ public enum ChannelOwnershipTransferError {
|
|||||||
case adminsTooMuch
|
case adminsTooMuch
|
||||||
case userPublicChannelsTooMuch
|
case userPublicChannelsTooMuch
|
||||||
case userLocatedGroupsTooMuch
|
case userLocatedGroupsTooMuch
|
||||||
|
case tooMuchJoined
|
||||||
case restricted
|
case restricted
|
||||||
case userBlocked
|
case userBlocked
|
||||||
}
|
}
|
||||||
@ -64,6 +65,8 @@ public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Networ
|
|||||||
return .restricted
|
return .restricted
|
||||||
} else if error.errorDescription == "USER_BLOCKED" {
|
} else if error.errorDescription == "USER_BLOCKED" {
|
||||||
return .userBlocked
|
return .userBlocked
|
||||||
|
} else if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||||
|
return .tooMuchJoined
|
||||||
}
|
}
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public enum CreateGroupError {
|
|||||||
case generic
|
case generic
|
||||||
case privacy
|
case privacy
|
||||||
case restricted
|
case restricted
|
||||||
|
case tooMuchJoined
|
||||||
case tooMuchLocationBasedGroups
|
case tooMuchLocationBasedGroups
|
||||||
case serverProvided(String)
|
case serverProvided(String)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import Foundation
|
|||||||
|
|
||||||
public enum JoinChannelError {
|
public enum JoinChannelError {
|
||||||
case generic
|
case generic
|
||||||
|
case tooMuchJoined
|
||||||
}
|
}
|
||||||
|
|
||||||
public func joinChannel(account: Account, peerId: PeerId) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
|
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
|
|> mapToSignal { peer -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||||
if let inputChannel = apiInputChannel(peer) {
|
if let inputChannel = apiInputChannel(peer) {
|
||||||
return account.network.request(Api.functions.channels.joinChannel(channel: inputChannel))
|
return account.network.request(Api.functions.channels.joinChannel(channel: inputChannel))
|
||||||
|> mapError { _ -> JoinChannelError in
|
|> mapError { error -> JoinChannelError in
|
||||||
return .generic
|
if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||||
|
return .tooMuchJoined
|
||||||
|
} else {
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
|
|||||||
@ -14,6 +14,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public enum JoinLinkError {
|
||||||
|
case generic
|
||||||
|
case tooMuchJoined
|
||||||
|
}
|
||||||
|
|
||||||
func apiUpdatesGroups(_ updates: Api.Updates) -> [Api.Chat] {
|
func apiUpdatesGroups(_ updates: Api.Updates) -> [Api.Chat] {
|
||||||
switch updates {
|
switch updates {
|
||||||
case let .updates( _, _, chats, _, _):
|
case let .updates( _, _, chats, _, _):
|
||||||
@ -31,31 +36,31 @@ public enum ExternalJoiningChatState {
|
|||||||
case invalidHash
|
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))
|
return account.network.request(Api.functions.messages.importChatInvite(hash: hash))
|
||||||
|> map(Optional.init)
|
|> mapError { error -> JoinLinkError in
|
||||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
if error.errorDescription == "CHANNELS_TOO_MUCH" {
|
||||||
return .single(nil)
|
return .tooMuchJoined
|
||||||
}
|
|
||||||
|> 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)
|
|
||||||
} else {
|
} 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> {
|
public func joinLinkInformation(_ hash: String, account: Account) -> Signal<ExternalJoiningChatState, NoError> {
|
||||||
|
|||||||
@ -237,11 +237,11 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
|
|||||||
} else if layerSupport >= 73 {
|
} 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)
|
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 = 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 {
|
} 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)
|
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 = 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 {
|
} else {
|
||||||
throw MessageParsingError.contentParsingError
|
throw MessageParsingError.contentParsingError
|
||||||
}
|
}
|
||||||
|
|||||||
@ -216,7 +216,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 102
|
return 101
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
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.apply = apply
|
||||||
|
|
||||||
self.titleNode = ASTextNode()
|
self.titleNode = ASTextNode()
|
||||||
self.titleNode.maximumNumberOfLines = 2
|
self.titleNode.maximumNumberOfLines = 3
|
||||||
|
|
||||||
var starNodes: [ASButtonNode] = []
|
var starNodes: [ASButtonNode] = []
|
||||||
for _ in 0 ..< 5 {
|
for _ in 0 ..< 5 {
|
||||||
@ -110,7 +110,7 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
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 {
|
for node in self.starNodes {
|
||||||
node.setImage(generateTintedImage(image: UIImage(bundleImageName: "Call/Star"), color: theme.accentColor), for: [])
|
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)
|
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))
|
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
|
origin.y += titleSize.height + 13.0
|
||||||
|
|
||||||
@ -156,10 +156,10 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
|||||||
effectiveActionLayout = .vertical
|
effectiveActionLayout = .vertical
|
||||||
}
|
}
|
||||||
switch effectiveActionLayout {
|
switch effectiveActionLayout {
|
||||||
case .horizontal:
|
case .horizontal:
|
||||||
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
||||||
case .vertical:
|
case .vertical:
|
||||||
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,24 +198,24 @@ private final class CallRatingAlertContentNode: AlertContentNode {
|
|||||||
if separatorIndex >= 0 {
|
if separatorIndex >= 0 {
|
||||||
let separatorNode = self.actionVerticalSeparators[separatorIndex]
|
let separatorNode = self.actionVerticalSeparators[separatorIndex]
|
||||||
switch effectiveActionLayout {
|
switch effectiveActionLayout {
|
||||||
case .horizontal:
|
case .horizontal:
|
||||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
||||||
case .vertical:
|
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)))
|
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
|
separatorIndex += 1
|
||||||
|
|
||||||
let currentActionWidth: CGFloat
|
let currentActionWidth: CGFloat
|
||||||
switch effectiveActionLayout {
|
switch effectiveActionLayout {
|
||||||
case .horizontal:
|
case .horizontal:
|
||||||
if nodeIndex == self.actionNodes.count - 1 {
|
if nodeIndex == self.actionNodes.count - 1 {
|
||||||
currentActionWidth = resultSize.width - actionOffset
|
currentActionWidth = resultSize.width - actionOffset
|
||||||
} else {
|
} else {
|
||||||
currentActionWidth = actionWidth
|
currentActionWidth = actionWidth
|
||||||
}
|
}
|
||||||
case .vertical:
|
case .vertical:
|
||||||
currentActionWidth = resultSize.width
|
currentActionWidth = resultSize.width
|
||||||
}
|
}
|
||||||
|
|
||||||
let actionNodeFrame: CGRect
|
let actionNodeFrame: CGRect
|
||||||
|
|||||||
@ -376,6 +376,8 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
|||||||
switch error {
|
switch error {
|
||||||
case .limitExceeded:
|
case .limitExceeded:
|
||||||
text = presentationData.strings.Channel_ErrorAddTooMuch
|
text = presentationData.strings.Channel_ErrorAddTooMuch
|
||||||
|
case .tooMuchJoined:
|
||||||
|
text = presentationData.strings.Invite_ChannelsTooMuch
|
||||||
case .generic:
|
case .generic:
|
||||||
text = presentationData.strings.Login_UnknownError
|
text = presentationData.strings.Login_UnknownError
|
||||||
case .restricted:
|
case .restricted:
|
||||||
|
|||||||
@ -126,15 +126,20 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
|||||||
strongSelf.activityIndicator.stopAnimating()
|
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 {
|
guard let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState, let peer = presentationInterfaceState.renderedPeer?.peer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let text: String
|
let text: String
|
||||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
switch error {
|
||||||
text = presentationInterfaceState.strings.Channel_ErrorAccessDenied
|
case .tooMuchJoined:
|
||||||
} else {
|
text = presentationInterfaceState.strings.Join_ChannelsTooMuch
|
||||||
text = presentationInterfaceState.strings.Group_ErrorAccessDenied
|
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)
|
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?
|
private var searchContentNode: NavigationBarSearchContentNode?
|
||||||
|
|
||||||
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
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) {
|
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.controlsHistoryPreload = controlsHistoryPreload
|
self.controlsHistoryPreload = controlsHistoryPreload
|
||||||
|
|||||||
@ -534,7 +534,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if self.highlightedBackgroundNode.supernode != nil {
|
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 let strongSelf = self {
|
||||||
if completed {
|
if completed {
|
||||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
|||||||
@ -13,6 +13,8 @@ final class ChatTextInputMenu {
|
|||||||
private var stringItalic: String = "Italic"
|
private var stringItalic: String = "Italic"
|
||||||
private var stringMonospace: String = "Monospace"
|
private var stringMonospace: String = "Monospace"
|
||||||
private var stringLink: String = "Link"
|
private var stringLink: String = "Link"
|
||||||
|
private var stringStrikethrough: String = "Strikethrough"
|
||||||
|
private var stringUnderline: String = "Underline"
|
||||||
|
|
||||||
private(set) var state: ChatTextInputMenuState = .inactive {
|
private(set) var state: ChatTextInputMenuState = .inactive {
|
||||||
didSet {
|
didSet {
|
||||||
@ -27,7 +29,9 @@ final class ChatTextInputMenu {
|
|||||||
UIMenuItem(title: self.stringBold, action: Selector(("formatAttributesBold:"))),
|
UIMenuItem(title: self.stringBold, action: Selector(("formatAttributesBold:"))),
|
||||||
UIMenuItem(title: self.stringItalic, action: Selector(("formatAttributesItalic:"))),
|
UIMenuItem(title: self.stringItalic, action: Selector(("formatAttributesItalic:"))),
|
||||||
UIMenuItem(title: self.stringMonospace, action: Selector(("formatAttributesMonospace:"))),
|
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.isMenuVisible = true
|
||||||
UIMenuController.shared.update()
|
UIMenuController.shared.update()
|
||||||
@ -56,6 +60,8 @@ final class ChatTextInputMenu {
|
|||||||
self.stringItalic = strings.TextFormat_Italic
|
self.stringItalic = strings.TextFormat_Italic
|
||||||
self.stringMonospace = strings.TextFormat_Monospace
|
self.stringMonospace = strings.TextFormat_Monospace
|
||||||
self.stringLink = strings.TextFormat_Link
|
self.stringLink = strings.TextFormat_Link
|
||||||
|
self.stringStrikethrough = strings.TextFormat_Strikethrough
|
||||||
|
self.stringUnderline = strings.TextFormat_Underline
|
||||||
}
|
}
|
||||||
|
|
||||||
func activate() {
|
func activate() {
|
||||||
|
|||||||
@ -230,6 +230,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||||||
private var currentPlaceholder: String?
|
private var currentPlaceholder: String?
|
||||||
|
|
||||||
private var presentationInterfaceState: ChatPresentationInterfaceState?
|
private var presentationInterfaceState: ChatPresentationInterfaceState?
|
||||||
|
private var initializedPlaceholder = false
|
||||||
|
|
||||||
private var keepSendButtonEnabled = false
|
private var keepSendButtonEnabled = false
|
||||||
private var extendedSearchLayout = 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
|
let placeholder: String
|
||||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
if interfaceState.interfaceState.silentPosting {
|
if interfaceState.interfaceState.silentPosting {
|
||||||
@ -1342,7 +1345,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||||||
} else {
|
} else {
|
||||||
return ASEditableTextNodeTargetForAction(target: nil)
|
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 {
|
if case .format = self.inputMenu.state {
|
||||||
return ASEditableTextNodeTargetForAction(target: self)
|
return ASEditableTextNodeTargetForAction(target: self)
|
||||||
} else {
|
} else {
|
||||||
@ -1385,6 +1388,20 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||||||
self.interfaceInteraction?.openLinkEditing()
|
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 {
|
@objc func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||||
self.updateActivity()
|
self.updateActivity()
|
||||||
var cleanText = text
|
var cleanText = text
|
||||||
|
|||||||
@ -77,12 +77,12 @@ public class ContactsController: ViewController {
|
|||||||
|
|
||||||
var switchToChatsController: (() -> Void)?
|
var switchToChatsController: (() -> Void)?
|
||||||
|
|
||||||
|
|
||||||
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
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) {
|
public init(context: AccountContext) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
|
|||||||
@ -424,7 +424,7 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: highlightProgress)
|
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: highlightProgress)
|
||||||
} else {
|
} else {
|
||||||
if self.highlightedBackgroundNode.supernode != nil {
|
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 let strongSelf = self {
|
||||||
if completed {
|
if completed {
|
||||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
|||||||
@ -262,6 +262,8 @@ public func createChannelController(context: AccountContext) -> ViewController {
|
|||||||
switch error {
|
switch error {
|
||||||
case .generic, .tooMuchLocationBasedGroups:
|
case .generic, .tooMuchLocationBasedGroups:
|
||||||
text = presentationData.strings.Login_UnknownError
|
text = presentationData.strings.Login_UnknownError
|
||||||
|
case .tooMuchJoined:
|
||||||
|
text = presentationData.strings.CreateGroup_ChannelsTooMuch
|
||||||
case .restricted:
|
case .restricted:
|
||||||
text = presentationData.strings.Common_ActionNotAllowedError
|
text = presentationData.strings.Common_ActionNotAllowedError
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -356,6 +356,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
|||||||
return .generic
|
return .generic
|
||||||
case .restricted:
|
case .restricted:
|
||||||
return .restricted
|
return .restricted
|
||||||
|
case .tooMuchJoined:
|
||||||
|
return .tooMuchJoined
|
||||||
case .tooMuchLocationBasedGroups:
|
case .tooMuchLocationBasedGroups:
|
||||||
return .tooMuchLocationBasedGroups
|
return .tooMuchLocationBasedGroups
|
||||||
case let .serverProvided(error):
|
case let .serverProvided(error):
|
||||||
@ -381,6 +383,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
|||||||
return .generic
|
return .generic
|
||||||
case .restricted:
|
case .restricted:
|
||||||
return .restricted
|
return .restricted
|
||||||
|
case .tooMuchJoined:
|
||||||
|
return .tooMuchJoined
|
||||||
case .tooMuchLocationBasedGroups:
|
case .tooMuchLocationBasedGroups:
|
||||||
return .tooMuchLocationBasedGroups
|
return .tooMuchLocationBasedGroups
|
||||||
case let .serverProvided(error):
|
case let .serverProvided(error):
|
||||||
@ -448,6 +452,8 @@ public func createGroupController(context: AccountContext, peerIds: [PeerId], in
|
|||||||
text = presentationData.strings.Login_UnknownError
|
text = presentationData.strings.Login_UnknownError
|
||||||
case .restricted:
|
case .restricted:
|
||||||
text = presentationData.strings.Common_ActionNotAllowedError
|
text = presentationData.strings.Common_ActionNotAllowedError
|
||||||
|
case .tooMuchJoined:
|
||||||
|
text = presentationData.strings.CreateGroup_ChannelsTooMuch
|
||||||
case .tooMuchLocationBasedGroups:
|
case .tooMuchLocationBasedGroups:
|
||||||
text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch
|
text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -54,7 +54,7 @@ final class DeviceLocationManager: NSObject, CLLocationManagerDelegate {
|
|||||||
}
|
}
|
||||||
self.manager.delegate = self
|
self.manager.delegate = self
|
||||||
self.manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
self.manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
||||||
self.manager.distanceFilter = 20.0
|
self.manager.distanceFilter = 10.0
|
||||||
self.manager.activityType = .other
|
self.manager.activityType = .other
|
||||||
self.manager.pausesLocationUpdatesAutomatically = false
|
self.manager.pausesLocationUpdatesAutomatically = false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1815,13 +1815,13 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
|||||||
|> deliverOnMainQueue).start(error: { error in
|
|> deliverOnMainQueue).start(error: { error in
|
||||||
if peers.count == 1, case .restricted = error {
|
if peers.count == 1, case .restricted = error {
|
||||||
switch peers[0] {
|
switch peers[0] {
|
||||||
case let .peer(peerId):
|
case let .peer(peerId):
|
||||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> 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)
|
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:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -105,6 +105,13 @@ public final class JoinLinkPreviewController: ViewController {
|
|||||||
strongSelf.dismiss()
|
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 let separatorNode: ASDisplayNode
|
||||||
|
|
||||||
private var validLayout: (CGSize, CGFloat, CGFloat)?
|
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) {
|
init(accountPeerId: PeerId, theme: PresentationTheme, strings: PresentationStrings, tapAction: @escaping () -> Void, close: @escaping () -> Void) {
|
||||||
self.accountPeerId = accountPeerId
|
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)
|
let titleString = NSAttributedString(string: self.strings.Conversation_LiveLocation, font: titleFont, textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||||
var subtitleString: NSAttributedString?
|
var subtitleString: NSAttributedString?
|
||||||
if let (peers, mode) = self.peersAndMode {
|
if let (peers, mode, canClose) = self.peersAndMode {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .summary:
|
case .summary:
|
||||||
let text: String
|
let text: String
|
||||||
@ -119,6 +119,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
subtitleString = NSAttributedString(string: text, font: subtitleFont, textColor: self.theme.rootController.navigationBar.secondaryTextColor)
|
subtitleString = NSAttributedString(string: text, font: subtitleFont, textColor: self.theme.rootController.navigationBar.secondaryTextColor)
|
||||||
case .peer:
|
case .peer:
|
||||||
|
self.closeButton.isHidden = !canClose
|
||||||
let filteredPeers = peers.filter {
|
let filteredPeers = peers.filter {
|
||||||
$0.id != self.accountPeerId
|
$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)))
|
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) {
|
func update(peers: [Peer], mode: LocationBroadcastNavigationAccessoryPanelMode, canClose: Bool) {
|
||||||
self.peersAndMode = (peers, mode)
|
self.peersAndMode = (peers, mode, canClose)
|
||||||
if let layout = validLayout {
|
if let layout = validLayout {
|
||||||
self.updateLayout(size: layout.0, leftInset: layout.1, rightInset: layout.2, transition: .immediate)
|
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
|
|> mapToSignal { _ -> Signal<Void, AddChannelMemberError> in
|
||||||
return .complete()
|
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> {
|
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)
|
context.sharedContext.switchToAccount(id: id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
var didAppear = false
|
controller.didAppear = { _ in
|
||||||
controller.didAppear = { [weak controller] _ in
|
|
||||||
updatePassport()
|
updatePassport()
|
||||||
updateNotifyExceptions()
|
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
|
controller.previewItemWithTag = { tag in
|
||||||
if let tag = tag as? SettingsEntryTag, case let .account(id) = tag {
|
if let tag = tag as? SettingsEntryTag, case let .account(id) = tag {
|
||||||
|
|||||||
@ -184,24 +184,24 @@ public class TelegramController: ViewController, KeyShortcutResponder {
|
|||||||
peers?.append(author)
|
peers?.append(author)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (peers, nil)
|
return (peers, outgoingMessages)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
self.locationBroadcastMode = .summary
|
self.locationBroadcastMode = .summary
|
||||||
signal = liveLocationManager.summaryManager.broadcastingToMessages()
|
signal = liveLocationManager.summaryManager.broadcastingToMessages()
|
||||||
|> map { messages -> ([Peer]?, [MessageId: Message]?) in
|
|> map { messages -> ([Peer]?, [MessageId: Message]?) in
|
||||||
if messages.isEmpty {
|
if messages.isEmpty {
|
||||||
return (nil, nil)
|
return (nil, nil)
|
||||||
} else {
|
} else {
|
||||||
var peers: [Peer] = []
|
var peers: [Peer] = []
|
||||||
for message in messages.values.sorted(by: { $0.index < $1.index }) {
|
for message in messages.values.sorted(by: { $0.index < $1.index }) {
|
||||||
if let peer = message.peers[message.id.peerId] {
|
if let peer = message.peers[message.id.peerId] {
|
||||||
peers.append(peer)
|
peers.append(peer)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (peers, messages)
|
|
||||||
}
|
}
|
||||||
|
return (peers, messages)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +223,16 @@ public class TelegramController: ViewController, KeyShortcutResponder {
|
|||||||
if wasEmpty != (peers == nil) {
|
if wasEmpty != (peers == nil) {
|
||||||
strongSelf.requestLayout(transition: .animated(duration: 0.4, curve: .spring))
|
strongSelf.requestLayout(transition: .animated(duration: 0.4, curve: .spring))
|
||||||
} else if let peers = peers, let locationBroadcastMode = strongSelf.locationBroadcastMode {
|
} 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
|
self.locationBroadcastAccessoryPanel = locationBroadcastAccessoryPanel
|
||||||
locationBroadcastAccessoryPanel.frame = panelFrame
|
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)
|
locationBroadcastAccessoryPanel.updateLayout(size: panelFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: .immediate)
|
||||||
if transition.isAnimated {
|
if transition.isAnimated {
|
||||||
locationBroadcastAccessoryPanel.animateIn(transition)
|
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)
|
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)
|
let targetScale = max(transformedFrame.size.width / videoNode.layer.bounds.size.width, transformedFrame.size.height / videoNode.layer.bounds.size.height)
|
||||||
|
|
||||||
videoNode.backgroundColor = .clear
|
videoNode.backgroundColor = .clear
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user