mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
10984d7ce4
commit
44f02c258f
@ -13290,5 +13290,10 @@ Sorry for the inconvenience.";
|
|||||||
"MediaGallery.ToastVideoPip.Title" = "Video Minimized";
|
"MediaGallery.ToastVideoPip.Title" = "Video Minimized";
|
||||||
"MediaGallery.ToastVideoPip.Text" = "Swipe down on a video to close it.";
|
"MediaGallery.ToastVideoPip.Text" = "Swipe down on a video to close it.";
|
||||||
|
|
||||||
"Chat.ToastSubscribedToScheduledLiveStream.Text" = "You will be notified when the liver stream starts.";
|
"Chat.ToastSubscribedToScheduledLiveStream.Text" = "You will be notified when the live stream starts.";
|
||||||
"Chat.TitleVideochatPanel.NotifyScheduledButton" = "Notify Me";
|
"Chat.TitleVideochatPanel.NotifyScheduledButton" = "Notify Me";
|
||||||
|
|
||||||
|
"WebApp.ShareMessage.Title" = "Share Message";
|
||||||
|
"WebApp.ShareMessage.PreviewTitle" = "MESSAGE PREVIEW";
|
||||||
|
"WebApp.ShareMessage.Info" = "%@ mini app suggests you to send this message to a chat you select.";
|
||||||
|
"WebApp.ShareMessage.Share" = "Share With...";
|
||||||
|
@ -1000,7 +1000,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
|
|
||||||
func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController
|
func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController
|
||||||
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController
|
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController
|
||||||
func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption]) -> ViewController
|
func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption], hasBirthday: Bool) -> ViewController
|
||||||
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
|
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
|
||||||
func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController
|
func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController
|
||||||
|
|
||||||
|
@ -1256,6 +1256,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.chatListDisplayNode.dismissSearch = { [weak self] in
|
||||||
|
if let self {
|
||||||
|
self.deactivateSearch(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.chatListDisplayNode.requestOpenRecentPeerOptions = { [weak self] peer in
|
self.chatListDisplayNode.requestOpenRecentPeerOptions = { [weak self] peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.view.window?.endEditing(true)
|
strongSelf.view.window?.endEditing(true)
|
||||||
|
@ -1095,6 +1095,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
var isEmptyUpdated: ((Bool) -> Void)?
|
var isEmptyUpdated: ((Bool) -> Void)?
|
||||||
var emptyListAction: ((EnginePeer.Id?) -> Void)?
|
var emptyListAction: ((EnginePeer.Id?) -> Void)?
|
||||||
var cancelEditing: (() -> Void)?
|
var cancelEditing: (() -> Void)?
|
||||||
|
var dismissSearch: (() -> Void)?
|
||||||
|
|
||||||
let debugListView = ListView()
|
let debugListView = ListView()
|
||||||
|
|
||||||
@ -1668,6 +1669,9 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
}, navigationController: navigationController, parentController: { [weak self] in
|
}, navigationController: navigationController, parentController: { [weak self] in
|
||||||
return self?.controller
|
return self?.controller
|
||||||
})
|
})
|
||||||
|
contentNode.dismissSearch = { [weak self] in
|
||||||
|
self?.dismissSearch?()
|
||||||
|
}
|
||||||
|
|
||||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: contentNode, cancel: { [weak self] in
|
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: contentNode, cancel: { [weak self] in
|
||||||
if let requestDeactivateSearch = self?.requestDeactivateSearch {
|
if let requestDeactivateSearch = self?.requestDeactivateSearch {
|
||||||
|
@ -61,8 +61,9 @@ final class ChatListSearchInteraction {
|
|||||||
let getSelectedMessageIds: () -> Set<EngineMessage.Id>?
|
let getSelectedMessageIds: () -> Set<EngineMessage.Id>?
|
||||||
let openStories: ((PeerId, ASDisplayNode) -> Void)?
|
let openStories: ((PeerId, ASDisplayNode) -> Void)?
|
||||||
let switchToFilter: (ChatListSearchPaneKey) -> Void
|
let switchToFilter: (ChatListSearchPaneKey) -> Void
|
||||||
|
let dismissSearch: () -> Void
|
||||||
|
|
||||||
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void) {
|
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void) {
|
||||||
self.openPeer = openPeer
|
self.openPeer = openPeer
|
||||||
self.openDisabledPeer = openDisabledPeer
|
self.openDisabledPeer = openDisabledPeer
|
||||||
self.openMessage = openMessage
|
self.openMessage = openMessage
|
||||||
@ -78,6 +79,7 @@ final class ChatListSearchInteraction {
|
|||||||
self.getSelectedMessageIds = getSelectedMessageIds
|
self.getSelectedMessageIds = getSelectedMessageIds
|
||||||
self.openStories = openStories
|
self.openStories = openStories
|
||||||
self.switchToFilter = switchToFilter
|
self.switchToFilter = switchToFilter
|
||||||
|
self.dismissSearch = dismissSearch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +102,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
private let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void
|
private let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void
|
||||||
private let navigationController: NavigationController?
|
private let navigationController: NavigationController?
|
||||||
|
|
||||||
|
var dismissSearch: (() -> Void)?
|
||||||
|
|
||||||
private let dimNode: ASDisplayNode
|
private let dimNode: ASDisplayNode
|
||||||
let filterContainerNode: ChatListSearchFiltersContainerNode
|
let filterContainerNode: ChatListSearchFiltersContainerNode
|
||||||
private let paneContainerNode: ChatListSearchPaneContainerNode
|
private let paneContainerNode: ChatListSearchPaneContainerNode
|
||||||
@ -298,6 +302,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
Queue.mainQueue().justDispatch {
|
Queue.mainQueue().justDispatch {
|
||||||
self.paneContainerNode.requestSelectPane(filter)
|
self.paneContainerNode.requestSelectPane(filter)
|
||||||
}
|
}
|
||||||
|
}, dismissSearch: { [weak self] in
|
||||||
|
self?.dismissSearch?()
|
||||||
})
|
})
|
||||||
self.paneContainerNode.interaction = interaction
|
self.paneContainerNode.interaction = interaction
|
||||||
|
|
||||||
|
@ -614,7 +614,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .thread(peer: peer, title: threadInfo.info.title, icon: threadInfo.info.icon, color: threadInfo.info.iconColor), status: .none, badge: nil, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .thread(peer: peer, title: threadInfo.info.title, icon: threadInfo.info.icon, color: threadInfo.info.iconColor), status: .none, badge: nil, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||||
interaction.peerSelected(peer, nil, threadInfo.id, nil)
|
interaction.peerSelected(peer, nil, threadInfo.id, nil, false)
|
||||||
}, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer)
|
}, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer)
|
||||||
case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, storyStats, requiresPremiumForMessaging):
|
case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, storyStats, requiresPremiumForMessaging):
|
||||||
let primaryPeer: EnginePeer
|
let primaryPeer: EnginePeer
|
||||||
@ -667,6 +667,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
badge = ContactsPeerItemBadge(count: unreadBadge.0, type: unreadBadge.1 ? .inactive : .active)
|
badge = ContactsPeerItemBadge(count: unreadBadge.0, type: unreadBadge.1 ? .inactive : .active)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var buttonAction: ContactsPeerItemButtonAction?
|
||||||
let header: ChatListSearchItemHeader?
|
let header: ChatListSearchItemHeader?
|
||||||
if filter.contains(.removeSearchHeader) {
|
if filter.contains(.removeSearchHeader) {
|
||||||
header = nil
|
header = nil
|
||||||
@ -676,15 +677,24 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
headerType = .chats
|
headerType = .chats
|
||||||
} else {
|
} else {
|
||||||
headerType = .recentPeers
|
headerType = .recentPeers
|
||||||
|
|
||||||
|
if case .chats = key, case let .user(user) = primaryPeer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp) {
|
||||||
|
buttonAction = ContactsPeerItemButtonAction(
|
||||||
|
title: presentationData.strings.ChatList_Search_Open,
|
||||||
|
action: { peer, _, _ in
|
||||||
|
interaction.peerSelected(primaryPeer, nil, nil, nil, true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
header = ChatListSearchItemHeader(type: headerType, theme: theme, strings: strings, actionTitle: nil, action: nil)
|
header = ChatListSearchItemHeader(type: headerType, theme: theme, strings: strings, actionTitle: nil, action: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), buttonAction: buttonAction, index: nil, header: header, action: { contactPeer in
|
||||||
if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer {
|
if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer {
|
||||||
interaction.peerSelected(chatPeer, peer, nil, nil)
|
interaction.peerSelected(chatPeer, peer, nil, nil, false)
|
||||||
} else {
|
} else {
|
||||||
interaction.peerSelected(peer, nil, nil, nil)
|
interaction.peerSelected(peer, nil, nil, nil, false)
|
||||||
}
|
}
|
||||||
}, disabledAction: { _ in
|
}, disabledAction: { _ in
|
||||||
interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
||||||
@ -804,11 +814,21 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in
|
var buttonAction: ContactsPeerItemButtonAction?
|
||||||
|
if case .chats = key, case let .user(user) = primaryPeer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp) {
|
||||||
|
buttonAction = ContactsPeerItemButtonAction(
|
||||||
|
title: presentationData.strings.ChatList_Search_Open,
|
||||||
|
action: { peer, _, _ in
|
||||||
|
interaction.peerSelected(primaryPeer, nil, nil, nil, true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), buttonAction: buttonAction, index: nil, header: header, action: { contactPeer in
|
||||||
if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer {
|
if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer {
|
||||||
interaction.peerSelected(chatPeer, peer, nil, nil)
|
interaction.peerSelected(chatPeer, peer, nil, nil, false)
|
||||||
} else {
|
} else {
|
||||||
interaction.peerSelected(peer, nil, nil, nil)
|
interaction.peerSelected(peer, nil, nil, nil, false)
|
||||||
}
|
}
|
||||||
}, disabledAction: { _ in
|
}, disabledAction: { _ in
|
||||||
interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
||||||
@ -891,7 +911,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: query, action: { _ in
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: query, action: { _ in
|
||||||
interaction.peerSelected(EnginePeer(peer.peer), nil, nil, nil)
|
interaction.peerSelected(EnginePeer(peer.peer), nil, nil, nil, false)
|
||||||
}, disabledAction: { _ in
|
}, disabledAction: { _ in
|
||||||
interaction.disabledPeerSelected(EnginePeer(peer.peer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
interaction.disabledPeerSelected(EnginePeer(peer.peer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
||||||
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
||||||
@ -2883,9 +2903,29 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chatListInteraction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {
|
let chatListInteraction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {
|
||||||
}, peerSelected: { [weak self] peer, chatPeer, threadId, _ in
|
}, peerSelected: { [weak self] peer, chatPeer, threadId, _, openApp in
|
||||||
interaction.dismissInput()
|
interaction.dismissInput()
|
||||||
|
if openApp, let self {
|
||||||
|
if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp), let parentController = self.parentController {
|
||||||
|
context.sharedContext.openWebApp(
|
||||||
|
context: context,
|
||||||
|
parentController: parentController,
|
||||||
|
updatedPresentationData: nil,
|
||||||
|
botPeer: peer,
|
||||||
|
chatPeer: nil,
|
||||||
|
threadId: nil,
|
||||||
|
buttonText: "",
|
||||||
|
url: "",
|
||||||
|
simple: true,
|
||||||
|
source: .generic,
|
||||||
|
skipTermsOfService: true,
|
||||||
|
payload: nil
|
||||||
|
)
|
||||||
|
interaction.dismissSearch()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
interaction.openPeer(peer, chatPeer, threadId, false)
|
interaction.openPeer(peer, chatPeer, threadId, false)
|
||||||
|
}
|
||||||
switch location {
|
switch location {
|
||||||
case .chatList, .forum:
|
case .chatList, .forum:
|
||||||
let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).startStandalone()
|
let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).startStandalone()
|
||||||
@ -3851,6 +3891,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil
|
||||||
)
|
)
|
||||||
|
interaction.dismissSearch()
|
||||||
} else {
|
} else {
|
||||||
interaction.openPeer(peer, nil, threadId, true)
|
interaction.openPeer(peer, nil, threadId, true)
|
||||||
}
|
}
|
||||||
@ -4853,7 +4894,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
let timestamp1: Int32 = 100000
|
let timestamp1: Int32 = 100000
|
||||||
var peers: [EnginePeer.Id: EnginePeer] = [:]
|
var peers: [EnginePeer.Id: EnginePeer] = [:]
|
||||||
peers[peer1.id] = peer1
|
peers[peer1.id] = peer1
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {
|
||||||
|
@ -153,7 +153,7 @@ public final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil))
|
let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil))
|
||||||
let timestamp1: Int32 = 100000
|
let timestamp1: Int32 = 100000
|
||||||
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {}, openBirthdaySetup: {}, performActiveSessionAction: { _, _ in }, openChatFolderUpdates: {}, hideChatFolderUpdates: {}, openStories: { _, _ in }, openStarsTopup: { _ in
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {}, openBirthdaySetup: {}, performActiveSessionAction: { _, _ in }, openChatFolderUpdates: {}, hideChatFolderUpdates: {}, openStories: { _, _ in }, openStarsTopup: { _ in
|
||||||
|
@ -503,9 +503,9 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
|||||||
}
|
}
|
||||||
self.interaction.messageSelected(peer, threadId, message, peerData.promoInfo)
|
self.interaction.messageSelected(peer, threadId, message, peerData.promoInfo)
|
||||||
} else if let peer = peerData.peer.peer {
|
} else if let peer = peerData.peer.peer {
|
||||||
self.interaction.peerSelected(peer, nil, nil, peerData.promoInfo)
|
self.interaction.peerSelected(peer, nil, nil, peerData.promoInfo, false)
|
||||||
} else if let peer = peerData.peer.peers[peerData.peer.peerId] {
|
} else if let peer = peerData.peer.peers[peerData.peer.peerId] {
|
||||||
self.interaction.peerSelected(peer, nil, nil, peerData.promoInfo)
|
self.interaction.peerSelected(peer, nil, nil, peerData.promoInfo, false)
|
||||||
}
|
}
|
||||||
case let .groupReference(groupReferenceData):
|
case let .groupReference(groupReferenceData):
|
||||||
self.interaction.groupSelected(groupReferenceData.groupId)
|
self.interaction.groupSelected(groupReferenceData.groupId)
|
||||||
|
@ -73,7 +73,7 @@ public final class ChatListNodeInteraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let activateSearch: () -> Void
|
let activateSearch: () -> Void
|
||||||
let peerSelected: (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void
|
let peerSelected: (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?, Bool) -> Void
|
||||||
let disabledPeerSelected: (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void
|
let disabledPeerSelected: (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void
|
||||||
let togglePeerSelected: (EnginePeer, Int64?) -> Void
|
let togglePeerSelected: (EnginePeer, Int64?) -> Void
|
||||||
let togglePeersSelection: ([PeerEntry], Bool) -> Void
|
let togglePeersSelection: ([PeerEntry], Bool) -> Void
|
||||||
@ -129,7 +129,7 @@ public final class ChatListNodeInteraction {
|
|||||||
animationCache: AnimationCache,
|
animationCache: AnimationCache,
|
||||||
animationRenderer: MultiAnimationRenderer,
|
animationRenderer: MultiAnimationRenderer,
|
||||||
activateSearch: @escaping () -> Void,
|
activateSearch: @escaping () -> Void,
|
||||||
peerSelected: @escaping (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void,
|
peerSelected: @escaping (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?, Bool) -> Void,
|
||||||
disabledPeerSelected: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void,
|
disabledPeerSelected: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void,
|
||||||
togglePeerSelected: @escaping (EnginePeer, Int64?) -> Void,
|
togglePeerSelected: @escaping (EnginePeer, Int64?) -> Void,
|
||||||
togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void,
|
togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void,
|
||||||
@ -613,7 +613,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
if editing {
|
if editing {
|
||||||
nodeInteraction.togglePeerSelected(chatPeer, threadId)
|
nodeInteraction.togglePeerSelected(chatPeer, threadId)
|
||||||
} else {
|
} else {
|
||||||
nodeInteraction.peerSelected(chatPeer, nil, threadId, nil)
|
nodeInteraction.peerSelected(chatPeer, nil, threadId, nil, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, disabledAction: (isForum && editing) && !peerEntry.requiresPremiumForMessaging ? nil : { _ in
|
}, disabledAction: (isForum && editing) && !peerEntry.requiresPremiumForMessaging ? nil : { _ in
|
||||||
@ -653,7 +653,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
if editing {
|
if editing {
|
||||||
nodeInteraction.togglePeerSelected(chatPeer, nil)
|
nodeInteraction.togglePeerSelected(chatPeer, nil)
|
||||||
} else {
|
} else {
|
||||||
nodeInteraction.peerSelected(chatPeer, nil, nil, nil)
|
nodeInteraction.peerSelected(chatPeer, nil, nil, nil, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, disabledAction: peerEntry.requiresPremiumForMessaging ? { _ in
|
}, disabledAction: peerEntry.requiresPremiumForMessaging ? { _ in
|
||||||
@ -719,7 +719,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
index: nil,
|
index: nil,
|
||||||
header: header,
|
header: header,
|
||||||
action: { _ in
|
action: { _ in
|
||||||
nodeInteraction.peerSelected(contactEntry.peer, nil, nil, nil)
|
nodeInteraction.peerSelected(contactEntry.peer, nil, nil, nil, false)
|
||||||
},
|
},
|
||||||
disabledAction: nil,
|
disabledAction: nil,
|
||||||
animationCache: nodeInteraction.animationCache,
|
animationCache: nodeInteraction.animationCache,
|
||||||
@ -957,7 +957,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
if editing {
|
if editing {
|
||||||
nodeInteraction.togglePeerSelected(chatPeer, threadId)
|
nodeInteraction.togglePeerSelected(chatPeer, threadId)
|
||||||
} else {
|
} else {
|
||||||
nodeInteraction.peerSelected(chatPeer, nil, threadId, nil)
|
nodeInteraction.peerSelected(chatPeer, nil, threadId, nil, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, disabledAction: (isForum && editing) && !peerEntry.requiresPremiumForMessaging ? nil : { _ in
|
}, disabledAction: (isForum && editing) && !peerEntry.requiresPremiumForMessaging ? nil : { _ in
|
||||||
@ -997,7 +997,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
if editing {
|
if editing {
|
||||||
nodeInteraction.togglePeerSelected(chatPeer, nil)
|
nodeInteraction.togglePeerSelected(chatPeer, nil)
|
||||||
} else {
|
} else {
|
||||||
nodeInteraction.peerSelected(chatPeer, nil, nil, nil)
|
nodeInteraction.peerSelected(chatPeer, nil, nil, nil, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, disabledAction: peerEntry.requiresPremiumForMessaging ? { _ in
|
}, disabledAction: peerEntry.requiresPremiumForMessaging ? { _ in
|
||||||
@ -1063,7 +1063,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
index: nil,
|
index: nil,
|
||||||
header: header,
|
header: header,
|
||||||
action: { _ in
|
action: { _ in
|
||||||
nodeInteraction.peerSelected(contactEntry.peer, nil, nil, nil)
|
nodeInteraction.peerSelected(contactEntry.peer, nil, nil, nil, false)
|
||||||
},
|
},
|
||||||
disabledAction: nil,
|
disabledAction: nil,
|
||||||
animationCache: nodeInteraction.animationCache,
|
animationCache: nodeInteraction.animationCache,
|
||||||
@ -1395,7 +1395,7 @@ public final class ChatListNode: ListView {
|
|||||||
if let strongSelf = self, let activateSearch = strongSelf.activateSearch {
|
if let strongSelf = self, let activateSearch = strongSelf.activateSearch {
|
||||||
activateSearch()
|
activateSearch()
|
||||||
}
|
}
|
||||||
}, peerSelected: { [weak self] peer, _, threadId, promoInfo in
|
}, peerSelected: { [weak self] peer, _, threadId, promoInfo, _ in
|
||||||
if let strongSelf = self, let peerSelected = strongSelf.peerSelected {
|
if let strongSelf = self, let peerSelected = strongSelf.peerSelected {
|
||||||
peerSelected(peer, threadId, true, true, promoInfo)
|
peerSelected(peer, threadId, true, true, promoInfo)
|
||||||
}
|
}
|
||||||
@ -1727,7 +1727,7 @@ public final class ChatListNode: ListView {
|
|||||||
|> filter { !$0.isEmpty }
|
|> filter { !$0.isEmpty }
|
||||||
|> deliverOnMainQueue).start(next: { giftOptions in
|
|> deliverOnMainQueue).start(next: { giftOptions in
|
||||||
let premiumOptions = giftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
let premiumOptions = giftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
||||||
let controller = self.context.sharedContext.makeGiftOptionsController(context: self.context, peerId: peerId, premiumOptions: premiumOptions)
|
let controller = self.context.sharedContext.makeGiftOptionsController(context: self.context, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: true)
|
||||||
controller.navigationPresentation = .modal
|
controller.navigationPresentation = .modal
|
||||||
self.push?(controller)
|
self.push?(controller)
|
||||||
})
|
})
|
||||||
|
@ -108,7 +108,10 @@ class EmojiHeaderComponent: Component {
|
|||||||
|
|
||||||
self.statusView.isHidden = false
|
self.statusView.isHidden = false
|
||||||
if containerView.subviews.count > 1 && containerView.subviews[1].subviews.count > 1 {
|
if containerView.subviews.count > 1 && containerView.subviews[1].subviews.count > 1 {
|
||||||
containerView = containerView.subviews[1].subviews[1]
|
let candidateView = containerView.subviews[1].subviews[1]
|
||||||
|
if !(candidateView is UIVisualEffectView) {
|
||||||
|
containerView = candidateView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let initialPosition = self.statusView.center
|
let initialPosition = self.statusView.center
|
||||||
|
@ -218,7 +218,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView
|
|||||||
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
|
@ -366,7 +366,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
|
@ -378,7 +378,7 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||||||
self.controllerInteraction.sendMessage(markupButton.title)
|
self.controllerInteraction.sendMessage(markupButton.title)
|
||||||
dismissIfOnce = true
|
dismissIfOnce = true
|
||||||
case let .url(url):
|
case let .url(url):
|
||||||
self.controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: true))
|
self.controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: true, progress: Promise()))
|
||||||
case .requestMap:
|
case .requestMap:
|
||||||
self.controllerInteraction.shareCurrentLocation()
|
self.controllerInteraction.shareCurrentLocation()
|
||||||
case .requestPhone:
|
case .requestPhone:
|
||||||
|
@ -585,7 +585,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
animationRenderer: component.context.animationRenderer,
|
animationRenderer: component.context.animationRenderer,
|
||||||
activateSearch: {
|
activateSearch: {
|
||||||
},
|
},
|
||||||
peerSelected: { _, _, _, _ in
|
peerSelected: { _, _, _, _, _ in
|
||||||
},
|
},
|
||||||
disabledPeerSelected: { _, _, _ in
|
disabledPeerSelected: { _, _, _ in
|
||||||
},
|
},
|
||||||
|
@ -814,7 +814,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol {
|
|||||||
if url.hasPrefix("tg://") {
|
if url.hasPrefix("tg://") {
|
||||||
concealed = false
|
concealed = false
|
||||||
}
|
}
|
||||||
item.controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: concealed))
|
item.controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: concealed, progress: Promise()))
|
||||||
case .requestMap:
|
case .requestMap:
|
||||||
item.controllerInteraction.shareCurrentLocation()
|
item.controllerInteraction.shareCurrentLocation()
|
||||||
case .requestPhone:
|
case .requestPhone:
|
||||||
|
@ -35,6 +35,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
let starsContext: StarsContext
|
let starsContext: StarsContext
|
||||||
let peerId: EnginePeer.Id
|
let peerId: EnginePeer.Id
|
||||||
let premiumOptions: [CachedPremiumGiftOption]
|
let premiumOptions: [CachedPremiumGiftOption]
|
||||||
|
let hasBirthday: Bool
|
||||||
let completion: (() -> Void)?
|
let completion: (() -> Void)?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ -42,12 +43,14 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
starsContext: StarsContext,
|
starsContext: StarsContext,
|
||||||
peerId: EnginePeer.Id,
|
peerId: EnginePeer.Id,
|
||||||
premiumOptions: [CachedPremiumGiftOption],
|
premiumOptions: [CachedPremiumGiftOption],
|
||||||
|
hasBirthday: Bool,
|
||||||
completion: (() -> Void)?
|
completion: (() -> Void)?
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.starsContext = starsContext
|
self.starsContext = starsContext
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.premiumOptions = premiumOptions
|
self.premiumOptions = premiumOptions
|
||||||
|
self.hasBirthday = hasBirthday
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +64,9 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
if lhs.premiumOptions != rhs.premiumOptions {
|
if lhs.premiumOptions != rhs.premiumOptions {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasBirthday != rhs.hasBirthday {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,13 +133,25 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
private var _effectiveStarGifts: ([StarGift], StarsFilter)?
|
private var _effectiveStarGifts: ([StarGift], StarsFilter)?
|
||||||
private var effectiveStarGifts: [StarGift]? {
|
private var effectiveStarGifts: [StarGift]? {
|
||||||
get {
|
get {
|
||||||
if case .all = self.starsFilter {
|
|
||||||
return self.state?.starGifts
|
|
||||||
} else {
|
|
||||||
if let (currentGifts, currentFilter) = self._effectiveStarGifts, currentFilter == self.starsFilter {
|
if let (currentGifts, currentFilter) = self._effectiveStarGifts, currentFilter == self.starsFilter {
|
||||||
return currentGifts
|
return currentGifts
|
||||||
} else if let allGifts = self.state?.starGifts {
|
} else if let allGifts = self.state?.starGifts {
|
||||||
let filteredGifts: [StarGift] = allGifts.filter {
|
var sortedGifts = allGifts
|
||||||
|
if self.component?.hasBirthday == true {
|
||||||
|
var updatedGifts: [StarGift] = []
|
||||||
|
for gift in allGifts {
|
||||||
|
if gift.flags.contains(.isBirthdayGift) {
|
||||||
|
updatedGifts.append(gift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for gift in allGifts {
|
||||||
|
if !gift.flags.contains(.isBirthdayGift) {
|
||||||
|
updatedGifts.append(gift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortedGifts = updatedGifts
|
||||||
|
}
|
||||||
|
let filteredGifts: [StarGift] = sortedGifts.filter {
|
||||||
switch self.starsFilter {
|
switch self.starsFilter {
|
||||||
case .all:
|
case .all:
|
||||||
return true
|
return true
|
||||||
@ -155,7 +173,6 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private var isUpdating: Bool = false
|
private var isUpdating: Bool = false
|
||||||
|
|
||||||
@ -236,7 +253,8 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
transition.setAlpha(view: topSeparator, alpha: topPanelAlpha)
|
transition.setAlpha(view: topSeparator, alpha: topPanelAlpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
let topInset: CGFloat = environment.navigationHeight - 56.0
|
let topInset: CGFloat = 0.0
|
||||||
|
let headerTopInset: CGFloat = environment.navigationHeight - 56.0
|
||||||
|
|
||||||
let premiumTitleInitialPosition = (topInset + 160.0)
|
let premiumTitleInitialPosition = (topInset + 160.0)
|
||||||
let premiumTitleOffsetDelta = premiumTitleInitialPosition - (environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0)
|
let premiumTitleOffsetDelta = premiumTitleInitialPosition - (environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0)
|
||||||
@ -261,7 +279,11 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
let starsTitleScale = 1.0 - starsTitleFraction * 0.36
|
let starsTitleScale = 1.0 - starsTitleFraction * 0.36
|
||||||
if let starsTitleView = self.starsTitle.view {
|
if let starsTitleView = self.starsTitle.view {
|
||||||
transition.setPosition(view: starsTitleView, position: CGPoint(x: availableWidth / 2.0, y: max(topInset + 455.0 - starsTitleOffset, environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0)))
|
var starsTitlePosition: CGFloat = 455.0
|
||||||
|
if let descriptionPosition = self.starsDescription.view?.frame.minY {
|
||||||
|
starsTitlePosition = descriptionPosition - 28.0
|
||||||
|
}
|
||||||
|
transition.setPosition(view: starsTitleView, position: CGPoint(x: availableWidth / 2.0, y: max(topInset + starsTitlePosition - starsTitleOffset, environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0)))
|
||||||
transition.setScale(view: starsTitleView, scale: starsTitleScale)
|
transition.setScale(view: starsTitleView, scale: starsTitleScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +293,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let headerView = self.header.view {
|
if let headerView = self.header.view {
|
||||||
transition.setPosition(view: headerView, position: CGPoint(x: availableWidth / 2.0, y: topInset + headerView.bounds.height / 2.0 - 30.0 - premiumTitleOffset * premiumTitleScale))
|
transition.setPosition(view: headerView, position: CGPoint(x: availableWidth / 2.0, y: headerTopInset + headerView.bounds.height / 2.0 - 30.0 - premiumTitleOffset * premiumTitleScale))
|
||||||
transition.setScale(view: headerView, scale: premiumTitleScale)
|
transition.setScale(view: headerView, scale: premiumTitleScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,6 +1095,7 @@ open class GiftOptionsScreen: ViewControllerComponentContainer, GiftOptionsScree
|
|||||||
starsContext: StarsContext,
|
starsContext: StarsContext,
|
||||||
peerId: EnginePeer.Id,
|
peerId: EnginePeer.Id,
|
||||||
premiumOptions: [CachedPremiumGiftOption],
|
premiumOptions: [CachedPremiumGiftOption],
|
||||||
|
hasBirthday: Bool,
|
||||||
completion: (() -> Void)? = nil
|
completion: (() -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -1082,6 +1105,7 @@ open class GiftOptionsScreen: ViewControllerComponentContainer, GiftOptionsScree
|
|||||||
starsContext: starsContext,
|
starsContext: starsContext,
|
||||||
peerId: peerId,
|
peerId: peerId,
|
||||||
premiumOptions: premiumOptions,
|
premiumOptions: premiumOptions,
|
||||||
|
hasBirthday: hasBirthday,
|
||||||
completion: completion
|
completion: completion
|
||||||
), navigationBarAppearance: .none, theme: .default, updatedPresentationData: nil)
|
), navigationBarAppearance: .none, theme: .default, updatedPresentationData: nil)
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component.openStarsIntro()
|
component.openStarsIntro()
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
context.add(description
|
context.add(description
|
||||||
@ -1110,7 +1110,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
|> filter { !$0.isEmpty }
|
|> filter { !$0.isEmpty }
|
||||||
|> deliverOnMainQueue).start(next: { giftOptions in
|
|> deliverOnMainQueue).start(next: { giftOptions in
|
||||||
let premiumOptions = giftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
let premiumOptions = giftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
||||||
let controller = context.sharedContext.makeGiftOptionsController(context: context, peerId: peerId, premiumOptions: premiumOptions)
|
let controller = context.sharedContext.makeGiftOptionsController(context: context, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: false)
|
||||||
self.push(controller)
|
self.push(controller)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ public final class LoadingOverlayNode: ASDisplayNode {
|
|||||||
let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil))
|
let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil))
|
||||||
let timestamp1: Int32 = 100000
|
let timestamp1: Int32 = 100000
|
||||||
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
let peers: [EnginePeer.Id: EnginePeer] = [:]
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: context.animationCache, animationRenderer: context.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: context.animationCache, animationRenderer: context.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {}, openBirthdaySetup: {}, performActiveSessionAction: { _, _ in }, openChatFolderUpdates: {}, hideChatFolderUpdates: {}, openStories: { _, _ in }, openStarsTopup: { _ in
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: { _, _ in }, openPremiumManagement: {}, openActiveSessions: {}, openBirthdaySetup: {}, performActiveSessionAction: { _, _ in }, openChatFolderUpdates: {}, hideChatFolderUpdates: {}, openStories: { _, _ in }, openStarsTopup: { _ in
|
||||||
@ -452,7 +452,7 @@ private final class PeerInfoScreenPersonalChannelItemNode: PeerInfoScreenItemNod
|
|||||||
animationRenderer: item.context.animationRenderer,
|
animationRenderer: item.context.animationRenderer,
|
||||||
activateSearch: {
|
activateSearch: {
|
||||||
},
|
},
|
||||||
peerSelected: { _, _, _, _ in
|
peerSelected: { _, _, _, _, _ in
|
||||||
},
|
},
|
||||||
disabledPeerSelected: { _, _, _ in
|
disabledPeerSelected: { _, _, _ in
|
||||||
},
|
},
|
||||||
|
@ -9907,7 +9907,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
let controller = self.context.sharedContext.makeGiftOptionsController(
|
let controller = self.context.sharedContext.makeGiftOptionsController(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
peerId: self.peerId,
|
peerId: self.peerId,
|
||||||
premiumOptions: premiumOptions
|
premiumOptions: premiumOptions,
|
||||||
|
hasBirthday: false
|
||||||
)
|
)
|
||||||
self.controller?.push(controller)
|
self.controller?.push(controller)
|
||||||
}
|
}
|
||||||
|
@ -1200,7 +1200,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||||||
chatControllerInteraction.toggleMessagesSelection(messageId, selected)
|
chatControllerInteraction.toggleMessagesSelection(messageId, selected)
|
||||||
},
|
},
|
||||||
openUrl: { url, concealed, external, message in
|
openUrl: { url, concealed, external, message in
|
||||||
chatControllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: concealed, external: external, message: message))
|
chatControllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: concealed, external: external, message: message, progress: Promise()))
|
||||||
},
|
},
|
||||||
openInstantPage: { message, data in
|
openInstantPage: { message, data in
|
||||||
chatControllerInteraction.openInstantPage(message, data)
|
chatControllerInteraction.openInstantPage(message, data)
|
||||||
|
@ -130,7 +130,7 @@ final class GreetingMessageListItemComponent: Component {
|
|||||||
animationRenderer: component.context.animationRenderer,
|
animationRenderer: component.context.animationRenderer,
|
||||||
activateSearch: {
|
activateSearch: {
|
||||||
},
|
},
|
||||||
peerSelected: { _, _, _, _ in
|
peerSelected: { _, _, _, _, _ in
|
||||||
},
|
},
|
||||||
disabledPeerSelected: { _, _, _ in
|
disabledPeerSelected: { _, _, _ in
|
||||||
},
|
},
|
||||||
|
@ -119,7 +119,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||||||
animationRenderer: listNode.context.animationRenderer,
|
animationRenderer: listNode.context.animationRenderer,
|
||||||
activateSearch: {
|
activateSearch: {
|
||||||
},
|
},
|
||||||
peerSelected: { [weak listNode] _, _, _, _ in
|
peerSelected: { [weak listNode] _, _, _, _, _ in
|
||||||
guard let listNode, let parentView = listNode.parentView else {
|
guard let listNode, let parentView = listNode.parentView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -860,7 +860,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate
|
|||||||
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
var items: [ChatListItem] = []
|
var items: [ChatListItem] = []
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
|
@ -127,8 +127,13 @@ func openWebAppImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasWebApp = false
|
||||||
|
if case let .user(user) = botPeer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp) {
|
||||||
|
hasWebApp = true
|
||||||
|
}
|
||||||
|
|
||||||
var presentImpl: ((ViewController, Any?) -> Void)?
|
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||||
let params = WebAppParameters(source: .menu, peerId: chatPeer?.id ?? botPeer.id, botId: botPeer.id, botName: botName, botVerified: botVerified, botAddress: botPeer.addressName ?? "", appName: nil, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: fullSize, isFullscreen: isFullscreen, appSettings: appSettings)
|
let params = WebAppParameters(source: .menu, peerId: chatPeer?.id ?? botPeer.id, botId: botPeer.id, botName: botName, botVerified: botVerified, botAddress: botPeer.addressName ?? "", appName: hasWebApp ? "" : nil, url: url, queryId: nil, payload: nil, buttonText: buttonText, keepAliveSignal: nil, forceHasSettings: false, fullSize: fullSize, isFullscreen: isFullscreen, appSettings: appSettings)
|
||||||
|
|
||||||
let controller = standaloneWebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, threadId: threadId, openUrl: { [weak parentController] url, concealed, forceUpdate, commit in
|
let controller = standaloneWebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, threadId: threadId, openUrl: { [weak parentController] url, concealed, forceUpdate, commit in
|
||||||
ChatControllerImpl.botOpenUrl(context: context, peerId: chatPeer?.id ?? botPeer.id, controller: parentController as? ChatControllerImpl, url: url, concealed: concealed, forceUpdate: forceUpdate, present: { c, a in
|
ChatControllerImpl.botOpenUrl(context: context, peerId: chatPeer?.id ?? botPeer.id, controller: parentController as? ChatControllerImpl, url: url, concealed: concealed, forceUpdate: forceUpdate, present: { c, a in
|
||||||
@ -267,8 +272,14 @@ func openWebAppImpl(
|
|||||||
guard let parentController else {
|
guard let parentController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasWebApp = false
|
||||||
|
if case let .user(user) = botPeer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp) {
|
||||||
|
hasWebApp = true
|
||||||
|
}
|
||||||
|
|
||||||
var presentImpl: ((ViewController, Any?) -> Void)?
|
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||||
let params = WebAppParameters(source: .button, peerId: chatPeer?.id ?? botPeer.id, botId: botPeer.id, botName: botName, botVerified: botVerified, botAddress: botPeer.addressName ?? "", appName: nil, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false, fullSize: result.flags.contains(.fullSize), isFullscreen: result.flags.contains(.fullScreen), appSettings: appSettings)
|
let params = WebAppParameters(source: .button, peerId: chatPeer?.id ?? botPeer.id, botId: botPeer.id, botName: botName, botVerified: botVerified, botAddress: botPeer.addressName ?? "", appName: hasWebApp ? "" : nil, url: result.url, queryId: result.queryId, payload: nil, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, forceHasSettings: false, fullSize: result.flags.contains(.fullSize), isFullscreen: result.flags.contains(.fullScreen), appSettings: appSettings)
|
||||||
let controller = standaloneWebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, threadId: threadId, openUrl: { [weak parentController] url, concealed, forceUpdate, commit in
|
let controller = standaloneWebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, threadId: threadId, openUrl: { [weak parentController] url, concealed, forceUpdate, commit in
|
||||||
ChatControllerImpl.botOpenUrl(context: context, peerId: chatPeer?.id ?? botPeer.id, controller: parentController as? ChatControllerImpl, url: url, concealed: concealed, forceUpdate: forceUpdate, present: { c, a in
|
ChatControllerImpl.botOpenUrl(context: context, peerId: chatPeer?.id ?? botPeer.id, controller: parentController as? ChatControllerImpl, url: url, concealed: concealed, forceUpdate: forceUpdate, present: { c, a in
|
||||||
presentImpl?(c, a)
|
presentImpl?(c, a)
|
||||||
|
@ -591,7 +591,7 @@ extension ChatControllerImpl {
|
|||||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let starsContext = context.starsContext {
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let starsContext = context.starsContext {
|
||||||
let premiumGiftOptions = strongSelf.presentationInterfaceState.premiumGiftOptions
|
let premiumGiftOptions = strongSelf.presentationInterfaceState.premiumGiftOptions
|
||||||
if !premiumGiftOptions.isEmpty {
|
if !premiumGiftOptions.isEmpty {
|
||||||
let controller = PremiumGiftAttachmentScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumGiftOptions, completion: { [weak self] in
|
let controller = PremiumGiftAttachmentScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumGiftOptions, hasBirthday: true, completion: { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ extension ListMessageItemInteraction {
|
|||||||
}, toggleMessagesSelection: { messageId, selected in
|
}, toggleMessagesSelection: { messageId, selected in
|
||||||
controllerInteraction.toggleMessagesSelection(messageId, selected)
|
controllerInteraction.toggleMessagesSelection(messageId, selected)
|
||||||
}, openUrl: { url, param1, param2, message in
|
}, openUrl: { url, param1, param2, message in
|
||||||
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: param1, external: param2, message: message))
|
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: param1, external: param2, message: message, progress: Promise()))
|
||||||
}, openInstantPage: { message, data in
|
}, openInstantPage: { message, data in
|
||||||
controllerInteraction.openInstantPage(message, data)
|
controllerInteraction.openInstantPage(message, data)
|
||||||
}, longTap: { action, message in
|
}, longTap: { action, message in
|
||||||
|
@ -917,7 +917,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||||||
if url.hasPrefix("tg://") {
|
if url.hasPrefix("tg://") {
|
||||||
isConcealed = false
|
isConcealed = false
|
||||||
}
|
}
|
||||||
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: isConcealed))
|
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: isConcealed, progress: Promise()))
|
||||||
case .requestMap:
|
case .requestMap:
|
||||||
controllerInteraction.shareCurrentLocation()
|
controllerInteraction.shareCurrentLocation()
|
||||||
case .requestPhone:
|
case .requestPhone:
|
||||||
|
@ -227,7 +227,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, ASScrollViewDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {
|
let interaction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {
|
||||||
}, peerSelected: { _, _, _, _ in
|
}, peerSelected: { _, _, _, _, _ in
|
||||||
}, disabledPeerSelected: { _, _, _ in
|
}, disabledPeerSelected: { _, _, _ in
|
||||||
}, togglePeerSelected: { _, _ in
|
}, togglePeerSelected: { _, _ in
|
||||||
}, togglePeersSelection: { _, _ in
|
}, togglePeersSelection: { _, _ in
|
||||||
|
@ -98,7 +98,7 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
|||||||
animationRenderer: context.animationRenderer,
|
animationRenderer: context.animationRenderer,
|
||||||
activateSearch: {
|
activateSearch: {
|
||||||
},
|
},
|
||||||
peerSelected: { _, _, _, _ in
|
peerSelected: { _, _, _, _, _ in
|
||||||
commandSelected(.shortcut(shortcut), true)
|
commandSelected(.shortcut(shortcut), true)
|
||||||
},
|
},
|
||||||
disabledPeerSelected: { _, _, _ in
|
disabledPeerSelected: { _, _, _ in
|
||||||
|
@ -2336,7 +2336,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
.startStandalone(next: { [weak controller] result, options in
|
.startStandalone(next: { [weak controller] result, options in
|
||||||
if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext {
|
if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext {
|
||||||
let premiumOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
let premiumOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
|
||||||
let giftController = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumOptions)
|
let giftController = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumOptions, hasBirthday: currentBirthdays?[peer.id] != nil)
|
||||||
giftController.navigationPresentation = .modal
|
giftController.navigationPresentation = .modal
|
||||||
controller?.push(giftController)
|
controller?.push(giftController)
|
||||||
}
|
}
|
||||||
@ -2402,11 +2402,11 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption]) -> ViewController {
|
public func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption], hasBirthday: Bool) -> ViewController {
|
||||||
guard let starsContext = context.starsContext else {
|
guard let starsContext = context.starsContext else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
let controller = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peerId, premiumOptions: premiumOptions)
|
let controller = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: hasBirthday)
|
||||||
controller.navigationPresentation = .modal
|
controller.navigationPresentation = .modal
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
@ -645,7 +645,6 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, query: String)
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,39 @@ import Foundation
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
|
||||||
final class FileDownload: NSObject, URLSessionDownloadDelegate {
|
final class FileDownload: NSObject, URLSessionDownloadDelegate {
|
||||||
private let fileSize: Int64?
|
let fileName: String
|
||||||
|
let fileSize: Int64?
|
||||||
|
let isMedia: Bool
|
||||||
|
|
||||||
private var urlSession: URLSession!
|
private var urlSession: URLSession!
|
||||||
private var completion: ((URL?, Error?) -> Void)?
|
private var completion: ((URL?, Error?) -> Void)?
|
||||||
private var progressHandler: ((Double) -> Void)?
|
private var progressHandler: ((Double) -> Void)?
|
||||||
|
private var task: URLSessionDownloadTask!
|
||||||
|
|
||||||
init(from url: URL, fileSize: Int64?, progressHandler: @escaping (Double) -> Void, completion: @escaping (URL?, Error?) -> Void) {
|
private let progressPromise = ValuePromise<Double>(0.0)
|
||||||
self.progressHandler = progressHandler
|
var progressSignal: Signal<Double, NoError> {
|
||||||
|
return self.progressPromise.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from url: URL, fileName: String, fileSize: Int64?, isMedia: Bool, progressHandler: @escaping (Double) -> Void, completion: @escaping (URL?, Error?) -> Void) {
|
||||||
|
self.fileName = fileName
|
||||||
self.fileSize = fileSize
|
self.fileSize = fileSize
|
||||||
|
self.isMedia = isMedia
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
|
self.progressHandler = progressHandler
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
let configuration = URLSessionConfiguration.default
|
let configuration = URLSessionConfiguration.default
|
||||||
urlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
|
self.urlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
|
||||||
|
|
||||||
let downloadTask = self.urlSession.downloadTask(with: url)
|
let downloadTask = self.urlSession.downloadTask(with: url)
|
||||||
downloadTask.resume()
|
downloadTask.resume()
|
||||||
|
self.task = downloadTask
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancel() {
|
||||||
|
self.task.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
||||||
@ -27,17 +42,18 @@ final class FileDownload: NSObject, URLSessionDownloadDelegate {
|
|||||||
if totalBytesExpectedToWrite == -1, let fileSize = self.fileSize {
|
if totalBytesExpectedToWrite == -1, let fileSize = self.fileSize {
|
||||||
totalBytesExpectedToWrite = fileSize
|
totalBytesExpectedToWrite = fileSize
|
||||||
}
|
}
|
||||||
let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
|
let progress = max(0.0, min(1.0, Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)))
|
||||||
progressHandler?(progress)
|
self.progressHandler?(progress)
|
||||||
|
self.progressPromise.set(progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||||
completion?(location, nil)
|
self.completion?(location, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||||
if let error = error {
|
if let error = error {
|
||||||
completion?(nil, error)
|
self.completion?(nil, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ final class FullscreenControlsComponent: Component {
|
|||||||
|
|
||||||
let buttonTitleUpdated = (previousComponent?.hasBack ?? false) != component.hasBack
|
let buttonTitleUpdated = (previousComponent?.hasBack ?? false) != component.hasBack
|
||||||
let animationMultiplier = !component.hasBack ? -1.0 : 1.0
|
let animationMultiplier = !component.hasBack ? -1.0 : 1.0
|
||||||
if buttonTitleUpdated {
|
if buttonTitleUpdated && !self.displayTitle {
|
||||||
isAnimatingTextTransition = true
|
isAnimatingTextTransition = true
|
||||||
|
|
||||||
if let view = self.buttonTitle.view, let snapshotView = view.snapshotView(afterScreenUpdates: false) {
|
if let view = self.buttonTitle.view, let snapshotView = view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
@ -145,6 +145,8 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
public var isContainerPanning: () -> Bool = { return false }
|
public var isContainerPanning: () -> Bool = { return false }
|
||||||
public var isContainerExpanded: () -> Bool = { return false }
|
public var isContainerExpanded: () -> Bool = { return false }
|
||||||
|
|
||||||
|
static var activeDownloads: [FileDownload] = []
|
||||||
|
|
||||||
fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, ASScrollViewDelegate {
|
fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, ASScrollViewDelegate {
|
||||||
private weak var controller: WebAppController?
|
private weak var controller: WebAppController?
|
||||||
|
|
||||||
@ -369,6 +371,9 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
context.fillPath()
|
context.fillPath()
|
||||||
})!
|
})!
|
||||||
strongSelf.placeholderIcon = (image.withRenderingMode(.alwaysTemplate), false)
|
strongSelf.placeholderIcon = (image.withRenderingMode(.alwaysTemplate), false)
|
||||||
|
if let (layout, navigationBarHeight) = strongSelf.validLayout {
|
||||||
|
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -2400,17 +2405,19 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private var fileDownload: FileDownload?
|
fileprivate weak var fileDownloadTooltip: UndoOverlayController?
|
||||||
private weak var fileDownloadTooltip: UndoOverlayController?
|
|
||||||
fileprivate func startDownload(url: String, fileName: String, fileSize: Int64?, isMedia: Bool) {
|
fileprivate func startDownload(url: String, fileName: String, fileSize: Int64?, isMedia: Bool) {
|
||||||
guard let controller = self.controller else {
|
guard let controller = self.controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.webView?.sendEvent(name: "file_download_requested", data: "{status: \"downloading\"}")
|
self.webView?.sendEvent(name: "file_download_requested", data: "{status: \"downloading\"}")
|
||||||
|
|
||||||
self.fileDownload = FileDownload(
|
var removeImpl: (() -> Void)?
|
||||||
|
let fileDownload = FileDownload(
|
||||||
from: URL(string: url)!,
|
from: URL(string: url)!,
|
||||||
|
fileName: fileName,
|
||||||
fileSize: fileSize,
|
fileSize: fileSize,
|
||||||
|
isMedia: isMedia,
|
||||||
progressHandler: { [weak self] progress in
|
progressHandler: { [weak self] progress in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -2432,6 +2439,8 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
},
|
},
|
||||||
completion: { [weak self] resultUrl, _ in
|
completion: { [weak self] resultUrl, _ in
|
||||||
if let resultUrl, let self {
|
if let resultUrl, let self {
|
||||||
|
removeImpl?()
|
||||||
|
|
||||||
let tooltipContent: UndoOverlayContent = .actionSucceeded(title: fileName, text: isMedia ? self.presentationData.strings.WebApp_Download_SavedToPhotos : self.presentationData.strings.WebApp_Download_SavedToFiles, cancel: nil, destructive: false)
|
let tooltipContent: UndoOverlayContent = .actionSucceeded(title: fileName, text: isMedia ? self.presentationData.strings.WebApp_Download_SavedToPhotos : self.presentationData.strings.WebApp_Download_SavedToFiles, cancel: nil, destructive: false)
|
||||||
if isMedia {
|
if isMedia {
|
||||||
let saveToPhotos: (URL, Bool) -> Void = { url, isVideo in
|
let saveToPhotos: (URL, Bool) -> Void = { url, isVideo in
|
||||||
@ -2496,6 +2505,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
WebAppController.activeDownloads.append(fileDownload)
|
||||||
|
|
||||||
|
removeImpl = { [weak fileDownload] in
|
||||||
|
if let fileDownload {
|
||||||
|
WebAppController.activeDownloads.removeAll(where: { $0 === fileDownload })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let text: String
|
let text: String
|
||||||
if let fileSize {
|
if let fileSize {
|
||||||
@ -2514,7 +2530,11 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
),
|
),
|
||||||
elevatedLayout: false,
|
elevatedLayout: false,
|
||||||
position: .top,
|
position: .top,
|
||||||
action: { _ in
|
action: { [weak fileDownload] action in
|
||||||
|
if case .undo = action, let fileDownload {
|
||||||
|
fileDownload.cancel()
|
||||||
|
removeImpl?()
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -2708,8 +2728,6 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
let url = URL(string: "\(scheme)://t.me/\(addressName)\(appName)?startapp&addToHomeScreen")!
|
let url = URL(string: "\(scheme)://t.me/\(addressName)\(appName)?startapp&addToHomeScreen")!
|
||||||
UIApplication.shared.open(url)
|
UIApplication.shared.open(url)
|
||||||
|
|
||||||
controller.dismiss()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3072,18 +3090,55 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
let hasSettings = self.hasSettings
|
let hasSettings = self.hasSettings
|
||||||
|
|
||||||
|
let activeDownload = WebAppController.activeDownloads.first
|
||||||
|
let activeDownloadProgress: Signal<Double?, NoError>
|
||||||
|
if let activeDownload {
|
||||||
|
activeDownloadProgress = activeDownload.progressSignal
|
||||||
|
|> map(Optional.init)
|
||||||
|
|> mapToThrottled { next -> Signal<Double?, NoError> in
|
||||||
|
return .single(next) |> then(.complete() |> delay(0.2, queue: Queue.mainQueue()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
activeDownloadProgress = .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
let items = combineLatest(queue: Queue.mainQueue(),
|
let items = combineLatest(queue: Queue.mainQueue(),
|
||||||
context.engine.messages.attachMenuBots(),
|
context.engine.messages.attachMenuBots() |> take(1),
|
||||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.botId)),
|
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.botId)),
|
||||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.BotCommands(id: self.botId)),
|
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.BotCommands(id: self.botId)),
|
||||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.BotPrivacyPolicyUrl(id: self.botId))
|
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.BotPrivacyPolicyUrl(id: self.botId)),
|
||||||
|
activeDownloadProgress
|
||||||
)
|
)
|
||||||
|> take(1)
|
|> map { [weak self] attachMenuBots, botPeer, botCommands, privacyPolicyUrl, activeDownloadProgress -> ContextController.Items in
|
||||||
|> map { [weak self] attachMenuBots, botPeer, botCommands, privacyPolicyUrl -> ContextController.Items in
|
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
|
|
||||||
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
if let activeDownload, let progress = activeDownloadProgress {
|
||||||
|
let isActive = progress < 1.0 - .ulpOfOne
|
||||||
|
let progressString: String
|
||||||
|
if isActive {
|
||||||
|
if let fileSize = activeDownload.fileSize {
|
||||||
|
let downloadedSize = Int64(Double(fileSize) * progress)
|
||||||
|
progressString = "\(dataSizeString(downloadedSize, formatting: DataSizeStringFormatting(presentationData: presentationData))) / \(dataSizeString(fileSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))"
|
||||||
|
} else {
|
||||||
|
progressString = "\(Int32(progress))%"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
progressString = activeDownload.isMedia ? presentationData.strings.WebApp_Download_SavedToPhotos : presentationData.strings.WebApp_Download_SavedToFiles
|
||||||
|
}
|
||||||
|
items.append(.action(ContextMenuActionItem(text: activeDownload.fileName, textLayout: .secondLineWithValue(progressString), icon: { theme in return isActive ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.primaryColor) : nil }, iconPosition: .right, action: isActive ? { [weak self, weak activeDownload] _, f in
|
||||||
|
f(.default)
|
||||||
|
|
||||||
|
WebAppController.activeDownloads.removeAll(where: { $0 === activeDownload })
|
||||||
|
activeDownload?.cancel()
|
||||||
|
|
||||||
|
if let fileDownloadTooltip = self?.controllerNode.fileDownloadTooltip {
|
||||||
|
fileDownloadTooltip.dismissWithCommitAction()
|
||||||
|
}
|
||||||
|
} : nil)))
|
||||||
|
items.append(.separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
||||||
if hasSettings {
|
if hasSettings {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_Settings, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_Settings, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.contextMenu.primaryColor)
|
||||||
|
@ -76,7 +76,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let closeButton = closeButton.update(
|
let closeButton = closeButton.update(
|
||||||
component: Button(
|
component: Button(
|
||||||
content: AnyComponent(Text(text: "Cancel", font: Font.regular(17.0), color: theme.actionSheet.controlAccentColor)),
|
content: AnyComponent(Text(text: environment.strings.Common_Cancel, font: Font.regular(17.0), color: theme.actionSheet.controlAccentColor)),
|
||||||
action: {
|
action: {
|
||||||
component.dismiss()
|
component.dismiss()
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
|
|
||||||
let title = title.update(
|
let title = title.update(
|
||||||
component: Text(text: "Share Message", font: Font.bold(17.0), color: theme.list.itemPrimaryTextColor),
|
component: Text(text: environment.strings.WebApp_ShareMessage_Title, font: Font.bold(17.0), color: theme.list.itemPrimaryTextColor),
|
||||||
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
@ -105,7 +105,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
return (TelegramTextAttributes.URL, contents)
|
return (TelegramTextAttributes.URL, contents)
|
||||||
})
|
})
|
||||||
|
|
||||||
let amountInfoString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("\(component.botName) mini app suggests you to send this message to a chat you select.", attributes: amountMarkdownAttributes, textAlignment: .natural))
|
let amountInfoString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.WebApp_ShareMessage_Info(component.botName).string, attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||||
let amountFooter = AnyComponent(MultilineTextComponent(
|
let amountFooter = AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(amountInfoString),
|
text: .plain(amountInfoString),
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 0,
|
||||||
@ -192,7 +192,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
theme: theme,
|
theme: theme,
|
||||||
header: AnyComponent(MultilineTextComponent(
|
header: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: "Message Preview".uppercased(),
|
string: environment.strings.WebApp_ShareMessage_PreviewTitle.uppercased(),
|
||||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||||
textColor: theme.list.freeTextColor
|
textColor: theme.list.freeTextColor
|
||||||
)),
|
)),
|
||||||
@ -230,7 +230,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
contentSize.height += amountSection.size.height
|
contentSize.height += amountSection.size.height
|
||||||
contentSize.height += 32.0
|
contentSize.height += 32.0
|
||||||
|
|
||||||
let buttonString: String = "Share With..."
|
let buttonString: String = environment.strings.WebApp_ShareMessage_Share
|
||||||
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||||
|
|
||||||
let button = button.update(
|
let button = button.update(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "11.4",
|
"app": "11.4.1",
|
||||||
"xcode": "16.0",
|
"xcode": "16.0",
|
||||||
"bazel": "7.3.1:981f82a470bad1349322b6f51c9c6ffa0aa291dab1014fac411543c12e661dff",
|
"bazel": "7.3.1:981f82a470bad1349322b6f51c9c6ffa0aa291dab1014fac411543c12e661dff",
|
||||||
"macos": "15.0"
|
"macos": "15.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user