mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
Version 11.9
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import SGStrings
|
||||
import SGSimpleSettings
|
||||
import PeerInfoUI
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
@@ -485,6 +488,16 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
isEmbeddedMode = true
|
||||
}
|
||||
// MARK: Swiftgram
|
||||
var canReveal = false
|
||||
if !chatPresentationInterfaceState.copyProtectionEnabled {
|
||||
outer: for message in messages {
|
||||
if message.canRevealContent(contentSettings: context.currentContentSettings.with { $0 }) {
|
||||
canReveal = true
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if case let .customChatContents(customChatContents) = chatPresentationInterfaceState.subject, case .hashTagSearch = customChatContents.kind {
|
||||
isEmbeddedMode = true
|
||||
@@ -633,7 +646,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
messageEntities = attribute.entities
|
||||
}
|
||||
if let attribute = attribute as? RestrictedContentMessageAttribute {
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) ?? ""
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }, chatId: message.author?.id.id._internalGetInt64Value()) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,6 +940,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
let isPremium = accountPeer?.isPremium ?? false
|
||||
|
||||
var actions: [ContextMenuItem] = []
|
||||
var sgActions: [ContextMenuItem] = []
|
||||
|
||||
var isPinnedMessages = false
|
||||
if case .pinnedMessages = chatPresentationInterfaceState.subject {
|
||||
@@ -1161,6 +1175,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})
|
||||
})
|
||||
})))
|
||||
if !SGSimpleSettings.shared.contextShowReply { sgActions.append(actions.removeLast()) }
|
||||
}
|
||||
|
||||
if data.messageActions.options.contains(.sendScheduledNow) {
|
||||
@@ -1268,7 +1283,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
messageEntities = attribute.entities
|
||||
}
|
||||
if let attribute = attribute as? RestrictedContentMessageAttribute {
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) ?? ""
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }, chatId: message.author?.id.id._internalGetInt64Value()) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1385,6 +1400,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})
|
||||
f(.default)
|
||||
})))
|
||||
if !SGSimpleSettings.shared.contextShowSaveMedia { sgActions.append(actions.removeLast()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1430,6 +1446,18 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})))
|
||||
}
|
||||
|
||||
let showJsonAction: ContextMenuItem = .action(ContextMenuActionItem(text: "JSON", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
showMessageJson(controllerInteraction: controllerInteraction, chatPresentationInterfaceState: chatPresentationInterfaceState, message: message, context: context)
|
||||
f(.default)
|
||||
}))
|
||||
if SGSimpleSettings.shared.contextShowJson {
|
||||
actions.append(showJsonAction)
|
||||
} else {
|
||||
sgActions.append(showJsonAction)
|
||||
}
|
||||
|
||||
var threadId: Int64?
|
||||
var threadMessageCount: Int = 0
|
||||
if case .peer = chatPresentationInterfaceState.chatLocation, let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .group = channel.info {
|
||||
@@ -1468,6 +1496,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
controllerInteraction.openMessageReplies(messages[0].id, true, true)
|
||||
})
|
||||
})))
|
||||
if !SGSimpleSettings.shared.contextShowMessageReplies { sgActions.append(actions.removeLast()) }
|
||||
}
|
||||
|
||||
let isMigrated: Bool
|
||||
@@ -1545,6 +1574,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
interfaceInteraction.pinMessage(messages[0].id, c)
|
||||
})))
|
||||
}
|
||||
if !SGSimpleSettings.shared.contextShowPin { sgActions.append(actions.removeLast()) }
|
||||
}
|
||||
|
||||
if let activePoll = activePoll, messages[0].forwardInfo == nil {
|
||||
@@ -1717,18 +1747,52 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuForward, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
interfaceInteraction.forwardMessages(selectAll || isImage ? messages : [message])
|
||||
interfaceInteraction.forwardMessages(selectAll || isImage ? messages : [message], nil)
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
if message.id.peerId != context.account.peerId {
|
||||
let action: ContextMenuItem = .action(ContextMenuActionItem(text: i18n("ContextMenu.SaveToCloud", chatPresentationInterfaceState.strings.baseLanguageCode), icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
interfaceInteraction.forwardMessages(selectAll || isImage ? messages : [message], "forwardMessagesToCloud")
|
||||
f(.dismissWithoutContent)
|
||||
}))
|
||||
if SGSimpleSettings.shared.contextShowSaveToCloud {
|
||||
actions.append(action)
|
||||
} else {
|
||||
sgActions.append(action)
|
||||
}
|
||||
}
|
||||
let action: ContextMenuItem = .action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.NotificationSettings_Stories_CompactHideName, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
interfaceInteraction.forwardMessages(selectAll || isImage ? messages : [message], "forwardMessagesWithNoNames")
|
||||
f(.dismissWithoutContent)
|
||||
}))
|
||||
if SGSimpleSettings.shared.contextShowHideForwardName {
|
||||
actions.append(action)
|
||||
} else {
|
||||
sgActions.append(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if data.messageActions.options.contains(.report) {
|
||||
if canReveal {
|
||||
actions.insert(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Username_ActivateAlertShow, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Premium/Stories/Views" /*"Chat/Context Menu/Eye"*/ ), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
interfaceInteraction.forwardMessages(selectAll || isImage ? messages : [message], "forwardMessagesToCloudWithNoNamesAndOpen")
|
||||
f(.dismissWithoutContent)
|
||||
})), at: 0)
|
||||
}
|
||||
|
||||
if data.messageActions.options.contains(.report) || context.account.testingEnvironment {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuReport, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Report"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { controller, f in
|
||||
interfaceInteraction.reportMessages(messages, controller)
|
||||
})))
|
||||
if !SGSimpleSettings.shared.contextShowReport { sgActions.append(actions.removeLast()) }
|
||||
} else if message.id.peerId.isReplies {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuBlock, textColor: .destructive, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.destructiveActionTextColor)
|
||||
@@ -1737,6 +1801,54 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})))
|
||||
}
|
||||
|
||||
if let peer = chatPresentationInterfaceState.renderedPeer?.peer ?? message.peers[message.id.peerId] {
|
||||
let hasRestrictPermission: Bool
|
||||
if let channel = peer as? TelegramChannel {
|
||||
hasRestrictPermission = channel.hasPermission(.banMembers)
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
switch group.role {
|
||||
case .creator:
|
||||
hasRestrictPermission = true
|
||||
case let .admin(adminRights, _):
|
||||
hasRestrictPermission = adminRights.rights.contains(.canBanUsers)
|
||||
case .member:
|
||||
hasRestrictPermission = false
|
||||
}
|
||||
} else {
|
||||
hasRestrictPermission = false
|
||||
}
|
||||
|
||||
if let user = message.author as? TelegramUser {
|
||||
if (user.id != context.account.peerId) && hasRestrictPermission {
|
||||
let banDisposables = DisposableDict<PeerId>()
|
||||
// TODO(swiftgram): Check is user an admin?
|
||||
let action: ContextMenuItem = .action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuBan, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
let participantSignal: Signal<ChannelParticipant?, NoError>
|
||||
if peer is TelegramChannel {
|
||||
participantSignal = context.engine.peers.fetchChannelParticipant(peerId: peer.id, participantId: user.id)
|
||||
} else if peer is TelegramGroup {
|
||||
participantSignal = .single(.member(id: user.id, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil, subscriptionUntilDate: nil))
|
||||
} else {
|
||||
participantSignal = .single(nil)
|
||||
}
|
||||
banDisposables.set((participantSignal
|
||||
|> deliverOnMainQueue).start(next: { participant in
|
||||
controllerInteraction.presentController(channelBannedMemberController(context: context, peerId: peer.id, memberId: message.author!.id, initialParticipant: participant, updated: { _ in }, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}), forKey: user.id)
|
||||
f(.dismissWithoutContent)
|
||||
}))
|
||||
if SGSimpleSettings.shared.contextShowRestrict {
|
||||
actions.append(action)
|
||||
} else {
|
||||
sgActions.append(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var clearCacheAsDelete = false
|
||||
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info, !isMigrated {
|
||||
var views: Int = 0
|
||||
@@ -1855,9 +1967,86 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
var sgActionsIndex: Int? = nil
|
||||
if !isPinnedMessages, !isReplyThreadHead, data.canSelect {
|
||||
sgActionsIndex = actions.count
|
||||
var didAddSeparator = false
|
||||
// MARK: Swiftgram
|
||||
if let authorId = message.author?.id {
|
||||
let action: ContextMenuItem = .action(ContextMenuActionItem(text: i18n("ContextMenu.SelectFromUser", chatPresentationInterfaceState.strings.baseLanguageCode), icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/SelectAll"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let overlayController = OverlayStatusController(theme: chatPresentationInterfaceState.theme, type: .loading(cancelled: nil))
|
||||
controllerInteraction.presentGlobalOverlayController(overlayController, nil)
|
||||
return ActionDisposable { [weak overlayController] in
|
||||
Queue.mainQueue().async() {
|
||||
overlayController?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.2, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
let _ = (context.account.postbox.transaction { transaction -> [MessageId] in
|
||||
let limit = 500
|
||||
var result: [MessageId] = []
|
||||
|
||||
let needThreadIdFilter: Bool
|
||||
let searchThreadId: Int64?
|
||||
switch chatPresentationInterfaceState.chatLocation {
|
||||
case let .replyThread(replyThreadMessage):
|
||||
needThreadIdFilter = true
|
||||
searchThreadId = replyThreadMessage.threadId
|
||||
default:
|
||||
needThreadIdFilter = false
|
||||
searchThreadId = nil
|
||||
}
|
||||
transaction.withAllMessages(peerId: message.id.peerId, reversed: true, { searchMessage in
|
||||
if result.count >= limit {
|
||||
return false
|
||||
}
|
||||
if searchMessage.author?.id == authorId {
|
||||
// Only messages from current opened thread
|
||||
// print("searchMessage.threadId:\(String(describing: searchMessage.threadId)) threadId:\(String(describing: threadId)) message.threadId:\(String(describing:message.threadId)) needThreadIdFilter:\(needThreadIdFilter) searchThreadId:\(String(describing:searchThreadId))")
|
||||
if needThreadIdFilter && searchMessage.threadId != searchThreadId {
|
||||
return true
|
||||
}
|
||||
// No service messages
|
||||
if searchMessage.media.contains(where: { $0 is TelegramMediaAction }) {
|
||||
return true
|
||||
}
|
||||
result.append(searchMessage.id)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|> deliverOnMainQueue)
|
||||
.start(next: { ids in
|
||||
interfaceInteraction.beginMessageSelection(ids, { transition in
|
||||
f(.custom(transition))
|
||||
})
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
}, completed: {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
})
|
||||
}))
|
||||
if SGSimpleSettings.shared.contextShowSelectFromUser {
|
||||
if !actions.isEmpty && !didAddSeparator {
|
||||
didAddSeparator = true
|
||||
actions.append(.separator)
|
||||
}
|
||||
actions.append(action)
|
||||
} else {
|
||||
sgActions.append(action)
|
||||
}
|
||||
}
|
||||
|
||||
if !selectAll || messages.count == 1 {
|
||||
if !actions.isEmpty && !didAddSeparator {
|
||||
didAddSeparator = true
|
||||
@@ -1889,6 +2078,40 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Swiftgram
|
||||
if !sgActions.isEmpty {
|
||||
if !actions.isEmpty {
|
||||
if let sgActionsIndex = sgActionsIndex {
|
||||
actions.insert(.separator, at: sgActionsIndex)
|
||||
} else {
|
||||
actions.append(.separator)
|
||||
}
|
||||
}
|
||||
|
||||
var popSGItems: (() -> Void)? = nil
|
||||
sgActions.insert(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Common_Back, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor)
|
||||
}, iconPosition: .left, action: { _, _ in
|
||||
popSGItems?()
|
||||
})), at: 0)
|
||||
sgActions.insert(.separator, at: 1)
|
||||
|
||||
let swiftgramSubMenu: ContextMenuItem = .action(ContextMenuActionItem(text: "Swiftgram", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "SwiftgramContextMenu"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { c, f in
|
||||
popSGItems = { [weak c] in
|
||||
c?.popItems()
|
||||
}
|
||||
c?.pushItems(items: .single(ContextController.Items(content: .list(sgActions))))
|
||||
}))
|
||||
|
||||
if let sgActionsIndex = sgActionsIndex {
|
||||
actions.insert(swiftgramSubMenu, at: sgActionsIndex + 1)
|
||||
} else {
|
||||
actions.append(swiftgramSubMenu)
|
||||
}
|
||||
}
|
||||
|
||||
let canViewStats: Bool
|
||||
if let messageReadStatsAreHidden = infoSummaryData.messageReadStatsAreHidden, !messageReadStatsAreHidden {
|
||||
canViewStats = canViewReadStats(message: message, participantCount: infoSummaryData.participantCount, isMessageRead: isMessageRead, isPremium: isPremium, appConfig: appConfig)
|
||||
@@ -2055,7 +2278,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
messageEntities = attribute.entities
|
||||
}
|
||||
if let attribute = attribute as? RestrictedContentMessageAttribute {
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) ?? ""
|
||||
restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }, chatId: message.author?.id.id._internalGetInt64Value()) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user