mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
7ec1611c08
commit
f51b91aa77
@ -10992,3 +10992,5 @@ Sorry for the inconvenience.";
|
||||
"Premium.MessageTags" = "Tags for Messages";
|
||||
"Premium.MessageTagsInfo" = "Organize your Saved Messages with tags for quicker access.";
|
||||
"Premium.MessageTags.Proceed" = "About Telegram Premium";
|
||||
|
||||
"Chat.SavedMessagesTabInfoText" = "Messages you send to **Saved Messages**";
|
||||
|
@ -196,6 +196,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
||||
case incomingVideoMessagePlayOnceTip = 62
|
||||
case outgoingVideoMessagePlayOnceTip = 63
|
||||
case dismissedMessageTagsBadge = 64
|
||||
case savedMessageTagLabelSuggestion = 65
|
||||
|
||||
var key: ValueBoxKey {
|
||||
let v = ValueBoxKey(length: 4)
|
||||
@ -509,6 +510,10 @@ private struct ApplicationSpecificNoticeKeys {
|
||||
static func dismissedMessageTagsBadge() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedMessageTagsBadge.key)
|
||||
}
|
||||
|
||||
static func savedMessageTagLabelSuggestion() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.savedMessageTagLabelSuggestion.key)
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationSpecificNotice {
|
||||
@ -2106,4 +2111,31 @@ public struct ApplicationSpecificNotice {
|
||||
}
|
||||
|> take(1)
|
||||
}
|
||||
|
||||
public static func getSavedMessageTagLabelSuggestion(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||
return accountManager.transaction { transaction -> Int32 in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.savedMessageTagLabelSuggestion())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
return value.value
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func incrementSavedMessageTagLabelSuggestion(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int = 1) -> Signal<Int, NoError> {
|
||||
return accountManager.transaction { transaction -> Int in
|
||||
var currentValue: Int32 = 0
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.savedMessageTagLabelSuggestion())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
currentValue = value.value
|
||||
}
|
||||
let previousValue = currentValue
|
||||
currentValue += Int32(count)
|
||||
|
||||
if let entry = CodableEntry(ApplicationSpecificCounterNotice(value: currentValue)) {
|
||||
transaction.setNotice(ApplicationSpecificNoticeKeys.savedMessageTagLabelSuggestion(), entry)
|
||||
}
|
||||
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
selectedForeground: themeColors.reactionActiveForeground.argb,
|
||||
extractedBackground: arguments.presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: arguments.presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : arguments.presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
@ -408,7 +408,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
selectedForeground: themeColors.reactionActiveForeground.argb,
|
||||
extractedBackground: arguments.presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: arguments.presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : arguments.presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
|
@ -79,7 +79,7 @@ public final class MessageReactionButtonsNode: ASDisplayNode {
|
||||
selectedForeground: themeColors.reactionActiveForeground.argb,
|
||||
extractedBackground: presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
@ -92,7 +92,7 @@ public final class MessageReactionButtonsNode: ASDisplayNode {
|
||||
selectedForeground: themeColors.reactionActiveForeground.argb,
|
||||
extractedBackground: presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
@ -110,7 +110,7 @@ public final class MessageReactionButtonsNode: ASDisplayNode {
|
||||
selectedForeground: themeColors.reactionActiveForeground.argb,
|
||||
extractedBackground: presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
extractedSelectedForeground: presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
|
@ -16,6 +16,7 @@ import TextNodeWithEntities
|
||||
import PremiumUI
|
||||
import TooltipUI
|
||||
import TopMessageReactions
|
||||
import TelegramNotices
|
||||
|
||||
extension ChatControllerImpl {
|
||||
func openMessageContextMenu(message: Message, selectAll: Bool, node: ASDisplayNode, frame: CGRect, anyRecognizer: UIGestureRecognizer?, location: CGPoint?) -> Void {
|
||||
@ -396,13 +397,31 @@ extension ChatControllerImpl {
|
||||
standaloneReactionAnimation.frame = self.chatDisplayNode.bounds
|
||||
self.chatDisplayNode.addSubnode(standaloneReactionAnimation)
|
||||
}, completion: { [weak self, weak itemNode, weak targetView] in
|
||||
guard let self, let itemNode = itemNode, let targetView = targetView else {
|
||||
guard let self, let itemNode, let targetView else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = self
|
||||
let _ = itemNode
|
||||
let _ = targetView
|
||||
let _ = (ApplicationSpecificNotice.getSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak targetView, weak itemNode] value in
|
||||
guard let self, let targetView, let itemNode else {
|
||||
return
|
||||
}
|
||||
if value >= 3 {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = itemNode
|
||||
|
||||
//TODO:localize
|
||||
let rect = self.chatDisplayNode.view.convert(targetView.bounds, from: targetView).insetBy(dx: -8.0, dy: -8.0)
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: .plain(text: "Tap and hold to add a name to your tag"), location: .point(rect, .bottom), displayDuration: .custom(5.0), shouldDismissOnTouch: { point, _ in
|
||||
return .ignore
|
||||
})
|
||||
self.present(tooltipScreen, in: .current)
|
||||
|
||||
let _ = ApplicationSpecificNotice.incrementSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager).startStandalone()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
controller.dismiss()
|
||||
|
@ -1901,6 +1901,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
let current = listInsets
|
||||
listInsets.top = current.bottom
|
||||
listInsets.bottom = current.top
|
||||
listInsets.top += 8.0
|
||||
}
|
||||
|
||||
var displayTopDimNode = false
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TemporaryCachedPeerDataManager
|
||||
@ -7,6 +8,9 @@ import AccountContext
|
||||
import TelegramPresentationData
|
||||
import ChatHistoryEntry
|
||||
import ChatMessageItemCommon
|
||||
import TextFormat
|
||||
import Markdown
|
||||
import Display
|
||||
|
||||
func chatHistoryEntriesForView(
|
||||
location: ChatLocation,
|
||||
@ -15,6 +19,7 @@ func chatHistoryEntriesForView(
|
||||
includeEmptyEntry: Bool,
|
||||
includeChatInfoEntry: Bool,
|
||||
includeSearchEntry: Bool,
|
||||
includeEmbeddedSavedChatInfo: Bool,
|
||||
reverse: Bool,
|
||||
groupMessages: Bool,
|
||||
reverseGroupedMessages: Bool,
|
||||
@ -454,6 +459,56 @@ func chatHistoryEntriesForView(
|
||||
}
|
||||
}
|
||||
}
|
||||
if includeEmbeddedSavedChatInfo, let peerId = location.peerId {
|
||||
if !view.isLoading && view.laterId == nil {
|
||||
let string = presentationData.strings.Chat_SavedMessagesTabInfoText
|
||||
let formattedString = parseMarkdownIntoAttributedString(
|
||||
string,
|
||||
attributes: MarkdownAttributes(
|
||||
body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: .black),
|
||||
bold: MarkdownAttributeSet(font: Font.regular(15.0), textColor: .white),
|
||||
link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: .black),
|
||||
linkAttribute: { url in
|
||||
return ("URL", url)
|
||||
}
|
||||
)
|
||||
)
|
||||
var entities: [MessageTextEntity] = []
|
||||
formattedString.enumerateAttribute(.foregroundColor, in: NSRange(location: 0, length: formattedString.length), options: [], using: { value, range, _ in
|
||||
if let value = value as? UIColor, value == .white {
|
||||
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Bold))
|
||||
}
|
||||
})
|
||||
|
||||
let message = Message(
|
||||
stableId: UInt32.max - 1001,
|
||||
stableVersion: 0,
|
||||
id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: 123),
|
||||
globallyUniqueId: nil,
|
||||
groupingKey: nil,
|
||||
groupInfo: nil,
|
||||
threadId: nil,
|
||||
timestamp: Int32.max - 1,
|
||||
flags: [.Incoming],
|
||||
tags: [],
|
||||
globalTags: [],
|
||||
localTags: [],
|
||||
customTags: [],
|
||||
forwardInfo: nil,
|
||||
author: nil,
|
||||
text: "",
|
||||
attributes: [],
|
||||
media: [TelegramMediaAction(action: .customText(text: formattedString.string, entities: entities, additionalAttributes: nil))],
|
||||
peers: SimpleDictionary<PeerId, Peer>(),
|
||||
associatedMessages: SimpleDictionary<MessageId, Message>(),
|
||||
associatedMessageIds: [],
|
||||
associatedMedia: [:],
|
||||
associatedThreadInfo: nil,
|
||||
associatedStories: [:]
|
||||
)
|
||||
entries.append(.MessageEntry(message, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil)))
|
||||
}
|
||||
}
|
||||
|
||||
if reverse {
|
||||
return entries.reversed()
|
||||
|
@ -1697,6 +1697,11 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
|
||||
let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, subject: subject, currentlyPlayingMessageId: currentlyPlayingMessageIdAndType?.0, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, isPremium: isPremium, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, accountPeer: accountPeer, topicAuthorId: topicAuthorId, hasBots: chatHasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: !rotated)
|
||||
|
||||
var includeEmbeddedSavedChatInfo = false
|
||||
if case let .replyThread(message) = chatLocation, message.peerId == context.account.peerId, !rotated {
|
||||
includeEmbeddedSavedChatInfo = true
|
||||
}
|
||||
|
||||
let filteredEntries = chatHistoryEntriesForView(
|
||||
location: chatLocation,
|
||||
view: view,
|
||||
@ -1704,6 +1709,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
includeEmptyEntry: mode == .bubbles && tag == nil,
|
||||
includeChatInfoEntry: mode == .bubbles,
|
||||
includeSearchEntry: includeSearchEntry && tag != nil,
|
||||
includeEmbeddedSavedChatInfo: includeEmbeddedSavedChatInfo,
|
||||
reverse: reverse,
|
||||
groupMessages: mode == .bubbles,
|
||||
reverseGroupedMessages: reverseGroups,
|
||||
|
Loading…
x
Reference in New Issue
Block a user