Psa improvements

This commit is contained in:
Ali 2020-04-25 16:28:00 +04:00
parent 2a06b2dede
commit 049cba24bf
29 changed files with 4507 additions and 4348 deletions

View File

@ -560,7 +560,6 @@
"Message.StickerText" = "Sticker %@";
"Message.Audio" = "Voice Message";
"Message.ForwardedMessage" = "Forwarded Message\nFrom: %@";
"Message.GenericForwardedPsa" = "Public Service Announcement\nFrom: %@";
"Message.Animation" = "GIF";
"Message.Game" = "Game";
@ -3174,8 +3173,6 @@ Unused sets are archived when you add more.";
"DialogList.AdNoticeAlert" = "The proxy you are using displays a sponsored channel in your chat list.";
"SocksProxySetup.AdNoticeHelp" = "This proxy may display a sponsored channel in your chat list. This doesn't reveal your Telegram traffic.";
"DialogList.PsaLabel" = "PSA";
"SocksProxySetup.ShareProxyList" = "Share Proxy List";
"Privacy.SecretChatsTitle" = "SECRET CHATS";
@ -5488,3 +5485,13 @@ Any member of this group will be able to see messages in the channel.";
"CreatePoll.ExplanationInfo" = "Users will see this comment after choosing a wrong answer, good for educational purposes.";
"FeaturedStickers.OtherSection" = "OTHER STICKERS";
"ChatList.GenericPsaAlert" = "This provides public service announcements in your chat list.";
"ChatList.PsaAlert.covid" = "This message provides you with a public service announcement in relation to the undergoing pandemics. Learn more about this initiative at https://telegram.org/blog/coronavirus";
"ChatList.GenericPsaLabel" = "PSA";
"ChatList.PsaLabel.covid" = "Covid-19";
"Chat.GenericPsaTooltip" = "This is a public service announcement";
"Chat.PsaTooltip.covid" = "This message provides you with a public service announcement in relation to the undergoing pandemics. Learn more about this initiative at https://telegram.org/blog/coronavirus";
"Message.GenericForwardedPsa" = "Public Service Announcement\nFrom: %@";
"Message.ForwardedPsa.covid" = "Covid-19 Notification\nFrom: %@";

View File

