mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-06 22:33:10 +00:00
Cherry-pick various fixes
This commit is contained in:
parent
9b233d6051
commit
f125591ca8
@ -8,7 +8,7 @@ import VideoToolbox
|
|||||||
|
|
||||||
private let queue = Queue()
|
private let queue = Queue()
|
||||||
|
|
||||||
func cutoutStickerImage(from image: UIImage) -> Signal<UIImage?, NoError> {
|
public func cutoutStickerImage(from image: UIImage) -> Signal<UIImage?, NoError> {
|
||||||
if #available(iOS 17.0, *) {
|
if #available(iOS 17.0, *) {
|
||||||
guard let cgImage = image.cgImage else {
|
guard let cgImage = image.cgImage else {
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
|
|||||||
@ -21,6 +21,8 @@ public enum MessageContentKindKey {
|
|||||||
case liveLocation
|
case liveLocation
|
||||||
case expiredImage
|
case expiredImage
|
||||||
case expiredVideo
|
case expiredVideo
|
||||||
|
case expiredVoiceMessage
|
||||||
|
case expiredVideoMessage
|
||||||
case poll
|
case poll
|
||||||
case restricted
|
case restricted
|
||||||
case dice
|
case dice
|
||||||
@ -44,6 +46,8 @@ public enum MessageContentKind: Equatable {
|
|||||||
case liveLocation
|
case liveLocation
|
||||||
case expiredImage
|
case expiredImage
|
||||||
case expiredVideo
|
case expiredVideo
|
||||||
|
case expiredVoiceMessage
|
||||||
|
case expiredVideoMessage
|
||||||
case poll(String)
|
case poll(String)
|
||||||
case restricted(String)
|
case restricted(String)
|
||||||
case dice(String)
|
case dice(String)
|
||||||
@ -137,6 +141,18 @@ public enum MessageContentKind: Equatable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case .expiredVoiceMessage:
|
||||||
|
if case .expiredVoiceMessage = other {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case .expiredVideoMessage:
|
||||||
|
if case .expiredVideoMessage = other {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
case .poll:
|
case .poll:
|
||||||
if case .poll = other {
|
if case .poll = other {
|
||||||
return true
|
return true
|
||||||
@ -206,6 +222,10 @@ public enum MessageContentKind: Equatable {
|
|||||||
return .expiredImage
|
return .expiredImage
|
||||||
case .expiredVideo:
|
case .expiredVideo:
|
||||||
return .expiredVideo
|
return .expiredVideo
|
||||||
|
case .expiredVoiceMessage:
|
||||||
|
return .expiredVoiceMessage
|
||||||
|
case .expiredVideoMessage:
|
||||||
|
return .expiredVideoMessage
|
||||||
case .poll:
|
case .poll:
|
||||||
return .poll
|
return .poll
|
||||||
case .restricted:
|
case .restricted:
|
||||||
@ -405,6 +425,10 @@ public func stringForMediaKind(_ kind: MessageContentKind, strings: Presentation
|
|||||||
return (NSAttributedString(string: strings.Message_ImageExpired), true)
|
return (NSAttributedString(string: strings.Message_ImageExpired), true)
|
||||||
case .expiredVideo:
|
case .expiredVideo:
|
||||||
return (NSAttributedString(string: strings.Message_VideoExpired), true)
|
return (NSAttributedString(string: strings.Message_VideoExpired), true)
|
||||||
|
case .expiredVoiceMessage:
|
||||||
|
return (NSAttributedString(string: strings.Message_VoiceMessageExpired), true)
|
||||||
|
case .expiredVideoMessage:
|
||||||
|
return (NSAttributedString(string: strings.Message_VideoMessageExpired), true)
|
||||||
case let .poll(text):
|
case let .poll(text):
|
||||||
return (NSAttributedString(string: "📊 \(text)"), false)
|
return (NSAttributedString(string: "📊 \(text)"), false)
|
||||||
case let .restricted(text):
|
case let .restricted(text):
|
||||||
|
|||||||
@ -625,7 +625,7 @@ public final class MediaEditor {
|
|||||||
textureSource = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
textureSource = self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
||||||
|> mapToSignal { message in
|
|> mapToSignal { message in
|
||||||
var player: AVPlayer?
|
var player: AVPlayer?
|
||||||
if let message {
|
if let message, !"".isEmpty {
|
||||||
if let maybeFile = message.media.first(where: { $0 is TelegramMediaFile }) as? TelegramMediaFile, maybeFile.isVideo, let path = self.context.account.postbox.mediaBox.completedResourcePath(maybeFile.resource, pathExtension: "mp4") {
|
if let maybeFile = message.media.first(where: { $0 is TelegramMediaFile }) as? TelegramMediaFile, maybeFile.isVideo, let path = self.context.account.postbox.mediaBox.completedResourcePath(maybeFile.resource, pathExtension: "mp4") {
|
||||||
let asset = AVURLAsset(url: URL(fileURLWithPath: path))
|
let asset = AVURLAsset(url: URL(fileURLWithPath: path))
|
||||||
player = makePlayer(asset: asset)
|
player = makePlayer(asset: asset)
|
||||||
|
|||||||
@ -2473,7 +2473,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
messageEntity.secondaryRenderImage = result.nightImage
|
messageEntity.secondaryRenderImage = result.nightImage
|
||||||
messageEntity.overlayRenderImage = result.overlayImage
|
messageEntity.overlayRenderImage = result.overlayImage
|
||||||
messageEntity.referenceDrawingSize = storyDimensions
|
messageEntity.referenceDrawingSize = storyDimensions
|
||||||
messageEntity.position = CGPoint(x: storyDimensions.width / 2.0, y: storyDimensions.height / 2.0)
|
messageEntity.position = CGPoint(x: storyDimensions.width / 2.0 - 54.0, y: storyDimensions.height / 2.0)
|
||||||
|
|
||||||
let fraction = max(result.size.width, result.size.height) / 353.0
|
let fraction = max(result.size.width, result.size.height) / 353.0
|
||||||
messageEntity.scale = min(6.0, 3.3 * fraction)
|
messageEntity.scale = min(6.0, 3.3 * fraction)
|
||||||
@ -3375,6 +3375,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
let entity = DrawingStickerEntity(content: .image(updatedImage, .rectangle))
|
let entity = DrawingStickerEntity(content: .image(updatedImage, .rectangle))
|
||||||
entity.canCutOut = false
|
entity.canCutOut = false
|
||||||
|
|
||||||
|
let _ = (cutoutStickerImage(from: image)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak entity] result in
|
||||||
|
if result != nil, let entity {
|
||||||
|
entity.canCutOut = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
self?.interaction?.insertEntity(entity, scale: 2.5)
|
self?.interaction?.insertEntity(entity, scale: 2.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2589,7 +2589,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
|
|
||||||
if message.isCopyProtected() {
|
if message.isCopyProtected() {
|
||||||
|
|
||||||
} else if message.id.peerId.namespace != Namespaces.Peer.SecretChat {
|
} else if message.id.peerId.namespace != Namespaces.Peer.SecretChat && message.minAutoremoveOrClearTimeout == nil {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuForward, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuForward, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
|
||||||
c.dismiss(completion: {
|
c.dismiss(completion: {
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
|||||||
@ -992,7 +992,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let selectedMediaArea {
|
if let selectedMediaArea {
|
||||||
self.sendMessageContext.activateMediaArea(view: self, mediaArea: selectedMediaArea)
|
self.sendMessageContext.activateMediaArea(view: self, mediaArea: selectedMediaArea, position: point)
|
||||||
} else {
|
} else {
|
||||||
var direction: NavigationDirection?
|
var direction: NavigationDirection?
|
||||||
if point.x < itemLayout.containerSize.width * 0.25 {
|
if point.x < itemLayout.containerSize.width * 0.25 {
|
||||||
|
|||||||
@ -3279,7 +3279,7 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var selectedMediaArea: MediaArea?
|
private var selectedMediaArea: MediaArea?
|
||||||
func activateMediaArea(view: StoryItemSetContainerComponent.View, mediaArea: MediaArea, immediate: Bool = false) {
|
func activateMediaArea(view: StoryItemSetContainerComponent.View, mediaArea: MediaArea, position: CGPoint? = nil, immediate: Bool = false) {
|
||||||
guard let component = view.component, let controller = component.controller() else {
|
guard let component = view.component, let controller = component.controller() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -3289,6 +3289,8 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
|
|
||||||
let context = component.context
|
let context = component.context
|
||||||
|
|
||||||
|
var useGesturePosition = false
|
||||||
|
|
||||||
var actions: [ContextMenuAction] = []
|
var actions: [ContextMenuAction] = []
|
||||||
switch mediaArea {
|
switch mediaArea {
|
||||||
case let .venue(_, venue):
|
case let .venue(_, venue):
|
||||||
@ -3325,6 +3327,7 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
action()
|
action()
|
||||||
}))
|
}))
|
||||||
case let .channelMessage(_, messageId):
|
case let .channelMessage(_, messageId):
|
||||||
|
useGesturePosition = true
|
||||||
let action = { [weak self, weak view, weak controller] in
|
let action = { [weak self, weak view, weak controller] in
|
||||||
let _ = ((context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .cloud(skipLocal: true))
|
let _ = ((context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .cloud(skipLocal: true))
|
||||||
|> mapToSignal { result -> Signal<Message?, GetMessagesError> in
|
|> mapToSignal { result -> Signal<Message?, GetMessagesError> in
|
||||||
@ -3384,6 +3387,10 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
var frame = CGRect(x: mediaArea.coordinates.x / 100.0 * referenceSize.width - size.width / 2.0, y: mediaArea.coordinates.y / 100.0 * referenceSize.height - size.height / 2.0, width: size.width, height: size.height)
|
var frame = CGRect(x: mediaArea.coordinates.x / 100.0 * referenceSize.width - size.width / 2.0, y: mediaArea.coordinates.y / 100.0 * referenceSize.height - size.height / 2.0, width: size.width, height: size.height)
|
||||||
frame = view.controlsContainerView.convert(frame, to: nil)
|
frame = view.controlsContainerView.convert(frame, to: nil)
|
||||||
|
|
||||||
|
if useGesturePosition, let position {
|
||||||
|
frame = CGRect(origin: position.offsetBy(dx: 0.0, dy: 44.0), size: .zero)
|
||||||
|
}
|
||||||
|
|
||||||
let node = controller.displayNode
|
let node = controller.displayNode
|
||||||
let menuController = makeContextMenuController(actions: actions, blurred: true)
|
let menuController = makeContextMenuController(actions: actions, blurred: true)
|
||||||
menuController.centerHorizontally = true
|
menuController.centerHorizontally = true
|
||||||
|
|||||||
@ -21,6 +21,7 @@ func chatHistoryEntriesForView(
|
|||||||
selectedMessages: Set<MessageId>?,
|
selectedMessages: Set<MessageId>?,
|
||||||
presentationData: ChatPresentationData,
|
presentationData: ChatPresentationData,
|
||||||
historyAppearsCleared: Bool,
|
historyAppearsCleared: Bool,
|
||||||
|
skipViewOnceMedia: Bool,
|
||||||
pendingUnpinnedAllMessages: Bool,
|
pendingUnpinnedAllMessages: Bool,
|
||||||
pendingRemovedMessages: Set<MessageId>,
|
pendingRemovedMessages: Set<MessageId>,
|
||||||
associatedData: ChatMessageItemAssociatedData,
|
associatedData: ChatMessageItemAssociatedData,
|
||||||
@ -152,6 +153,10 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipViewOnceMedia, message.minAutoremoveOrClearTimeout != nil {
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
|
||||||
var contentTypeHint: ChatMessageEntryContentType = .generic
|
var contentTypeHint: ChatMessageEntryContentType = .generic
|
||||||
|
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
|
|||||||
@ -1588,6 +1588,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
selectedMessages: selectedMessages,
|
selectedMessages: selectedMessages,
|
||||||
presentationData: chatPresentationData,
|
presentationData: chatPresentationData,
|
||||||
historyAppearsCleared: historyAppearsCleared,
|
historyAppearsCleared: historyAppearsCleared,
|
||||||
|
skipViewOnceMedia: mode != .bubbles,
|
||||||
pendingUnpinnedAllMessages: pendingUnpinnedAllMessages,
|
pendingUnpinnedAllMessages: pendingUnpinnedAllMessages,
|
||||||
pendingRemovedMessages: pendingRemovedMessages,
|
pendingRemovedMessages: pendingRemovedMessages,
|
||||||
associatedData: associatedData,
|
associatedData: associatedData,
|
||||||
|
|||||||
@ -909,7 +909,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
actions.insert(.separator, at: 1)
|
actions.insert(.separator, at: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasRateTranscription {
|
if !hasRateTranscription && message.minAutoremoveOrClearTimeout == nil {
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if let file = media as? TelegramMediaFile, let size = file.size, size < 1 * 1024 * 1024, let duration = file.duration, duration < 60, (["audio/mpeg", "audio/mp3", "audio/mpeg3", "audio/ogg"] as [String]).contains(file.mimeType.lowercased()) {
|
if let file = media as? TelegramMediaFile, let size = file.size, size < 1 * 1024 * 1024, let duration = file.duration, duration < 60, (["audio/mpeg", "audio/mp3", "audio/mpeg3", "audio/ogg"] as [String]).contains(file.mimeType.lowercased()) {
|
||||||
let fileName = file.fileName ?? "Tone"
|
let fileName = file.fileName ?? "Tone"
|
||||||
|
|||||||
@ -271,7 +271,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFirstTime {
|
if isFirstTime, !self.viewOnceButton.isHidden {
|
||||||
self.maybePresentViewOnceTooltip()
|
self.maybePresentViewOnceTooltip()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2634,7 +2634,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
|||||||
}
|
}
|
||||||
transition.updateAlpha(node: self.viewOnceButton, alpha: viewOnceIsVisible ? 1.0 : 0.0)
|
transition.updateAlpha(node: self.viewOnceButton, alpha: viewOnceIsVisible ? 1.0 : 0.0)
|
||||||
transition.updateTransformScale(node: self.viewOnceButton, scale: viewOnceIsVisible ? 1.0 : 0.01)
|
transition.updateTransformScale(node: self.viewOnceButton, scale: viewOnceIsVisible ? 1.0 : 0.01)
|
||||||
if let _ = interfaceState.renderedPeer?.peer as? TelegramUser {
|
if let user = interfaceState.renderedPeer?.peer as? TelegramUser, user.id != interfaceState.accountPeerId && user.botInfo == nil {
|
||||||
self.viewOnceButton.isHidden = false
|
self.viewOnceButton.isHidden = false
|
||||||
} else {
|
} else {
|
||||||
self.viewOnceButton.isHidden = true
|
self.viewOnceButton.isHidden = true
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "10.5.1",
|
"app": "10.5.2",
|
||||||
"bazel": "6.4.0",
|
"bazel": "6.4.0",
|
||||||
"xcode": "15.0",
|
"xcode": "15.0",
|
||||||
"macos": "13.0"
|
"macos": "13.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user