mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
115c896a96
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
||||
include Utils.makefile
|
||||
|
||||
|
||||
APP_VERSION="6.1"
|
||||
APP_VERSION="6.1.1"
|
||||
CORE_COUNT=$(shell sysctl -n hw.logicalcpu)
|
||||
CORE_COUNT_MINUS_ONE=$(shell expr ${CORE_COUNT} \- 1)
|
||||
|
||||
|
||||
@ -1521,7 +1521,6 @@
|
||||
|
||||
"Channel.UpdatePhotoItem" = "Set Channel Photo";
|
||||
|
||||
"Channel.AboutItem" = "about";
|
||||
"Channel.LinkItem" = "share link";
|
||||
"Channel.Edit.AboutItem" = "Description";
|
||||
"Channel.Edit.LinkItem" = "Link";
|
||||
@ -5495,3 +5494,6 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Message.GenericForwardedPsa" = "Public Service Announcement\nFrom: %@";
|
||||
"Message.ForwardedPsa.covid" = "Covid-19 Notification\nFrom: %@";
|
||||
|
||||
"Channel.AboutItem" = "about";
|
||||
"PeerInfo.GroupAboutItem" = "about";
|
||||
|
||||
@ -1216,7 +1216,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if item.enableContextActions {
|
||||
if case .psa = promoInfo {
|
||||
peerRevealOptions = [
|
||||
ItemListRevealOption(key: RevealOptionKey.hidePsa.rawValue, title: item.presentationData.strings.ChatList_HideAction, icon: hideIcon, color: item.presentationData.theme.list.itemDisclosureActions.inactive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral1.foregroundColor)
|
||||
ItemListRevealOption(key: RevealOptionKey.hidePsa.rawValue, title: item.presentationData.strings.ChatList_HideAction, icon: deleteIcon, color: item.presentationData.theme.list.itemDisclosureActions.inactive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral1.foregroundColor)
|
||||
]
|
||||
peerLeftRevealOptions = []
|
||||
} else if promoInfo == nil {
|
||||
|
||||
@ -156,7 +156,11 @@ public struct MessageIndex: Comparable, Hashable {
|
||||
return lhs.id.namespace < rhs.id.namespace
|
||||
}
|
||||
|
||||
return lhs.id.id < rhs.id.id
|
||||
if lhs.id.id != rhs.id.id {
|
||||
return lhs.id.id < rhs.id.id
|
||||
}
|
||||
|
||||
return lhs.id.peerId.toInt64() < rhs.id.peerId.toInt64()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1879,13 +1879,16 @@ final class MessageHistoryTable: Table {
|
||||
if let forwardInfo = message.forwardInfo {
|
||||
var forwardInfoFlags: Int8 = 1
|
||||
if forwardInfo.sourceId != nil {
|
||||
forwardInfoFlags |= 2
|
||||
forwardInfoFlags |= 1 << 1
|
||||
}
|
||||
if forwardInfo.sourceMessageId != nil {
|
||||
forwardInfoFlags |= 4
|
||||
forwardInfoFlags |= 1 << 2
|
||||
}
|
||||
if forwardInfo.authorSignature != nil {
|
||||
forwardInfoFlags |= 8
|
||||
forwardInfoFlags |= 1 << 3
|
||||
}
|
||||
if forwardInfo.psaType != nil {
|
||||
forwardInfoFlags |= 1 << 4
|
||||
}
|
||||
sharedBuffer.write(&forwardInfoFlags, offset: 0, length: 1)
|
||||
var forwardAuthorId: Int64 = forwardInfo.authorId?.toInt64() ?? 0
|
||||
@ -1917,6 +1920,17 @@ final class MessageHistoryTable: Table {
|
||||
sharedBuffer.write(&length, offset: 0, length: 4)
|
||||
}
|
||||
}
|
||||
|
||||
if let psaType = forwardInfo.psaType {
|
||||
if let data = psaType.data(using: .utf8, allowLossyConversion: true) {
|
||||
var length: Int32 = Int32(data.count)
|
||||
sharedBuffer.write(&length, offset: 0, length: 4)
|
||||
sharedBuffer.write(data)
|
||||
} else {
|
||||
var length: Int32 = 0
|
||||
sharedBuffer.write(&length, offset: 0, length: 4)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var forwardInfoFlags: Int8 = 0
|
||||
sharedBuffer.write(&forwardInfoFlags, offset: 0, length: 1)
|
||||
|
||||
@ -296,6 +296,7 @@ public final class AccountStateManager {
|
||||
var collectedPollCompletionSubscribers: [(Int32, ([MessageId]) -> Void)] = []
|
||||
var collectedReplayAsynchronouslyBuiltFinalState: [(AccountFinalState, () -> Void)] = []
|
||||
var processEvents: [(Int32, AccountFinalStateEvents)] = []
|
||||
var customOperations: [(Int32, Signal<Void, NoError>)] = []
|
||||
|
||||
var replacedOperations: [AccountStateManagerOperation] = []
|
||||
|
||||
@ -313,6 +314,8 @@ public final class AccountStateManager {
|
||||
collectedReplayAsynchronouslyBuiltFinalState.append((finalState, completion))
|
||||
case let .processEvents(operationId, events):
|
||||
processEvents.append((operationId, events))
|
||||
case let .custom(operationId, customSignal):
|
||||
customOperations.append((operationId, customSignal))
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -335,6 +338,10 @@ public final class AccountStateManager {
|
||||
replacedOperations.append(AccountStateManagerOperation(content: .processEvents(operationId, events)))
|
||||
}
|
||||
|
||||
for (operationId, customSignal) in customOperations {
|
||||
replacedOperations.append(AccountStateManagerOperation(content: .custom(operationId, customSignal)))
|
||||
}
|
||||
|
||||
self.operations.removeAll()
|
||||
self.operations.append(contentsOf: replacedOperations)
|
||||
}
|
||||
|
||||
@ -60,40 +60,6 @@ private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId
|
||||
}
|
||||
}
|
||||
|
||||
func fetchPeerCloudReadState(network: Network, postbox: Postbox, peerId: PeerId, inputPeer: Api.InputPeer) -> Signal<PeerReadState?, NoError> {
|
||||
return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(peer: inputPeer)]))
|
||||
|> map { result -> PeerReadState? in
|
||||
switch result {
|
||||
case let .peerDialogs(dialogs, _, _, _, _):
|
||||
if let dialog = dialogs.filter({ $0.peerId == peerId }).first {
|
||||
let apiTopMessage: Int32
|
||||
let apiReadInboxMaxId: Int32
|
||||
let apiReadOutboxMaxId: Int32
|
||||
let apiUnreadCount: Int32
|
||||
let apiMarkedUnread: Bool
|
||||
switch dialog {
|
||||
case let .dialog(flags, _, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _, _, _, _):
|
||||
apiTopMessage = topMessage
|
||||
apiReadInboxMaxId = readInboxMaxId
|
||||
apiReadOutboxMaxId = readOutboxMaxId
|
||||
apiUnreadCount = unreadCount
|
||||
apiMarkedUnread = (flags & (1 << 3)) != 0
|
||||
case .dialogFolder:
|
||||
assertionFailure()
|
||||
return nil
|
||||
}
|
||||
|
||||
return .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount, markedUnread: apiMarkedUnread)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|> `catch` { _ -> Signal<PeerReadState?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func dialogReadState(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> {
|
||||
return dialogTopMessage(network: network, postbox: postbox, peerId: peerId)
|
||||
|> mapToSignal { topMessage -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> in
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -6482,7 +6482,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let tooltipScreen = TooltipScreen(text: psaText, textEntities: psaEntities, icon: .info, location: .top, shouldDismissOnTouch: { point in
|
||||
let tooltipScreen = TooltipScreen(text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in
|
||||
return .ignore
|
||||
}, openActiveTextItem: { [weak self] item, action in
|
||||
guard let strongSelf = self else {
|
||||
@ -6492,7 +6492,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case let .url(url, concealed):
|
||||
switch action {
|
||||
case .tap:
|
||||
strongSelf.openUrl(url, concealed: false)
|
||||
strongSelf.openUrl(url, concealed: concealed)
|
||||
case .longTap:
|
||||
strongSelf.controllerInteraction?.longTap(.url(url), nil)
|
||||
}
|
||||
@ -6560,18 +6560,34 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
let psaEntities: [MessageTextEntity] = generateTextEntities(psaText, enabledTypes: .url)
|
||||
|
||||
let messageId = item.message.id
|
||||
|
||||
var found = false
|
||||
self.forEachController({ controller in
|
||||
if let controller = controller as? TooltipScreen {
|
||||
if controller.text == psaText {
|
||||
found = true
|
||||
controller.dismiss()
|
||||
controller.resetDismissTimeout()
|
||||
|
||||
controller.willBecomeDismissed = { [weak self] tooltipScreen in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.controllerInteraction?.currentPsaMessageWithTooltip == messageId {
|
||||
strongSelf.controllerInteraction?.currentPsaMessageWithTooltip = nil
|
||||
strongSelf.updatePollTooltipMessageState(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if found {
|
||||
self.controllerInteraction?.currentPsaMessageWithTooltip = messageId
|
||||
self.updatePollTooltipMessageState(animated: !isAutomatic)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -6585,7 +6601,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case let .url(url, concealed):
|
||||
switch action {
|
||||
case .tap:
|
||||
strongSelf.openUrl(url, concealed: false)
|
||||
strongSelf.openUrl(url, concealed: concealed)
|
||||
case .longTap:
|
||||
strongSelf.controllerInteraction?.longTap(.url(url), nil)
|
||||
}
|
||||
@ -6620,7 +6636,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
})
|
||||
|
||||
let messageId = item.message.id
|
||||
self.controllerInteraction?.currentPsaMessageWithTooltip = messageId
|
||||
self.updatePollTooltipMessageState(animated: !isAutomatic)
|
||||
|
||||
|
||||
@ -784,7 +784,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
|
||||
var effectiveAuthor: Peer?
|
||||
var ignoreForward = false
|
||||
let displayAuthorInfo: Bool
|
||||
var displayAuthorInfo: Bool
|
||||
|
||||
let avatarInset: CGFloat
|
||||
var hasAvatar = false
|
||||
@ -809,7 +809,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
displayAuthorInfo = !mergedTop.merged && incoming && effectiveAuthor != nil
|
||||
} else {
|
||||
effectiveAuthor = firstMessage.author
|
||||
displayAuthorInfo = !mergedTop.merged && incoming && peerId.isGroupOrChannel && effectiveAuthor != nil
|
||||
displayAuthorInfo = !mergedTop.merged && incoming && peerId.isGroupOrChannel && effectiveAuthor != nil
|
||||
if let forwardInfo = firstMessage.forwardInfo, forwardInfo.psaType != nil {
|
||||
displayAuthorInfo = false
|
||||
}
|
||||
}
|
||||
|
||||
if peerId != item.context.account.peerId {
|
||||
@ -827,10 +830,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
} else if incoming {
|
||||
hasAvatar = true
|
||||
}
|
||||
/*case .group:
|
||||
allowFullWidth = true
|
||||
hasAvatar = true
|
||||
displayAuthorInfo = true*/
|
||||
}
|
||||
|
||||
if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.source == nil, forwardInfo.author?.id.namespace == Namespaces.Peer.CloudUser {
|
||||
@ -987,6 +986,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
}
|
||||
}
|
||||
|
||||
if let forwardInfo = firstMessage.forwardInfo, forwardInfo.psaType != nil {
|
||||
inlineBotNameString = nil
|
||||
}
|
||||
|
||||
var contentPropertiesAndLayouts: [(CGSize?, ChatMessageBubbleContentProperties, ChatMessageBubblePreparePosition, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void)))] = []
|
||||
|
||||
let topNodeMergeStatus: ChatMessageBubbleMergeStatus = mergedTop.merged ? (incoming ? .Left : .Right) : .None(incoming ? .Incoming : .Outgoing)
|
||||
@ -1877,19 +1880,19 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
||||
|
||||
if let forwardInfoNode = forwardInfoSizeApply.1(bubbleContentWidth) {
|
||||
strongSelf.forwardInfoNode = forwardInfoNode
|
||||
forwardInfoNode.openPsa = { [weak strongSelf] type, sourceNode in
|
||||
guard let strongSelf = strongSelf, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.displayPsa(type, sourceNode)
|
||||
}
|
||||
var animateFrame = true
|
||||
if forwardInfoNode.supernode == nil {
|
||||
strongSelf.contextSourceNode.contentNode.addSubnode(forwardInfoNode)
|
||||
animateFrame = false
|
||||
forwardInfoNode.openPsa = { [weak strongSelf] type, sourceNode in
|
||||
guard let strongSelf = strongSelf, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.displayPsa(type, sourceNode)
|
||||
}
|
||||
}
|
||||
let previousForwardInfoNodeFrame = forwardInfoNode.frame
|
||||
forwardInfoNode.frame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + forwardInfoOriginY), size: forwardInfoSizeApply.0)
|
||||
forwardInfoNode.frame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + forwardInfoOriginY), size: CGSize(width: bubbleContentWidth, height: forwardInfoSizeApply.0.height))
|
||||
if case let .System(duration) = animation {
|
||||
if animateFrame {
|
||||
forwardInfoNode.layer.animateFrame(from: previousForwardInfoNodeFrame, to: forwardInfoNode.frame, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
@ -154,7 +154,32 @@ class ChatMessageForwardInfoNode: ASDisplayNode {
|
||||
case .standalone:
|
||||
let serviceColor = serviceMessageColorComponents(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||
titleColor = serviceColor.primaryText
|
||||
completeSourceString = strings.Message_ForwardedMessageShort(peerString)
|
||||
|
||||
if let psaType = psaType {
|
||||
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 {
|
||||
completeSourceString = strings.Message_ForwardedMessageShort(peerString)
|
||||
}
|
||||
}
|
||||
|
||||
var currentCredibilityIconImage: UIImage?
|
||||
|
||||
@ -122,6 +122,10 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
|
||||
if let strongSelf = self {
|
||||
if let shareButtonNode = strongSelf.shareButtonNode, shareButtonNode.frame.contains(point) {
|
||||
return .fail
|
||||
} else if let forwardInfoNode = strongSelf.forwardInfoNode, forwardInfoNode.frame.contains(point) {
|
||||
if forwardInfoNode.hasAction(at: strongSelf.view.convert(point, to: forwardInfoNode.view)) {
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
}
|
||||
return .waitForSingleTap
|
||||
@ -572,6 +576,12 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
|
||||
if strongSelf.forwardInfoNode == nil {
|
||||
strongSelf.forwardInfoNode = forwardInfoNode
|
||||
strongSelf.addSubnode(forwardInfoNode)
|
||||
forwardInfoNode.openPsa = { [weak strongSelf] type, sourceNode in
|
||||
guard let strongSelf = strongSelf, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.displayPsa(type, sourceNode)
|
||||
}
|
||||
}
|
||||
let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0) : (params.width - params.rightInset - forwardInfoSize.width - layoutConstants.bubble.edgeInset - 12.0)), y: 8.0), size: forwardInfoSize)
|
||||
forwardInfoNode.frame = forwardInfoFrame
|
||||
@ -696,26 +706,28 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
|
||||
|
||||
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) {
|
||||
if let item = self.item, let forwardInfo = item.message.forwardInfo {
|
||||
if let sourceMessageId = forwardInfo.sourceMessageId {
|
||||
if let channel = forwardInfo.author as? TelegramChannel, channel.username == nil {
|
||||
if case .member = channel.participationStatus {
|
||||
} else {
|
||||
return .optionalAction({
|
||||
let performAction: () -> Void = {
|
||||
if let sourceMessageId = forwardInfo.sourceMessageId {
|
||||
if let channel = forwardInfo.author as? TelegramChannel, channel.username == nil {
|
||||
if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
|
||||
} else if case .member = channel.participationStatus {
|
||||
} else {
|
||||
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, forwardInfoNode, nil)
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return .optionalAction({
|
||||
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
|
||||
})
|
||||
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
|
||||
return .optionalAction({
|
||||
item.controllerInteraction.openPeer(id, .chat(textInputState: nil, subject: nil), nil)
|
||||
})
|
||||
} else if let _ = forwardInfo.authorSignature {
|
||||
return .optionalAction({
|
||||
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
|
||||
item.controllerInteraction.openPeer(id, .info, nil)
|
||||
} else if let _ = forwardInfo.authorSignature {
|
||||
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode, nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if forwardInfoNode.hasAction(at: self.view.convert(location, to: forwardInfoNode.view)) {
|
||||
return .action({})
|
||||
} else {
|
||||
return .optionalAction(performAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,11 +609,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
||||
}
|
||||
if let cachedData = data.cachedData as? CachedUserData {
|
||||
if user.isScam {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Channel_AboutItem, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledBioEntities : []), action: nil, requestLayout: {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledBioEntities : []), action: nil, requestLayout: {
|
||||
interaction.requestLayout()
|
||||
}))
|
||||
} else if let about = cachedData.about, !about.isEmpty {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Channel_AboutItem, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: []), action: nil, longTapAction: bioContextAction, linkItemAction: bioLinkAction, requestLayout: {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: []), action: nil, longTapAction: bioContextAction, linkItemAction: bioLinkAction, requestLayout: {
|
||||
interaction.requestLayout()
|
||||
}))
|
||||
}
|
||||
@ -733,11 +733,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
||||
} else if let group = data.peer as? TelegramGroup {
|
||||
if let cachedData = data.cachedData as? CachedGroupData {
|
||||
if group.isScam {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Channel_AboutItem, text: presentationData.strings.GroupInfo_ScamGroupWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledBioEntities), action: nil, requestLayout: {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.PeerInfo_GroupAboutItem, text: presentationData.strings.GroupInfo_ScamGroupWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledBioEntities), action: nil, requestLayout: {
|
||||
interaction.requestLayout()
|
||||
}))
|
||||
} else if let about = cachedData.about, !about.isEmpty {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Channel_AboutItem, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledBioEntities), action: nil, longTapAction: bioContextAction, linkItemAction: bioLinkAction, requestLayout: {
|
||||
items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.PeerInfo_GroupAboutItem, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledBioEntities), action: nil, longTapAction: bioContextAction, linkItemAction: bioLinkAction, requestLayout: {
|
||||
interaction.requestLayout()
|
||||
}))
|
||||
}
|
||||
|
||||
@ -391,6 +391,8 @@ public final class TooltipScreen: ViewController {
|
||||
public var willBecomeDismissed: ((TooltipScreen) -> Void)?
|
||||
public var becameDismissed: ((TooltipScreen) -> Void)?
|
||||
|
||||
private var dismissTimer: Foundation.Timer?
|
||||
|
||||
public init(text: String, textEntities: [MessageTextEntity] = [], icon: TooltipScreen.Icon?, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: @escaping (TooltipActiveTextItem, TooltipActiveTextAction) -> Void = { _, _ in }) {
|
||||
self.text = text
|
||||
self.textEntities = textEntities
|
||||
@ -409,22 +411,47 @@ public final class TooltipScreen: ViewController {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.dismissTimer?.invalidate()
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.controllerNode.animateIn()
|
||||
self.resetDismissTimeout(duration: self.displayDuration)
|
||||
}
|
||||
|
||||
public func resetDismissTimeout(duration: TooltipScreen.DisplayDuration? = nil) {
|
||||
self.dismissTimer?.invalidate()
|
||||
|
||||
let timeout: Double
|
||||
switch self.displayDuration {
|
||||
switch duration ?? self.displayDuration {
|
||||
case .default:
|
||||
timeout = 5.0
|
||||
case let .custom(value):
|
||||
timeout = value
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + timeout, execute: { [weak self] in
|
||||
self?.dismiss()
|
||||
})
|
||||
final class TimerTarget: NSObject {
|
||||
private let f: () -> Void
|
||||
|
||||
init(_ f: @escaping () -> Void) {
|
||||
self.f = f
|
||||
}
|
||||
|
||||
@objc func timerEvent() {
|
||||
self.f()
|
||||
}
|
||||
}
|
||||
let dismissTimer = Foundation.Timer(timeInterval: timeout, target: TimerTarget { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.dismiss()
|
||||
}, selector: #selector(TimerTarget.timerEvent), userInfo: nil, repeats: false)
|
||||
self.dismissTimer = dismissTimer
|
||||
RunLoop.main.add(dismissTimer, forMode: .common)
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
|
||||
Binary file not shown.
@ -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_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[0 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
}
|
||||
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[1 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user