mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 13:35:19 +00:00
Various improvements
This commit is contained in:
parent
13669eee96
commit
88e5ff8f6b
@ -235,6 +235,13 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
|
||||
}
|
||||
}
|
||||
}))
|
||||
options.append(OpenInOption(identifier: "yangoMaps", application: .other(title: "Yango Maps", identifier: 1665672451, scheme: "yangomaps", store: nil), action: {
|
||||
if let _ = directions {
|
||||
return .openUrl(url: "yangomaps://build_route_on_map?lat_to=\(lat)&lon_to=\(lon)")
|
||||
} else {
|
||||
return .openUrl(url: "yangomaps://maps.yango.com/?pt=\(lon),\(lat)&z=16")
|
||||
}
|
||||
}))
|
||||
|
||||
options.append(OpenInOption(identifier: "yandexMaps", application: .other(title: "Yandex.Maps", identifier: 313877526, scheme: "yandexmaps", store: nil), action: {
|
||||
if let _ = directions {
|
||||
|
@ -264,8 +264,7 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
|
||||
} else if let _ = media as? TelegramMediaExpiredContent {
|
||||
result.removeAll()
|
||||
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
|
||||
needReactions = false
|
||||
return (result, false, false)
|
||||
break inner
|
||||
} else if let _ = media as? TelegramMediaPoll {
|
||||
result.append((message, ChatMessagePollBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
|
||||
needReactions = false
|
||||
@ -2735,6 +2734,8 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
default:
|
||||
centerAligned = true
|
||||
}
|
||||
} else if let _ = media as? TelegramMediaExpiredContent {
|
||||
centerAligned = true
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -299,8 +299,6 @@ public func canAddMessageReactions(message: Message) -> Bool {
|
||||
if story.isMention {
|
||||
return false
|
||||
}
|
||||
} else if let _ = media as? TelegramMediaExpiredContent {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
@ -24,6 +24,7 @@ swift_library(
|
||||
"//submodules/AppBundle",
|
||||
"//submodules/PresentationDataUtils",
|
||||
"//submodules/TelegramUI/Components/LottieComponent",
|
||||
"//submodules/TelegramUI/Components/PlainButtonComponent",
|
||||
"//submodules/AvatarNode",
|
||||
],
|
||||
visibility = [
|
||||
|
@ -22,22 +22,19 @@ private final class QuickShareScreenComponent: Component {
|
||||
let context: AccountContext
|
||||
let sourceNode: ASDisplayNode
|
||||
let gesture: ContextGesture
|
||||
let openPeer: (EnginePeer.Id) -> Void
|
||||
let completion: (EnginePeer.Id) -> Void
|
||||
let completion: (EnginePeer, CGRect) -> Void
|
||||
let ready: Promise<Bool>
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
sourceNode: ASDisplayNode,
|
||||
gesture: ContextGesture,
|
||||
openPeer: @escaping (EnginePeer.Id) -> Void,
|
||||
completion: @escaping (EnginePeer.Id) -> Void,
|
||||
completion: @escaping (EnginePeer, CGRect) -> Void,
|
||||
ready: Promise<Bool>
|
||||
) {
|
||||
self.context = context
|
||||
self.sourceNode = sourceNode
|
||||
self.gesture = gesture
|
||||
self.openPeer = openPeer
|
||||
self.completion = completion
|
||||
self.ready = ready
|
||||
}
|
||||
@ -184,24 +181,9 @@ private final class QuickShareScreenComponent: Component {
|
||||
|
||||
func highlightGestureFinished(performAction: Bool) {
|
||||
if let selectedPeerId = self.selectedPeerId, performAction {
|
||||
if let component = self.component, let peer = self.peers?.first(where: { $0.id == selectedPeerId }), let view = self.items[selectedPeerId]?.view as? ItemComponent.View, let controller = self.environment?.controller() {
|
||||
controller.window?.forEachController({ controller in
|
||||
if let controller = controller as? QuickShareToastScreen {
|
||||
controller.dismiss()
|
||||
}
|
||||
})
|
||||
let toastScreen = QuickShareToastScreen(
|
||||
context: component.context,
|
||||
peer: peer,
|
||||
sourceFrame: view.convert(view.bounds, to: nil),
|
||||
action: {
|
||||
component.openPeer(peer.id)
|
||||
}
|
||||
)
|
||||
controller.present(toastScreen, in: .window(.root))
|
||||
if let component = self.component, let peer = self.peers?.first(where: { $0.id == selectedPeerId }), let view = self.items[selectedPeerId]?.view as? ItemComponent.View {
|
||||
component.completion(peer, view.convert(view.bounds, to: nil))
|
||||
view.avatarNode.isHidden = true
|
||||
|
||||
component.completion(peer.id)
|
||||
}
|
||||
|
||||
self.animateOut {
|
||||
@ -296,7 +278,7 @@ private final class QuickShareScreenComponent: Component {
|
||||
|
||||
if theme.overallDarkAppearance {
|
||||
self.backgroundView.updateColor(color: theme.contextMenu.backgroundColor, forceKeepBlur: true, transition: .immediate)
|
||||
self.backgroundTintView.backgroundColor = UIColor(white: 1.0, alpha: 0.5)
|
||||
self.backgroundTintView.backgroundColor = .clear
|
||||
} else {
|
||||
self.backgroundView.updateColor(color: .clear, forceKeepBlur: true, transition: .immediate)
|
||||
self.backgroundTintView.backgroundColor = theme.contextMenu.backgroundColor
|
||||
@ -411,8 +393,7 @@ public class QuickShareScreen: ViewControllerComponentContainer {
|
||||
context: AccountContext,
|
||||
sourceNode: ASDisplayNode,
|
||||
gesture: ContextGesture,
|
||||
openPeer: @escaping (EnginePeer.Id) -> Void,
|
||||
completion: @escaping (EnginePeer.Id) -> Void
|
||||
completion: @escaping (EnginePeer, CGRect) -> Void
|
||||
) {
|
||||
let componentReady = Promise<Bool>()
|
||||
|
||||
@ -422,7 +403,6 @@ public class QuickShareScreen: ViewControllerComponentContainer {
|
||||
context: context,
|
||||
sourceNode: sourceNode,
|
||||
gesture: gesture,
|
||||
openPeer: openPeer,
|
||||
completion: completion,
|
||||
ready: componentReady
|
||||
),
|
||||
@ -528,7 +508,7 @@ private final class ItemComponent: Component {
|
||||
private weak var state: EmptyComponentState?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 14.0))
|
||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 26.0))
|
||||
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
||||
|
||||
super.init(frame: frame)
|
||||
|
@ -14,18 +14,19 @@ import MultilineTextComponent
|
||||
import AvatarNode
|
||||
import Markdown
|
||||
import LottieComponent
|
||||
import PlainButtonComponent
|
||||
|
||||
private final class QuickShareToastScreenComponent: Component {
|
||||
let context: AccountContext
|
||||
let peer: EnginePeer
|
||||
let sourceFrame: CGRect
|
||||
let action: () -> Void
|
||||
let action: (QuickShareToastScreen.Action) -> Void
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
peer: EnginePeer,
|
||||
sourceFrame: CGRect,
|
||||
action: @escaping () -> Void
|
||||
action: @escaping (QuickShareToastScreen.Action) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
self.peer = peer
|
||||
@ -51,6 +52,7 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
private let animation = ComponentView<Empty>()
|
||||
|
||||
private let content = ComponentView<Empty>()
|
||||
private let actionButton = ComponentView<Empty>()
|
||||
|
||||
private var isUpdating: Bool = false
|
||||
private var component: QuickShareToastScreenComponent?
|
||||
@ -93,7 +95,8 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
component.action()
|
||||
component.action(.info)
|
||||
self.doneTimer?.invalidate()
|
||||
self.environment?.controller()?.dismiss()
|
||||
}
|
||||
|
||||
@ -187,10 +190,10 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
|
||||
if self.component == nil {
|
||||
self.doneTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
guard let self, let controller = self.environment?.controller() as? QuickShareToastScreen else {
|
||||
return
|
||||
}
|
||||
self.environment?.controller()?.dismiss()
|
||||
controller.dismissWithCommitAction()
|
||||
})
|
||||
}
|
||||
|
||||
@ -230,6 +233,29 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
tooltipText = environment.strings.Conversation_ForwardTooltip_Chat_One(component.peer.compactDisplayTitle).string
|
||||
}
|
||||
|
||||
let actionButtonSize = self.actionButton.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(PlainButtonComponent(
|
||||
content: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "Undo", font: Font.regular(17.0), textColor: environment.theme.list.itemAccentColor.withMultiplied(hue: 0.933, saturation: 0.61, brightness: 1.0)))
|
||||
)),
|
||||
effectAlignment: .center,
|
||||
contentInsets: UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0),
|
||||
action: { [weak self] in
|
||||
guard let self, let _ = self.component else {
|
||||
return
|
||||
}
|
||||
self.doneTimer?.invalidate()
|
||||
self.environment?.controller()?.dismiss()
|
||||
},
|
||||
animateAlpha: true,
|
||||
animateScale: false,
|
||||
animateContents: false
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableContentSize.width - contentInsets.left - contentInsets.right - spacing - iconSize.width, height: availableContentSize.height)
|
||||
)
|
||||
|
||||
let contentSize = self.content.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(MultilineTextComponent(text: .markdown(
|
||||
@ -279,6 +305,13 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
transition.setFrame(view: contentView, frame: CGRect(origin: CGPoint(x: contentInsets.left + iconSize.width + spacing, y: floor((contentHeight - contentSize.height) * 0.5)), size: contentSize))
|
||||
}
|
||||
|
||||
if let actionButtonView = self.actionButton.view {
|
||||
if actionButtonView.superview == nil {
|
||||
self.backgroundView.addSubview(actionButtonView)
|
||||
}
|
||||
transition.setFrame(view: actionButtonView, frame: CGRect(origin: CGPoint(x: availableContentSize.width - contentInsets.right - 16.0 - actionButtonSize.width, y: floor((contentHeight - actionButtonSize.height) * 0.5)), size: actionButtonSize))
|
||||
}
|
||||
|
||||
let size = CGSize(width: availableContentSize.width, height: contentHeight)
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: containerInsets.left, y: availableSize.height - containerInsets.bottom - size.height), size: size)
|
||||
|
||||
@ -301,16 +334,24 @@ private final class QuickShareToastScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
final class QuickShareToastScreen: ViewControllerComponentContainer {
|
||||
public final class QuickShareToastScreen: ViewControllerComponentContainer {
|
||||
public enum Action {
|
||||
case info
|
||||
case commit
|
||||
}
|
||||
|
||||
private var processedDidAppear: Bool = false
|
||||
private var processedDidDisappear: Bool = false
|
||||
|
||||
init(
|
||||
private let action: (Action) -> Void
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
peer: EnginePeer,
|
||||
sourceFrame: CGRect,
|
||||
action: @escaping () -> Void
|
||||
action: @escaping (Action) -> Void
|
||||
) {
|
||||
self.action = action
|
||||
super.init(
|
||||
context: context,
|
||||
component: QuickShareToastScreenComponent(
|
||||
@ -334,11 +375,11 @@ final class QuickShareToastScreen: ViewControllerComponentContainer {
|
||||
deinit {
|
||||
}
|
||||
|
||||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.processedDidAppear {
|
||||
@ -353,7 +394,12 @@ final class QuickShareToastScreen: ViewControllerComponentContainer {
|
||||
super.dismiss()
|
||||
}
|
||||
|
||||
override func dismiss(completion: (() -> Void)? = nil) {
|
||||
public func dismissWithCommitAction() {
|
||||
self.action(.commit)
|
||||
self.dismiss()
|
||||
}
|
||||
|
||||
public override func dismiss(completion: (() -> Void)? = nil) {
|
||||
if !self.processedDidDisappear {
|
||||
self.processedDidDisappear = true
|
||||
|
||||
|
@ -15,9 +15,9 @@ public func peerMessageAllowedReactions(context: AccountContext, message: Messag
|
||||
return .single((.all, false))
|
||||
}
|
||||
|
||||
if message.containsSecretMedia {
|
||||
return .single((AllowedReactions.set(Set()), false))
|
||||
}
|
||||
// if message.containsSecretMedia {
|
||||
// return .single((AllowedReactions.set(Set()), false))
|
||||
// }
|
||||
|
||||
return combineLatest(
|
||||
context.engine.data.get(
|
||||
|
@ -593,7 +593,6 @@ private final class SheetContent: CombinedComponent {
|
||||
return
|
||||
}
|
||||
starsContext.add(balance: StarsAmount(value: stars, nanos: 0))
|
||||
|
||||
let _ = (starsContext.onUpdate
|
||||
|> deliverOnMainQueue).start(next: {
|
||||
completion()
|
||||
|
@ -71,7 +71,8 @@ extension ChatControllerImpl {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let controller = self.context.sharedContext.makeStarsPurchaseScreen(context: self.context, starsContext: starsContext, options: options, purpose: .sendMessage(peerId: peer.id, requiredStars: totalAmount), completion: { _ in
|
||||
let controller = self.context.sharedContext.makeStarsPurchaseScreen(context: self.context, starsContext: starsContext, options: options, purpose: .sendMessage(peerId: peer.id, requiredStars: totalAmount), completion: { stars in
|
||||
starsContext.add(balance: StarsAmount(value: stars, nanos: 0))
|
||||
let _ = (starsContext.onUpdate
|
||||
|> deliverOnMainQueue).start(next: {
|
||||
completion(false)
|
||||
|
@ -12,39 +12,48 @@ extension ChatControllerImpl {
|
||||
context: self.context,
|
||||
sourceNode: node,
|
||||
gesture: gesture,
|
||||
openPeer: { [weak self] peerId in
|
||||
completion: { [weak self] peer, sourceFrame in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
guard let self else {
|
||||
return
|
||||
self.window?.forEachController({ controller in
|
||||
if let controller = controller as? QuickShareToastScreen {
|
||||
controller.dismissWithCommitAction()
|
||||
}
|
||||
self.openPeer(peer: peer, navigation: .chat(textInputState: nil, subject: nil, peekData: nil), fromMessage: nil)
|
||||
})
|
||||
},
|
||||
completion: { [weak self] peerId in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let enqueueMessage = StandaloneSendEnqueueMessage(
|
||||
content: .forward(forward: StandaloneSendEnqueueMessage.Forward(
|
||||
sourceId: id,
|
||||
threadId: nil
|
||||
)),
|
||||
replyToMessageId: nil
|
||||
let toastScreen = QuickShareToastScreen(
|
||||
context: self.context,
|
||||
peer: peer,
|
||||
sourceFrame: sourceFrame,
|
||||
action: { [weak self] action in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
switch action {
|
||||
case .info:
|
||||
self.openPeer(peer: peer, navigation: .chat(textInputState: nil, subject: nil, peekData: nil), fromMessage: nil)
|
||||
case .commit:
|
||||
let enqueueMessage = StandaloneSendEnqueueMessage(
|
||||
content: .forward(forward: StandaloneSendEnqueueMessage.Forward(
|
||||
sourceId: id,
|
||||
threadId: nil
|
||||
)),
|
||||
replyToMessageId: nil
|
||||
)
|
||||
let _ = (standaloneSendEnqueueMessages(
|
||||
accountPeerId: self.context.account.peerId,
|
||||
postbox: self.context.account.postbox,
|
||||
network: self.context.account.network,
|
||||
stateManager: self.context.account.stateManager,
|
||||
auxiliaryMethods: self.context.account.auxiliaryMethods,
|
||||
peerId: peer.id,
|
||||
threadId: nil,
|
||||
messages: [enqueueMessage]
|
||||
)).startStandalone()
|
||||
}
|
||||
}
|
||||
)
|
||||
let _ = (standaloneSendEnqueueMessages(
|
||||
accountPeerId: self.context.account.peerId,
|
||||
postbox: self.context.account.postbox,
|
||||
network: self.context.account.network,
|
||||
stateManager: self.context.account.stateManager,
|
||||
auxiliaryMethods: self.context.account.auxiliaryMethods,
|
||||
peerId: peerId,
|
||||
threadId: nil,
|
||||
messages: [enqueueMessage]
|
||||
)).startStandalone()
|
||||
self.present(toastScreen, in: .window(.root))
|
||||
}
|
||||
)
|
||||
self.presentInGlobalOverlay(controller)
|
||||
|
@ -134,6 +134,7 @@ import AdsReportScreen
|
||||
import AdUI
|
||||
import ChatMessagePaymentAlertController
|
||||
import TelegramCallsUI
|
||||
import QuickShareScreen
|
||||
|
||||
public enum ChatControllerPeekActions {
|
||||
case standard
|
||||
@ -10740,6 +10741,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismissWithCommitAction()
|
||||
}
|
||||
if let controller = controller as? QuickShareToastScreen {
|
||||
controller.dismissWithCommitAction()
|
||||
}
|
||||
})
|
||||
self.forEachController({ controller in
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
|
Loading…
x
Reference in New Issue
Block a user