@ -209,9 +209,9 @@ public final class NavigateToChatControllerParams {
public let animated: Bool
public let options: NavigationAnimationOptions
public let parentGroupId: PeerGroupId?
public let completion: () -> Void
public let completion: (ChatController) -> Void
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
self.navigationController = navigationController
self.chatController = chatController
self.context = context

View File

@ -371,6 +371,7 @@ public protocol ChatController: ViewController {
func updatePresentationMode(_ mode: ChatControllerPresentationMode)
func beginMessageSearch(_ query: String)
func displayPromoAnnouncement(text: String)
}
public protocol ChatMessagePrevewItemNode: class {

View File

@ -562,11 +562,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
strongSelf.toggleArchivedFolderHiddenByDefault()
}
self.chatListDisplayNode.containerNode.hidePsa = { [weak self] messageId in
self.chatListDisplayNode.containerNode.hidePsa = { [weak self] peerId in
guard let strongSelf = self else {
return
}
strongSelf.hidePsa(messageId)
strongSelf.hidePsa(peerId)
}
self.chatListDisplayNode.containerNode.deletePeerChat = { [weak self] peerId in
@ -579,29 +579,47 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
self.chatListDisplayNode.containerNode.peerSelected = { [weak self] peer, animated, promoInfo in
if let strongSelf = self {
if let navigationController = strongSelf.navigationController as? NavigationController {
if let promoInfo = promoInfo, case .proxy = promoInfo {
let _ = (ApplicationSpecificNotice.getProxyAdsAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager)
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
if !value {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.DialogList_AdNoticeAlert, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
if let strongSelf = self {
let _ = ApplicationSpecificNotice.setProxyAdsAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager).start()
}
})]), in: .window(.root))
}
})
}
var scrollToEndIfExists = false
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
scrollToEndIfExists = true
}
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, completion: { [weak self] in
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, completion: { [weak self] controller in
self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true)
if let promoInfo = promoInfo {
switch promoInfo {
case .proxy:
let _ = (ApplicationSpecificNotice.getProxyAdsAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager)
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
if !value {
controller.displayPromoAnnouncement(text: strongSelf.presentationData.strings.DialogList_AdNoticeAlert)
let _ = ApplicationSpecificNotice.setProxyAdsAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager).start()
}
})
case let .psa(type, _):
let _ = (ApplicationSpecificNotice.getPsaAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id)
|> deliverOnMainQueue).start(next: { value in
guard let strongSelf = self else {
return
}
if !value {
var text = strongSelf.presentationData.strings.ChatList_GenericPsaAlert
let key = "ChatList.PsaAlert.\(type)"
if let string = strongSelf.presentationData.strings.primaryComponent.dict[key] {
text = string
} else if let string = strongSelf.presentationData.strings.secondaryComponent?.dict[key] {
text = string
}
controller.displayPromoAnnouncement(text: text)
let _ = ApplicationSpecificNotice.setPsaAcknowledgment(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start()
}
})
}
}
}))
}
}
@ -1989,30 +2007,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
})
}
func hidePsa(_ id: MessageId) {
let _ = (self.context.account.postbox.transaction { transaction -> PeerId? in
var peerId: PeerId?
for item in transaction.getAdditionalChatListItems() {
if let item = item as? PromoChatListItem {
peerId = item.peerId
}
}
return peerId
func hidePsa(_ id: PeerId) {
self.chatListDisplayNode.containerNode.updateState { state in
var state = state
state.hiddenPsaPeerId = id
state.peerIdWithRevealedOptions = nil
return state
}
|> deliverOnMainQueue).start(next: { [weak self] _ in
guard let strongSelf = self else {
return
}
strongSelf.chatListDisplayNode.containerNode.updateState { state in
var state = state
state.hiddenPsaPeerId = id.peerId
state.peerIdWithRevealedOptions = nil
return state
}
let _ = hideAccountPromoInfoChat(account: strongSelf.context.account, peerId: id.peerId).start()
})
let _ = hideAccountPromoInfoChat(account: self.context.account, peerId: id).start()
}
func deletePeerChat(peerId: PeerId) {

View File

@ -194,7 +194,7 @@ private final class ChatListShimmerNode: ASDisplayNode {
let peer1 = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: 1), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
let timestamp1: Int32 = 100000
let peers = SimpleDictionary<PeerId, Peer>()
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
}, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in
gesture?.cancel()
}, present: { _ in })
@ -475,8 +475,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
itemNode.listNode.toggleArchivedFolderHiddenByDefault = { [weak self] in
self?.toggleArchivedFolderHiddenByDefault?()
}
itemNode.listNode.hidePsa = { [weak self] messageId in
self?.hidePsa?(messageId)
itemNode.listNode.hidePsa = { [weak self] peerId in
self?.hidePsa?(peerId)
}
itemNode.listNode.deletePeerChat = { [weak self] peerId in
self?.deletePeerChat?(peerId)
@ -526,7 +526,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
var presentAlert: ((String) -> Void)?
var present: ((ViewController) -> Void)?
var toggleArchivedFolderHiddenByDefault: (() -> Void)?
var hidePsa: ((MessageId) -> Void)?
var hidePsa: ((PeerId) -> Void)?
var deletePeerChat: ((PeerId) -> Void)?
var peerSelected: ((Peer, Bool, ChatListNodeEntryPromoInfo?) -> Void)?
var groupSelected: ((PeerGroupId) -> Void)?

View File

@ -415,7 +415,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
}
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
interaction.peerSelected(peer)
interaction.peerSelected(peer, nil)
}, contextAction: peerContextAction.flatMap { peerContextAction in
return { node, gesture in
if let chatPeer = chatPeer, chatPeer.id.namespace != Namespaces.Peer.SecretChat {
@ -478,7 +478,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
}
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
interaction.peerSelected(peer.peer)
interaction.peerSelected(peer.peer, nil)
}, contextAction: peerContextAction.flatMap { peerContextAction in
return { node, gesture in
peerContextAction(peer.peer, .search, node, gesture)
@ -997,7 +997,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
let previousSearchItems = Atomic<[ChatListSearchEntry]?>(value: nil)
let interaction = ChatListNodeInteraction(activateSearch: {
}, peerSelected: { [weak self] peer in
}, peerSelected: { [weak self] peer, _ in
self?.view.endEditing(true)
openPeer(peer, false)
let _ = addRecentlySearchedPeer(postbox: context.account.postbox, peerId: peer.id).start()

View File

@ -128,9 +128,9 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
if let message = message, let peer = peer.peer {
self.interaction.messageSelected(peer, message, promoInfo)
} else if let peer = peer.peer {
self.interaction.peerSelected(peer)
self.interaction.peerSelected(peer, promoInfo)
} else if let peer = peer.peers[peer.peerId] {
self.interaction.peerSelected(peer)
self.interaction.peerSelected(peer, promoInfo)
}
case let .groupReference(groupId, _, _, _, _):
self.interaction.groupSelected(groupId)
@ -1006,8 +1006,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
switch promoInfo {
case .proxy:
dateAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_AdLabel, font: dateFont, textColor: theme.dateTextColor)
case .psa:
dateAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_PsaLabel, font: dateFont, textColor: theme.dateTextColor)
case let .psa(type, _):
var text = item.presentationData.strings.ChatList_GenericPsaLabel
let key = "ChatList.PsaLabel.\(type)"
if let string = item.presentationData.strings.primaryComponent.dict[key] {
text = string
} else if let string = item.presentationData.strings.secondaryComponent?.dict[key] {
text = string
}
dateAttributedString = NSAttributedString(string: text, font: dateFont, textColor: theme.dateTextColor)
}
} else {
dateAttributedString = NSAttributedString(string: dateText, font: dateFont, textColor: theme.dateTextColor)
@ -1862,10 +1869,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
item.interaction.toggleArchivedFolderHiddenByDefault()
close = false
case RevealOptionKey.hidePsa.rawValue:
if let item = self.item, case let .peer(message, _, _, _, _, _, _, _, _, _, _, _) = item.content {
if let message = message {
item.interaction.hidePsa(message.id)
}
if let item = self.item, case let .peer(_, peer, _, _, _, _, _, _, _, _, _, _) = item.content {
item.interaction.hidePsa(peer.peerId)
}
close = false
self.skipFadeout = true

View File

@ -49,7 +49,7 @@ final class ChatListHighlightedLocation {
public final class ChatListNodeInteraction {
let activateSearch: () -> Void
let peerSelected: (Peer) -> Void
let peerSelected: (Peer, ChatListNodeEntryPromoInfo?) -> Void
let disabledPeerSelected: (Peer) -> Void
let togglePeerSelected: (PeerId) -> Void
let additionalCategorySelected: (Int) -> Void
@ -63,14 +63,14 @@ public final class ChatListNodeInteraction {
let updatePeerGrouping: (PeerId, Bool) -> Void
let togglePeerMarkedUnread: (PeerId, Bool) -> Void
let toggleArchivedFolderHiddenByDefault: () -> Void
let hidePsa: (MessageId) -> Void
let hidePsa: (PeerId) -> Void
let activateChatPreview: (ChatListItem, ASDisplayNode, ContextGesture?) -> Void
let present: (ViewController) -> Void
public var searchTextHighightState: String?
var highlightedChatLocation: ChatListHighlightedLocation?
public init(activateSearch: @escaping () -> Void, peerSelected: @escaping (Peer) -> Void, disabledPeerSelected: @escaping (Peer) -> Void, togglePeerSelected: @escaping (PeerId) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (Peer, Message, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (PeerGroupId) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setItemPinned: @escaping (PinnedItemId, Bool) -> Void, setPeerMuted: @escaping (PeerId, Bool) -> Void, deletePeer: @escaping (PeerId) -> Void, updatePeerGrouping: @escaping (PeerId, Bool) -> Void, togglePeerMarkedUnread: @escaping (PeerId, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (MessageId) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) {
public init(activateSearch: @escaping () -> Void, peerSelected: @escaping (Peer, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (Peer) -> Void, togglePeerSelected: @escaping (PeerId) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (Peer, Message, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (PeerGroupId) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setItemPinned: @escaping (PinnedItemId, Bool) -> Void, setPeerMuted: @escaping (PeerId, Bool) -> Void, deletePeer: @escaping (PeerId) -> Void, updatePeerGrouping: @escaping (PeerId, Bool) -> Void, togglePeerMarkedUnread: @escaping (PeerId, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (PeerId) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) {
self.activateSearch = activateSearch
self.peerSelected = peerSelected
self.disabledPeerSelected = disabledPeerSelected
@ -266,7 +266,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: status, enabled: enabled, selection: editing ? .selectable(selected: selected) : .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
if let chatPeer = chatPeer {
nodeInteraction.peerSelected(chatPeer)
nodeInteraction.peerSelected(chatPeer, nil)
}
}, disabledAction: { _ in
if let chatPeer = chatPeer {
@ -333,7 +333,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: status, enabled: enabled, selection: editing ? .selectable(selected: selected) : .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
if let chatPeer = chatPeer {
nodeInteraction.peerSelected(chatPeer)
nodeInteraction.peerSelected(chatPeer, nil)
}
}, disabledAction: { _ in
if let chatPeer = chatPeer {
@ -429,7 +429,7 @@ public final class ChatListNode: ListView {
public var presentAlert: ((String) -> Void)?
public var present: ((ViewController) -> Void)?
public var toggleArchivedFolderHiddenByDefault: (() -> Void)?
public var hidePsa: ((MessageId) -> Void)?
public var hidePsa: ((PeerId) -> Void)?
public var activateChatPreview: ((ChatListItem, ASDisplayNode, ContextGesture?) -> Void)?
private var theme: PresentationTheme
@ -534,9 +534,9 @@ public final class ChatListNode: ListView {
if let strongSelf = self, let activateSearch = strongSelf.activateSearch {
activateSearch()
}
}, peerSelected: { [weak self] peer in
}, peerSelected: { [weak self] peer, promoInfo in
if let strongSelf = self, let peerSelected = strongSelf.peerSelected {
peerSelected(peer, true, nil)
peerSelected(peer, true, promoInfo)
}
}, disabledPeerSelected: { [weak self] peer in
if let strongSelf = self, let disabledPeerSelected = strongSelf.disabledPeerSelected {

View File

@ -226,7 +226,7 @@ public class ContactsController: ViewController {
self?.deactivateSearch(animated: false)
self?.switchToChatsController?()
}
}, scrollToEndIfExists: scrollToEndIfExists, options: [.removeOnMasterDetails], completion: { [weak self] in
}, scrollToEndIfExists: scrollToEndIfExists, options: [.removeOnMasterDetails], completion: { [weak self] _ in
if let strongSelf = self {
strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true)
}

View File

@ -183,7 +183,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese
if let dimensions = file.dimensions {
pixelsCount = Int(dimensions.width) * Int(dimensions.height)
}
if true /*(file.size == nil || file.size! < 4 * 1024 * 1024) && pixelsCount < 4096 * 4096*/ {
if (file.size == nil || file.size! < 4 * 1024 * 1024) && pixelsCount < 4096 * 4096 {
return ChatImageGalleryItem(context: context, presentationData: presentationData, message: message, location: location, performAction: performAction, openActionOptions: openActionOptions)
} else {
return ChatDocumentGalleryItem(context: context, presentationData: presentationData, message: message, location: location)

View File

@ -351,7 +351,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
}
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))()
if largestSize.width > 2600 || largestSize.height > 2600 {
/*if largestSize.width > 2600 || largestSize.height > 2600 {
self.dataDisposable.set((self.context.account.postbox.mediaBox.resourceData(fileReference.media.resource)
|> deliverOnMainQueue).start(next: { [weak self] data in
guard let strongSelf = self else {
@ -362,9 +362,9 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
}
strongSelf.updateImageFromFile(path: data.path)
}))
} else {
} else {*/
self.imageNode.setSignal(chatMessageImageFile(account: context.account, fileReference: fileReference, thumbnail: false), dispatchOnDisplayLink: false)
}
//}
self.zoomableContent = (largestSize.cgSize, self.imageNode)
self.setupStatus(resource: fileReference.media.resource)

View File

@ -48,7 +48,7 @@ public final class HashtagSearchController: TelegramBaseController {
return result.messages.map({ .message($0, RenderedPeer(message: $0), result.readStates[$0.id.peerId], chatListPresentationData) })
}
let interaction = ChatListNodeInteraction(activateSearch: {
}, peerSelected: { peer in
}, peerSelected: { _, _ in
}, disabledPeerSelected: { _ in
}, togglePeerSelected: { _ in
}, additionalCategorySelected: { _ in

View File

@ -2,6 +2,7 @@ import Foundation
public protocol AdditionalChatListItem: PostboxCoding {
var peerId: PeerId { get }
var includeIfNoHistory: Bool { get }
func isEqual(to other: AdditionalChatListItem) -> Bool
}

View File

@ -664,7 +664,7 @@ final class ChatListTable: Table {
return result
}
func getStandalone(peerId: PeerId, messageHistoryTable: MessageHistoryTable) -> ChatListIntermediateEntry? {
func getStandalone(peerId: PeerId, messageHistoryTable: MessageHistoryTable, includeIfNoHistory: Bool) -> ChatListIntermediateEntry? {
let index = self.indexTable.get(peerId: peerId)
switch index.inclusion {
case .ifHasMessagesOrOneOf:
@ -674,8 +674,11 @@ final class ChatListTable: Table {
}
if let topMessageIndex = index.topMessageIndex {
return ChatListIntermediateEntry.message(ChatListIndex(pinningIndex: nil, messageIndex: topMessageIndex), topMessageIndex)
} else if includeIfNoHistory {
return ChatListIntermediateEntry.message(ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 1), timestamp: 1)), nil)
} else {
return nil
}
return nil
}
func getEntry(groupId: PeerGroupId, peerId: PeerId, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable) -> ChatListIntermediateEntry? {

View File

@ -363,7 +363,7 @@ final class MutableChatListView {
self.additionalItems = items
self.additionalItemIds = Set(items.map { $0.peerId })
for item in items {
if let entry = postbox.chatListTable.getStandalone(peerId: item.peerId, messageHistoryTable: postbox.messageHistoryTable) {
if let entry = postbox.chatListTable.getStandalone(peerId: item.peerId, messageHistoryTable: postbox.messageHistoryTable, includeIfNoHistory: item.includeIfNoHistory) {
self.additionalItemEntries.append(MutableChatListAdditionalItemEntry(
entry: MutableChatListEntry(entry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable),
info: item
@ -534,7 +534,7 @@ final class MutableChatListView {
if updateAdditionalItems {
self.additionalItemEntries.removeAll()
for item in self.additionalItems {
if let entry = postbox.chatListTable.getStandalone(peerId: item.peerId, messageHistoryTable: postbox.messageHistoryTable) {
if let entry = postbox.chatListTable.getStandalone(peerId: item.peerId, messageHistoryTable: postbox.messageHistoryTable, includeIfNoHistory: item.includeIfNoHistory) {
self.additionalItemEntries.append(MutableChatListAdditionalItemEntry(
entry: MutableChatListEntry(entry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable),
info: item

View File

@ -213,7 +213,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
var items: [ChatListItem] = []
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
}, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
}, activateChatPreview: { _, _, gesture in
gesture?.cancel()

View File

@ -766,7 +766,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
var items: [ChatListItem] = []
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
}, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
}, activateChatPreview: { _, _, gesture in
gesture?.cancel()

View File

@ -350,7 +350,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
var items: [ChatListItem] = []
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, additionalCategorySelected: { _ in
}, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in
}, activateChatPreview: { _, _, gesture in
gesture?.cancel()

View File

@ -362,10 +362,7 @@ public final class AccountViewTracker {
return account.postbox.transaction { transaction -> Void in
if let webpage = webpage {
transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType)
}
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
var media = currentMessage.media
for i in 0 ..< media.count {
if let _ = media[i] as? TelegramMediaWebpage {
@ -452,7 +449,7 @@ public final class AccountViewTracker {
if let message = messages[messageId] {
for media in message.media {
if let poll = media as? TelegramMediaPoll {
if let deadlineTimeout = poll.deadlineTimeout, message.id.namespace == Namespaces.Message.Cloud {
if let _ = poll.deadlineTimeout, message.id.namespace == Namespaces.Message.Cloud {
let startDate: Int32
if let forwardInfo = message.forwardInfo {
startDate = forwardInfo.date
@ -598,10 +595,7 @@ public final class AccountViewTracker {
for i in 0 ..< messageIds.count {
if i < viewCounts.count {
transaction.updateMessage(messageIds[i], update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType)
}
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
var attributes = currentMessage.attributes
loop: for j in 0 ..< attributes.count {
if let attribute = attributes[j] as? ViewCountMessageAttribute {

View File

@ -15,6 +15,15 @@ public final class PromoChatListItem: AdditionalChatListItem {
public let peerId: PeerId
public let kind: Kind
public var includeIfNoHistory: Bool {
switch self.kind {
case .proxy:
return false
case let .psa(_, message):
return message != nil
}
}
public init(peerId: PeerId, kind: Kind) {
self.peerId = peerId
self.kind = kind
@ -108,8 +117,8 @@ func managedPromoInfoUpdates(postbox: Postbox, network: Network, viewTracker: Ac
}
var additionalChatListItems: [AdditionalChatListItem] = []
if let channel = transaction.getPeer(peer.peerId) as? TelegramChannel {
additionalChatListItems.append(PromoChatListItem(peerId: channel.id, kind: kind))
if let parsedPeer = transaction.getPeer(peer.peerId) {
additionalChatListItems.append(PromoChatListItem(peerId: parsedPeer.id, kind: kind))
}
transaction.replaceAdditionalChatListItems(additionalChatListItems)
@ -139,7 +148,9 @@ func managedPromoInfoUpdates(postbox: Postbox, network: Network, viewTracker: Ac
return Signal { subscriber in
let disposables = DisposableSet()
for item in items {
disposables.add(viewTracker.polledChannel(peerId: item).start())
if item.namespace == Namespaces.Peer.CloudChannel {
disposables.add(viewTracker.polledChannel(peerId: item).start())
}
}
return ActionDisposable {

View File

@ -163,7 +163,8 @@ private struct ApplicationSpecificNoticeKeys {
private static let globalNamespace: Int32 = 2
private static let permissionsNamespace: Int32 = 3
private static let peerReportNamespace: Int32 = 4
private static let inlineBotLocationRequestNamespace: Int32 = 1
private static let inlineBotLocationRequestNamespace: Int32 = 5
private static let psaAcknowledgementNamespace: Int32 = 6
static func inlineBotLocationRequestNotice(peerId: PeerId) -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: inlineBotLocationRequestNamespace), key: noticeKey(peerId: peerId, key: 0))
@ -205,6 +206,10 @@ private struct ApplicationSpecificNoticeKeys {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.proxyAdsAcknowledgment.key)
}
static func psaAdsAcknowledgment(peerId: PeerId) -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: psaAcknowledgementNamespace), key: noticeKey(peerId: peerId, key: 0))
}
static func setPublicChannelLink() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.setPublicChannelLink.key)
}
@ -454,6 +459,22 @@ public struct ApplicationSpecificNotice {
}
}
public static func getPsaAcknowledgment(accountManager: AccountManager, peerId: PeerId) -> Signal<Bool, NoError> {
return accountManager.transaction { transaction -> Bool in
if let _ = transaction.getNotice(ApplicationSpecificNoticeKeys.psaAdsAcknowledgment(peerId: peerId)) as? ApplicationSpecificBoolNotice {
return true
} else {
return false
}
}
}
public static func setPsaAcknowledgment(accountManager: AccountManager, peerId: PeerId) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
transaction.setNotice(ApplicationSpecificNoticeKeys.psaAdsAcknowledgment(peerId: peerId), ApplicationSpecificBoolNotice())
}
}
public static func getPasscodeLockTips(accountManager: AccountManager) -> Signal<Bool, NoError> {
return accountManager.transaction { transaction -> Bool in
if let _ = transaction.getNotice(ApplicationSpecificNoticeKeys.passcodeLockTips()) as? ApplicationSpecificBoolNotice {

View File

@ -6463,6 +6463,80 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.present(tooltipScreen, in: .current)
}
public func displayPromoAnnouncement(text: String) {
let psaText: String = text
let psaEntities: [MessageTextEntity] = generateTextEntities(psaText, enabledTypes: .url)
var found = false
self.forEachController({ controller in
if let controller = controller as? TooltipScreen {
if controller.text == psaText {
found = true
controller.dismiss()
return false
}
}
return true
})
if found {
return
}
let tooltipScreen = TooltipScreen(text: psaText, textEntities: psaEntities, icon: .info, location: .top, shouldDismissOnTouch: { point in
return .ignore
}, openActiveTextItem: { [weak self] item, action in
guard let strongSelf = self else {
return
}
switch item {
case let .url(url):
switch action {
case .tap:
strongSelf.openUrl(url, concealed: false)
case .longTap:
strongSelf.controllerInteraction?.longTap(.url(url), nil)
}
case let .mention(peerId, mention):
switch action {
case .tap:
strongSelf.controllerInteraction?.openPeer(peerId, .default, nil)
case .longTap:
strongSelf.controllerInteraction?.longTap(.peerMention(peerId, mention), nil)
}
case let .textMention(mention):
switch action {
case .tap:
strongSelf.controllerInteraction?.openPeerMention(mention)
case .longTap:
strongSelf.controllerInteraction?.longTap(.mention(mention), nil)
}
case let .botCommand(command):
switch action {
case .tap:
strongSelf.controllerInteraction?.sendBotCommand(nil, command)
case .longTap:
strongSelf.controllerInteraction?.longTap(.command(command), nil)
}
case let .hashtag(hashtag):
switch action {
case .tap:
strongSelf.controllerInteraction?.openHashtag(nil, hashtag)
case .longTap:
strongSelf.controllerInteraction?.longTap(.hashtag(hashtag), nil)
}
}
})
self.forEachController({ controller in
if let controller = controller as? TooltipScreen {
controller.dismiss()
}
return true
})
self.present(tooltipScreen, in: .current)
}
private func displayPsa(type: String, sourceNode: ASDisplayNode, isAutomatic: Bool) {
var maybeFoundItemNode: ChatMessageItemView?
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
@ -6476,7 +6550,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let psaText: String = "This message provides you with a public service announcement in relation to the undergoing pandemics. Learn more about this initiative at https://telegram.org/blog/coronavirus"
var psaText = self.presentationData.strings.Chat_GenericPsaTooltip
let key = "Chat.PsaTooltip.\(type)"
if let string = self.presentationData.strings.primaryComponent.dict[key] {
psaText = string
} else if let string = self.presentationData.strings.secondaryComponent?.dict[key] {
psaText = string
}
let psaEntities: [MessageTextEntity] = generateTextEntities(psaText, enabledTypes: .url)
var found = false

View File

@ -123,9 +123,30 @@ class ChatMessageForwardInfoNode: ASDisplayNode {
switch type {
case let .bubble(incoming):
if let _ = psaType {
if let psaType = psaType {
titleColor = incoming ? presentationData.theme.theme.chat.message.incoming.polls.barPositive : presentationData.theme.theme.chat.message.outgoing.polls.barPositive
completeSourceString = strings.Message_GenericForwardedPsa(peerString)
var customFormat: String?
let key = "Message.ForwardedPsa.\(psaType)"
if let string = presentationData.strings.primaryComponent.dict[key] {
customFormat = string
} else if let string = presentationData.strings.secondaryComponent?.dict[key] {
customFormat = string
}
if let customFormat = customFormat {
if let range = customFormat.range(of: "%@") {
let leftPart = String(customFormat[customFormat.startIndex ..< range.lowerBound])
let rightPart = String(customFormat[range.upperBound...])
let formattedText = leftPart + peerString + rightPart
completeSourceString = (formattedText, [(0, NSRange(location: leftPart.count, length: peerString.count))])
} else {
completeSourceString = (customFormat, [])
}
} else {
completeSourceString = strings.Message_GenericForwardedPsa(peerString)
}
} else {
titleColor = incoming ? presentationData.theme.theme.chat.message.incoming.accentTextColor : presentationData.theme.theme.chat.message.outgoing.accentTextColor
completeSourceString = strings.Message_ForwardedMessage(peerString)
@ -174,7 +195,7 @@ class ChatMessageForwardInfoNode: ASDisplayNode {
var infoWidth: CGFloat = 0.0
if hasPsaInfo {
infoWidth += 44.0
infoWidth += 32.0
}
let (textLayout, textApply) = textNodeLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: constrainedSize.width - credibilityIconWidth - infoWidth, height: constrainedSize.height), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View File

@ -167,7 +167,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
}
let interaction = ChatListNodeInteraction(activateSearch: {
}, peerSelected: { _ in
}, peerSelected: { _, _ in
}, disabledPeerSelected: { _ in
}, togglePeerSelected: { _ in
}, additionalCategorySelected: { _ in

View File

@ -33,14 +33,14 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
} else if params.scrollToEndIfExists && isFirst {
controller.scrollToEndOfHistory()
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
params.completion()
params.completion(controller)
} else if params.activateMessageSearch {
controller.activateSearch()
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
params.completion()
params.completion(controller)
} else {
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
params.completion()
params.completion(controller)
}
controller.purposefulAction = params.purposefulAction
if params.activateInput {
@ -83,7 +83,9 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
resolvedKeepStack = false
}
if resolvedKeepStack {
params.navigationController.pushViewController(controller, animated: params.animated, completion: params.completion)
params.navigationController.pushViewController(controller, animated: params.animated, completion: {
params.completion(controller)
})
} else {
let viewControllers = params.navigationController.viewControllers.filter({ controller in
if controller is ChatListController {
@ -99,9 +101,13 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
}
})
if viewControllers.isEmpty {
params.navigationController.replaceAllButRootController(controller, animated: params.animated, animationOptions: params.options, completion: params.completion)
params.navigationController.replaceAllButRootController(controller, animated: params.animated, animationOptions: params.options, completion: {
params.completion(controller)
})
} else {
params.navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: params.animated, options: params.options, completion: params.completion)
params.navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: params.animated, options: params.options, completion: {
params.completion(controller)
})
}
}
if params.activateInput {

View File

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