mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-08 19:10:53 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
8d5c656280
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
||||
include Utils.makefile
|
||||
|
||||
BUCK_OPTIONS=\
|
||||
--config custom.appVersion="5.13" \
|
||||
--config custom.appVersion="5.13.1" \
|
||||
--config custom.developmentCodeSignIdentity="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \
|
||||
--config custom.distributionCodeSignIdentity="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \
|
||||
--config custom.developmentTeam="${DEVELOPMENT_TEAM}" \
|
||||
|
@ -5132,6 +5132,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"IntentsSettings.SuggestedChatsPrivateChats" = "Private Chats";
|
||||
"IntentsSettings.SuggestedChatsGroups" = "Groups";
|
||||
"IntentsSettings.SuggestedChatsInfo" = "Archived chats will not be suggested.";
|
||||
"IntentsSettings.SuggestedAndSpotlightChatsInfo" = "Suggestions will appear in the Share Sheet and Spotlight search results. Archived chats will not be suggested.";
|
||||
"IntentsSettings.SuggestBy" = "Suggest By";
|
||||
"IntentsSettings.SuggestByAll" = "All Sent Messages";
|
||||
"IntentsSettings.SuggestByShare" = "Only Shared Messages";
|
||||
|
@ -16,6 +16,7 @@ public enum PresentationCallState: Equatable {
|
||||
case requesting(Bool)
|
||||
case connecting(Data?)
|
||||
case active(Double, Int32?, Data)
|
||||
case reconnecting(Double, Int32?, Data)
|
||||
case terminating
|
||||
case terminated(CallId?, CallSessionTerminationReason?, Bool)
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
if case .root = groupId, checkProxy {
|
||||
if strongSelf.proxyUnavailableTooltipController == nil && !strongSelf.didShowProxyUnavailableTooltipController && strongSelf.isNodeLoaded && strongSelf.displayNode.view.window != nil {
|
||||
strongSelf.didShowProxyUnavailableTooltipController = true
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.Proxy_TooltipUnavailable), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, timeout: 60.0, dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.Proxy_TooltipUnavailable), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, timeout: 60.0, dismissByTapOutside: true)
|
||||
strongSelf.proxyUnavailableTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.proxyUnavailableTooltipController === tooltipController {
|
||||
@ -789,7 +789,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
if hasPasscode {
|
||||
let _ = ApplicationSpecificNotice.setPasscodeLockTips(accountManager: strongSelf.context.sharedContext.accountManager).start()
|
||||
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.DialogList_PasscodeLockHelp), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.DialogList_PasscodeLockHelp), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceViewAndRect: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
return (strongSelf.titleView, lockViewFrame.offsetBy(dx: 4.0, dy: 14.0))
|
||||
@ -959,7 +959,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
|
||||
public func activateSearch() {
|
||||
if self.displayNavigationBar {
|
||||
let _ = (self.chatListDisplayNode.chatListNode.ready
|
||||
let _ = (self.chatListDisplayNode.chatListNode.contentsReady
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
|
@ -77,7 +77,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
self.groupId = groupId
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.chatListNode = ChatListNode(context: context, groupId: groupId, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
self.chatListNode = ChatListNode(context: context, groupId: groupId, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
|
||||
self.controller = controller
|
||||
|
||||
@ -151,7 +151,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
self.searchDisplayController?.updatePresentationData(presentationData)
|
||||
self.chatListEmptyNode?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
||||
|
||||
|
@ -637,7 +637,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
|
||||
self.recentListNode = ListView()
|
||||
self.recentListNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
@ -1142,7 +1142,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if let strongSelf = self {
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
||||
|
||||
if previousTheme !== presentationData.theme {
|
||||
strongSelf.updateTheme(theme: presentationData.theme)
|
||||
|
@ -311,6 +311,12 @@ public final class ChatListNode: ListView {
|
||||
return _ready.get()
|
||||
}
|
||||
|
||||
private let _contentsReady = ValuePromise<Bool>()
|
||||
private var didSetContentsReady = false
|
||||
public var contentsReady: Signal<Bool, NoError> {
|
||||
return _contentsReady.get()
|
||||
}
|
||||
|
||||
public var peerSelected: ((PeerId, Bool, Bool) -> Void)?
|
||||
public var groupSelected: ((PeerGroupId) -> Void)?
|
||||
public var addContact: ((String) -> Void)?
|
||||
@ -1158,6 +1164,10 @@ public final class ChatListNode: ListView {
|
||||
strongSelf.didSetReady = true
|
||||
strongSelf._ready.set(true)
|
||||
}
|
||||
if !strongSelf.didSetContentsReady {
|
||||
strongSelf.didSetContentsReady = true
|
||||
strongSelf._contentsReady.set(true)
|
||||
}
|
||||
|
||||
var isEmpty = false
|
||||
if transition.chatListView.filteredEntries.isEmpty {
|
||||
|
@ -26,7 +26,7 @@ final class ContextActionNode: ASDisplayNode {
|
||||
self.getController = getController
|
||||
self.actionSelected = actionSelected
|
||||
|
||||
let textFont = Font.regular(presentationData.fontSize.baseDisplaySize)
|
||||
let textFont = Font.regular(presentationData.listsFontSize.baseDisplaySize)
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isAccessibilityElement = false
|
||||
@ -161,7 +161,7 @@ final class ContextActionNode: ASDisplayNode {
|
||||
textColor = presentationData.theme.contextMenu.destructiveColor
|
||||
}
|
||||
|
||||
let textFont = Font.regular(presentationData.fontSize.baseDisplaySize)
|
||||
let textFont = Font.regular(presentationData.listsFontSize.baseDisplaySize)
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.action.text, font: textFont, textColor: textColor)
|
||||
|
||||
|
@ -326,7 +326,7 @@ private final class InnerTextSelectionTipContainerNode: ASDisplayNode {
|
||||
let standardIconWidth: CGFloat = 32.0
|
||||
let iconSideInset: CGFloat = 12.0
|
||||
|
||||
let textFont = Font.regular(floor(presentationData.fontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
let textFont = Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
|
||||
let iconSize = self.iconNode.image?.size ?? CGSize(width: 16.0, height: 16.0)
|
||||
|
||||
|
@ -39,7 +39,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
||||
self.title = query
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
|
||||
let location: SearchMessagesLocation = .general
|
||||
let search = searchMessages(account: context.account, location: location, query: query, state: nil)
|
||||
|
@ -28,7 +28,7 @@ final class InstantPageAnchorItem: InstantPageItem {
|
||||
func drawInTile(context: CGContext) {
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ final class InstantPageArticleItem: InstantPageItem {
|
||||
self.rtl = rtl
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageArticleNode(context: context, item: self, webPage: self.webPage, strings: strings, theme: theme, contentItems: self.contentItems, contentSize: self.contentSize, cover: self.cover, url: self.url, webpageId: self.webpageId, rtl: self.rtl, openUrl: openUrl)
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ final class InstantPageAudioItem: InstantPageItem {
|
||||
self.medias = [media]
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageAudioNode(context: context, strings: strings, theme: theme, webPage: self.webpage, media: self.media, openMedia: openMedia)
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ final class InstantPageContentNode : ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
private let strings: PresentationStrings
|
||||
private let nameDisplayOrder: PresentationPersonNameOrder
|
||||
private let sourcePeerType: MediaAutoDownloadPeerType
|
||||
private let theme: InstantPageTheme
|
||||
|
||||
private let openMedia: (InstantPageMedia) -> Void
|
||||
@ -40,10 +41,11 @@ final class InstantPageContentNode : ASDisplayNode {
|
||||
|
||||
private var previousVisibleBounds: CGRect?
|
||||
|
||||
init(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, items: [InstantPageItem], contentSize: CGSize, inOverlayPanel: Bool = false, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void) {
|
||||
init(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, items: [InstantPageItem], contentSize: CGSize, inOverlayPanel: Bool = false, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.sourcePeerType = sourcePeerType
|
||||
self.theme = theme
|
||||
|
||||
self.openMedia = openMedia
|
||||
@ -187,7 +189,7 @@ final class InstantPageContentNode : ASDisplayNode {
|
||||
if itemNode == nil {
|
||||
let itemIndex = itemIndex
|
||||
let detailsIndex = detailsIndex
|
||||
if let newNode = item.node(context: self.context, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, theme: theme, openMedia: { [weak self] media in
|
||||
if let newNode = item.node(context: self.context, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, theme: theme, sourcePeerType: self.sourcePeerType, openMedia: { [weak self] media in
|
||||
self?.openMedia(media)
|
||||
}, longPressMedia: { [weak self] media in
|
||||
self?.longPressMedia(media)
|
||||
|
@ -541,7 +541,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
let itemIndex = itemIndex
|
||||
let embedIndex = embedIndex
|
||||
let detailsIndex = detailsIndex
|
||||
if let newNode = item.node(context: self.context, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, theme: theme, openMedia: { [weak self] media in
|
||||
if let newNode = item.node(context: self.context, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, theme: theme, sourcePeerType: self.sourcePeerType, openMedia: { [weak self] media in
|
||||
self?.openMedia(media)
|
||||
}, longPressMedia: { [weak self] media in
|
||||
self?.longPressMedia(media)
|
||||
@ -1051,7 +1051,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
let controller = InstantPageReferenceController(context: self.context, theme: theme, webPage: webPage, anchorText: anchorText, openUrl: { [weak self] url in
|
||||
let controller = InstantPageReferenceController(context: self.context, sourcePeerType: self.sourcePeerType, theme: theme, webPage: webPage, anchorText: anchorText, openUrl: { [weak self] url in
|
||||
self?.openUrl(url)
|
||||
}, openUrlIn: { [weak self] url in
|
||||
self?.openUrlIn(url)
|
||||
|
@ -34,12 +34,12 @@ final class InstantPageDetailsItem: InstantPageItem {
|
||||
self.index = index
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
var expanded: Bool?
|
||||
if let expandedDetails = currentExpandedDetails, let currentlyExpanded = expandedDetails[self.index] {
|
||||
expanded = currentlyExpanded
|
||||
}
|
||||
return InstantPageDetailsNode(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, item: self, openMedia: openMedia, longPressMedia: longPressMedia, openPeer: openPeer, openUrl: openUrl, currentlyExpanded: expanded, updateDetailsExpanded: updateDetailsExpanded)
|
||||
return InstantPageDetailsNode(context: context, sourcePeerType: sourcePeerType, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, item: self, openMedia: openMedia, longPressMedia: longPressMedia, openPeer: openPeer, openUrl: openUrl, currentlyExpanded: expanded, updateDetailsExpanded: updateDetailsExpanded)
|
||||
}
|
||||
|
||||
func matchesAnchor(_ anchor: String) -> Bool {
|
||||
|
@ -36,7 +36,7 @@ final class InstantPageDetailsNode: ASDisplayNode, InstantPageNode {
|
||||
|
||||
var requestLayoutUpdate: ((Bool) -> Void)?
|
||||
|
||||
init(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, item: InstantPageDetailsItem, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, currentlyExpanded: Bool?, updateDetailsExpanded: @escaping (Bool) -> Void) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, item: InstantPageDetailsItem, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, currentlyExpanded: Bool?, updateDetailsExpanded: @escaping (Bool) -> Void) {
|
||||
self.context = context
|
||||
self.strings = strings
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
@ -66,7 +66,7 @@ final class InstantPageDetailsNode: ASDisplayNode, InstantPageNode {
|
||||
self.arrowNode = InstantPageDetailsArrowNode(color: theme.controlColor, open: self.expanded)
|
||||
self.separatorNode = ASDisplayNode()
|
||||
|
||||
self.contentNode = InstantPageContentNode(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, items: item.items, contentSize: CGSize(width: item.frame.width, height: item.frame.height - item.titleHeight), openMedia: openMedia, longPressMedia: longPressMedia, openPeer: openPeer, openUrl: openUrl)
|
||||
self.contentNode = InstantPageContentNode(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, sourcePeerType: sourcePeerType, theme: theme, items: item.items, contentSize: CGSize(width: item.frame.width, height: item.frame.height - item.titleHeight), openMedia: openMedia, longPressMedia: longPressMedia, openPeer: openPeer, openUrl: openUrl)
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -21,7 +21,7 @@ final class InstantPageFeedbackItem: InstantPageItem {
|
||||
self.webPage = webPage
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageFeedbackNode(context: context, strings: strings, theme: theme, webPage: self.webPage, openUrl: openUrl)
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,8 @@ final class InstantPageImageItem: InstantPageItem {
|
||||
self.fit = fit
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageImageNode(context: context, theme: theme, webPage: self.webPage, media: self.media, attributes: self.attributes, interactive: self.interactive, roundCorners: self.roundCorners, fit: self.fit, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageImageNode(context: context, sourcePeerType: sourcePeerType, theme: theme, webPage: self.webPage, media: self.media, attributes: self.attributes, interactive: self.interactive, roundCorners: self.roundCorners, fit: self.fit, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
}
|
||||
|
||||
func matchesAnchor(_ anchor: String) -> Bool {
|
||||
|
@ -14,6 +14,7 @@ import MediaResources
|
||||
import LocationResources
|
||||
import LiveLocationPositionNode
|
||||
import AppBundle
|
||||
import TelegramUIPreferences
|
||||
|
||||
private struct FetchControls {
|
||||
let fetch: (Bool) -> Void
|
||||
@ -47,7 +48,7 @@ final class InstantPageImageNode: ASDisplayNode, InstantPageNode {
|
||||
|
||||
private var themeUpdated: Bool = false
|
||||
|
||||
init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, media: InstantPageMedia, attributes: [InstantPageImageAttribute], interactive: Bool, roundCorners: Bool, fit: Bool, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, webPage: TelegramMediaWebpage, media: InstantPageMedia, attributes: [InstantPageImageAttribute], interactive: Bool, roundCorners: Bool, fit: Bool, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.webPage = webPage
|
||||
@ -72,7 +73,9 @@ final class InstantPageImageNode: ASDisplayNode, InstantPageNode {
|
||||
let imageReference = ImageMediaReference.webPage(webPage: WebpageReference(webPage), media: image)
|
||||
self.imageNode.setSignal(chatMessagePhoto(postbox: context.account.postbox, photoReference: imageReference))
|
||||
|
||||
self.fetchedDisposable.set(chatMessagePhotoInteractiveFetched(context: context, photoReference: imageReference, storeToDownloadsPeerType: nil).start())
|
||||
if !interactive || shouldDownloadMediaAutomatically(settings: context.sharedContext.currentAutomaticMediaDownloadSettings.with { $0 }, peerType: sourcePeerType, networkType: MediaAutoDownloadNetworkType(context.account.immediateNetworkType), authorPeerId: nil, contactsPeerIds: Set(), media: image) {
|
||||
self.fetchedDisposable.set(chatMessagePhotoInteractiveFetched(context: context, photoReference: imageReference, storeToDownloadsPeerType: nil).start())
|
||||
}
|
||||
|
||||
self.fetchControls = FetchControls(fetch: { [weak self] manual in
|
||||
if let strongSelf = self {
|
||||
@ -102,7 +105,9 @@ final class InstantPageImageNode: ASDisplayNode, InstantPageNode {
|
||||
} else if let file = media.media as? TelegramMediaFile {
|
||||
let fileReference = FileMediaReference.webPage(webPage: WebpageReference(webPage), media: file)
|
||||
if file.mimeType.hasPrefix("image/") {
|
||||
_ = freeMediaFileInteractiveFetched(account: context.account, fileReference: fileReference).start()
|
||||
if !interactive || shouldDownloadMediaAutomatically(settings: context.sharedContext.currentAutomaticMediaDownloadSettings.with { $0 }, peerType: sourcePeerType, networkType: MediaAutoDownloadNetworkType(context.account.immediateNetworkType), authorPeerId: nil, contactsPeerIds: Set(), media: file) {
|
||||
_ = freeMediaFileInteractiveFetched(account: context.account, fileReference: fileReference).start()
|
||||
}
|
||||
self.imageNode.setSignal(instantPageImageFile(account: context.account, fileReference: fileReference, fetched: true))
|
||||
} else {
|
||||
self.imageNode.setSignal(chatMessageVideo(postbox: context.account.postbox, videoReference: fileReference))
|
||||
|
@ -16,7 +16,7 @@ protocol InstantPageItem {
|
||||
|
||||
func matchesAnchor(_ anchor: String) -> Bool
|
||||
func drawInTile(context: CGContext)
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)?
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)?
|
||||
func matchesNode(_ node: InstantPageNode) -> Bool
|
||||
func linkSelectionRects(at point: CGPoint) -> [CGRect]
|
||||
|
||||
|
@ -27,7 +27,7 @@ final class InstantPagePeerReferenceItem: InstantPageItem {
|
||||
self.rtl = rtl
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPagePeerReferenceNode(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, initialPeer: self.initialPeer, safeInset: self.safeInset, transparent: self.transparent, rtl: self.rtl, openPeer: openPeer)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ final class InstantPagePlayableVideoItem: InstantPageItem {
|
||||
self.interactive = interactive
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPagePlayableVideoNode(context: context, webPage: self.webPage, theme: theme, media: self.media, interactive: self.interactive, openMedia: openMedia)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import TelegramCore
|
||||
import SyncCore
|
||||
import SwiftSignalKit
|
||||
import AccountContext
|
||||
import TelegramUIPreferences
|
||||
|
||||
final class InstantPageReferenceController: ViewController {
|
||||
private var controllerNode: InstantPageReferenceControllerNode {
|
||||
@ -16,6 +17,7 @@ final class InstantPageReferenceController: ViewController {
|
||||
private var animatedIn = false
|
||||
|
||||
private let context: AccountContext
|
||||
private let sourcePeerType: MediaAutoDownloadPeerType
|
||||
private let theme: InstantPageTheme
|
||||
private let webPage: TelegramMediaWebpage
|
||||
private let anchorText: NSAttributedString
|
||||
@ -23,8 +25,9 @@ final class InstantPageReferenceController: ViewController {
|
||||
private let openUrlIn: (InstantPageUrlItem) -> Void
|
||||
private let present: (ViewController, Any?) -> Void
|
||||
|
||||
init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
self.context = context
|
||||
self.sourcePeerType = sourcePeerType
|
||||
self.theme = theme
|
||||
self.webPage = webPage
|
||||
self.anchorText = anchorText
|
||||
@ -42,7 +45,7 @@ final class InstantPageReferenceController: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = InstantPageReferenceControllerNode(context: self.context, theme: self.theme, webPage: self.webPage, anchorText: self.anchorText, openUrl: self.openUrl, openUrlIn: self.openUrlIn, present: self.present)
|
||||
self.displayNode = InstantPageReferenceControllerNode(context: self.context, sourcePeerType: self.sourcePeerType, theme: self.theme, webPage: self.webPage, anchorText: self.anchorText, openUrl: self.openUrl, openUrlIn: self.openUrlIn, present: self.present)
|
||||
self.controllerNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
@ -10,9 +10,11 @@ import TelegramPresentationData
|
||||
import AccountContext
|
||||
import ShareController
|
||||
import OpenInExternalAppUI
|
||||
import TelegramUIPreferences
|
||||
|
||||
class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private let sourcePeerType: MediaAutoDownloadPeerType
|
||||
private let theme: InstantPageTheme
|
||||
private var presentationData: PresentationData
|
||||
private let webPage: TelegramMediaWebpage
|
||||
@ -38,8 +40,9 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie
|
||||
var dismiss: (() -> Void)?
|
||||
var close: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
self.context = context
|
||||
self.sourcePeerType = sourcePeerType
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.theme = theme
|
||||
self.webPage = webPage
|
||||
@ -202,7 +205,7 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie
|
||||
|
||||
let sideInset: CGFloat = 16.0
|
||||
let (_, items, contentSize) = layoutTextItemWithString(self.anchorText, boundingWidth: width - sideInset * 2.0, offset: CGPoint(x: sideInset, y: sideInset), media: media, webpage: self.webPage)
|
||||
let contentNode = InstantPageContentNode(context: self.context, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, theme: self.theme, items: items, contentSize: CGSize(width: width, height: contentSize.height), inOverlayPanel: true, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in })
|
||||
let contentNode = InstantPageContentNode(context: self.context, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, sourcePeerType: self.sourcePeerType, theme: self.theme, items: items, contentSize: CGSize(width: width, height: contentSize.height), inOverlayPanel: true, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in })
|
||||
transition.updateFrame(node: contentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: titleAreaHeight), size: CGSize(width: width, height: contentSize.height)))
|
||||
self.contentContainerNode.insertSubnode(contentNode, at: 0)
|
||||
self.contentNode = contentNode
|
||||
|
@ -62,7 +62,7 @@ final class InstantPageShapeItem: InstantPageItem {
|
||||
return false
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ final class InstantPageSlideshowItem: InstantPageItem {
|
||||
self.medias = medias
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageSlideshowNode(context: context, theme: theme, webPage: webPage, medias: self.medias, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageSlideshowNode(context: context, sourcePeerType: sourcePeerType, theme: theme, webPage: webPage, medias: self.medias, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
}
|
||||
|
||||
func matchesAnchor(_ anchor: String) -> Bool {
|
||||
|
@ -6,6 +6,7 @@ import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import TelegramUIPreferences
|
||||
|
||||
private final class InstantPageSlideshowItemNode: ASDisplayNode {
|
||||
private var _index: Int?
|
||||
@ -64,6 +65,7 @@ private final class InstantPageSlideshowItemNode: ASDisplayNode {
|
||||
|
||||
private final class InstantPageSlideshowPagerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private let sourcePeerType: MediaAutoDownloadPeerType
|
||||
private let theme: InstantPageTheme
|
||||
private let webPage: TelegramMediaWebpage
|
||||
private let openMedia: (InstantPageMedia) -> Void
|
||||
@ -97,8 +99,9 @@ private final class InstantPageSlideshowPagerNode: ASDisplayNode, UIScrollViewDe
|
||||
}
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, pageGap: CGFloat = 0.0) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, webPage: TelegramMediaWebpage, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, pageGap: CGFloat = 0.0) {
|
||||
self.context = context
|
||||
self.sourcePeerType = sourcePeerType
|
||||
self.theme = theme
|
||||
self.webPage = webPage
|
||||
self.openMedia = openMedia
|
||||
@ -180,7 +183,7 @@ private final class InstantPageSlideshowPagerNode: ASDisplayNode, UIScrollViewDe
|
||||
let media = self.items[index]
|
||||
let contentNode: ASDisplayNode
|
||||
if let _ = media.media as? TelegramMediaImage {
|
||||
contentNode = InstantPageImageNode(context: self.context, theme: self.theme, webPage: self.webPage, media: media, attributes: [], interactive: true, roundCorners: false, fit: false, openMedia: self.openMedia, longPressMedia: self.longPressMedia)
|
||||
contentNode = InstantPageImageNode(context: self.context, sourcePeerType: self.sourcePeerType, theme: self.theme, webPage: self.webPage, media: media, attributes: [], interactive: true, roundCorners: false, fit: false, openMedia: self.openMedia, longPressMedia: self.longPressMedia)
|
||||
} else if let file = media.media as? TelegramMediaFile {
|
||||
contentNode = ASDisplayNode()
|
||||
} else {
|
||||
@ -379,10 +382,10 @@ final class InstantPageSlideshowNode: ASDisplayNode, InstantPageNode {
|
||||
private let pagerNode: InstantPageSlideshowPagerNode
|
||||
private let pageControlNode: PageControlNode
|
||||
|
||||
init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, medias: [InstantPageMedia], openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void) {
|
||||
init(context: AccountContext, sourcePeerType: MediaAutoDownloadPeerType, theme: InstantPageTheme, webPage: TelegramMediaWebpage, medias: [InstantPageMedia], openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void) {
|
||||
self.medias = medias
|
||||
|
||||
self.pagerNode = InstantPageSlideshowPagerNode(context: context, theme: theme, webPage: webPage, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
self.pagerNode = InstantPageSlideshowPagerNode(context: context, sourcePeerType: sourcePeerType, theme: theme, webPage: webPage, openMedia: openMedia, longPressMedia: longPressMedia)
|
||||
self.pagerNode.replaceItems(medias, centralItemIndex: nil)
|
||||
|
||||
self.pageControlNode = PageControlNode(dotColor: .white, inactiveDotColor: UIColor(white: 1.0, alpha: 0.5))
|
||||
|
@ -200,12 +200,12 @@ final class InstantPageTableItem: InstantPageScrollableItem {
|
||||
return false
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
var additionalNodes: [InstantPageNode] = []
|
||||
for cell in self.cells {
|
||||
for item in cell.additionalItems {
|
||||
if item.wantsNode {
|
||||
if let node = item.node(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in}, updateWebEmbedHeight: { _ in }, updateDetailsExpanded: { _ in }, currentExpandedDetails: nil) {
|
||||
if let node = item.node(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, sourcePeerType: sourcePeerType, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in}, updateWebEmbedHeight: { _ in }, updateDetailsExpanded: { _ in }, currentExpandedDetails: nil) {
|
||||
node.frame = item.frame.offsetBy(dx: cell.frame.minX, dy: cell.frame.minY)
|
||||
additionalNodes.append(node)
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ final class InstantPageTextItem: InstantPageItem {
|
||||
return false
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -391,11 +391,11 @@ final class InstantPageScrollableTextItem: InstantPageScrollableItem {
|
||||
context.restoreGState()
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
var additionalNodes: [InstantPageNode] = []
|
||||
for item in additionalItems {
|
||||
if item.wantsNode {
|
||||
if let node = item.node(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in}, updateWebEmbedHeight: { _ in }, updateDetailsExpanded: { _ in }, currentExpandedDetails: nil) {
|
||||
if let node = item.node(context: context, strings: strings, nameDisplayOrder: nameDisplayOrder, theme: theme, sourcePeerType: sourcePeerType, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in}, updateWebEmbedHeight: { _ in }, updateDetailsExpanded: { _ in }, currentExpandedDetails: nil) {
|
||||
node.frame = item.frame
|
||||
additionalNodes.append(node)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ final class InstantPageWebEmbedItem: InstantPageItem {
|
||||
self.enableScrolling = enableScrolling
|
||||
}
|
||||
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
func node(context: AccountContext, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, theme: InstantPageTheme, sourcePeerType: MediaAutoDownloadPeerType, openMedia: @escaping (InstantPageMedia) -> Void, longPressMedia: @escaping (InstantPageMedia) -> Void, openPeer: @escaping (PeerId) -> Void, openUrl: @escaping (InstantPageUrlItem) -> Void, updateWebEmbedHeight: @escaping (CGFloat) -> Void, updateDetailsExpanded: @escaping (Bool) -> Void, currentExpandedDetails: [Int : Bool]?) -> (InstantPageNode & ASDisplayNode)? {
|
||||
return InstantPageWebEmbedNode(frame: self.frame, url: self.url, html: self.html, enableScrolling: self.enableScrolling, updateWebEmbedHeight: updateWebEmbedHeight)
|
||||
}
|
||||
|
||||
|
@ -222,6 +222,6 @@ public extension PresentationFontSize {
|
||||
|
||||
public extension ItemListPresentationData {
|
||||
convenience init(_ presentationData: PresentationData) {
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings)
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings)
|
||||
}
|
||||
}
|
||||
|
@ -221,11 +221,11 @@ private final class LanguageSuggestionAlertContentNode: AlertContentNode {
|
||||
let selectedLocalization = ValuePromise(suggestedLocalization.languageCode, ignoreRepeated: true)
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ChooseLanguage, font: Font.bold(presentationData.fontSize.baseDisplaySize), textColor: presentationData.theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ChooseLanguage, font: Font.bold(presentationData.listsFontSize.baseDisplaySize), textColor: presentationData.theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.titleNode.maximumNumberOfLines = 2
|
||||
|
||||
self.subtitleNode = ASTextNode()
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: englishStrings.ChooseLanguage, font: Font.regular(floor(presentationData.fontSize.baseDisplaySize * 14.0 / 17.0)), textColor: presentationData.theme.actionSheet.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: englishStrings.ChooseLanguage, font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 14.0 / 17.0)), textColor: presentationData.theme.actionSheet.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.subtitleNode.maximumNumberOfLines = 2
|
||||
|
||||
self.titleSeparatorNode = ASDisplayNode()
|
||||
|
@ -1279,7 +1279,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
}
|
||||
}
|
||||
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:strongSelf->_hasSilentPosting canSchedule:effectiveHasSchedule reminder:strongSelf->_reminder];
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:strongSelf->_hasSilentPosting canSchedule:effectiveHasSchedule reminder:strongSelf->_reminder];
|
||||
controller.send = ^{
|
||||
__strong TGCameraController *strongSelf = weakSelf;
|
||||
__strong TGMediaPickerGalleryModel *strongModel = weakModel;
|
||||
|
@ -164,7 +164,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSchedule:effectiveHasSchedule reminder:reminder];
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSchedule:effectiveHasSchedule reminder:reminder];
|
||||
controller.send = ^{
|
||||
__strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
|
@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, copy) void (^sendSilently)(void);
|
||||
@property (nonatomic, copy) void (^schedule)(void);
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
TGModernButton *_buttonView;
|
||||
UILabel *_buttonLabel;
|
||||
UIImageView *_buttonIcon;
|
||||
UIView *_separatorView;
|
||||
}
|
||||
|
||||
@property (nonatomic, readonly) UILabel *buttonLabel;
|
||||
@ -20,7 +21,7 @@
|
||||
|
||||
@implementation TGMediaPickerSendActionSheetItemView
|
||||
|
||||
- (instancetype)initWithTitle:(NSString *)title icon:(UIImage *)icon {
|
||||
- (instancetype)initWithTitle:(NSString *)title icon:(UIImage *)icon isDark:(bool)isDark isLast:(bool)isLast {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_buttonView = [[TGModernButton alloc] init];
|
||||
@ -31,9 +32,17 @@
|
||||
__strong TGMediaPickerSendActionSheetItemView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
if (highlighted) {
|
||||
strongSelf->_buttonView.backgroundColor = UIColorRGB(0x363636);
|
||||
if (isDark) {
|
||||
strongSelf->_buttonView.backgroundColor = UIColorRGB(0x363636);
|
||||
} else {
|
||||
strongSelf->_buttonView.backgroundColor = UIColorRGBA(0x3c3c43, 0.2);
|
||||
}
|
||||
} else {
|
||||
strongSelf->_buttonView.backgroundColor = [UIColor clearColor];
|
||||
if (isDark) {
|
||||
strongSelf->_buttonView.backgroundColor = [UIColor clearColor];
|
||||
} else {
|
||||
strongSelf->_buttonView.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -43,15 +52,32 @@
|
||||
_buttonLabel = [[UILabel alloc] init];
|
||||
_buttonLabel.font = TGSystemFontOfSize(17.0f);
|
||||
_buttonLabel.text = title;
|
||||
_buttonLabel.textColor = [UIColor whiteColor];
|
||||
if (isDark) {
|
||||
_buttonLabel.textColor = [UIColor whiteColor];
|
||||
} else {
|
||||
_buttonLabel.textColor = [UIColor blackColor];
|
||||
}
|
||||
[_buttonLabel sizeToFit];
|
||||
_buttonLabel.userInteractionEnabled = false;
|
||||
[self addSubview:_buttonLabel];
|
||||
|
||||
_buttonIcon = [[UIImageView alloc] init];
|
||||
_buttonIcon.image = TGTintedImage(icon, [UIColor whiteColor]);
|
||||
if (isDark) {
|
||||
_buttonIcon.image = TGTintedImage(icon, [UIColor whiteColor]);
|
||||
} else {
|
||||
_buttonIcon.image = TGTintedImage(icon, [UIColor blackColor]);
|
||||
}
|
||||
[_buttonIcon sizeToFit];
|
||||
[self addSubview:_buttonIcon];
|
||||
|
||||
if (!isLast) {
|
||||
_separatorView = [[UIView alloc] init];
|
||||
if (isDark) {
|
||||
} else {
|
||||
_separatorView.backgroundColor = UIColorRGBA(0x3c3c43, 0.2);
|
||||
}
|
||||
[self addSubview:_separatorView];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -65,6 +91,7 @@
|
||||
_buttonLabel.frame = CGRectMake(16.0, 11.0, _buttonLabel.frame.size.width, _buttonLabel.frame.size.height);
|
||||
_buttonView.frame = self.bounds;
|
||||
_buttonIcon.frame = CGRectMake(self.bounds.size.width - _buttonIcon.frame.size.width - 12.0, 9.0, _buttonIcon.frame.size.width, _buttonIcon.frame.size.height);
|
||||
_separatorView.frame = CGRectMake(0.0f, self.bounds.size.height, self.bounds.size.width, 1.0f / [UIScreen mainScreen].scale);
|
||||
}
|
||||
|
||||
@end
|
||||
@ -73,6 +100,7 @@
|
||||
{
|
||||
id<LegacyComponentsContext> _context;
|
||||
|
||||
bool _isDark;
|
||||
CGRect _sendButtonFrame;
|
||||
bool _canSendSilently;
|
||||
bool _canSchedule;
|
||||
@ -92,10 +120,11 @@
|
||||
|
||||
@implementation TGMediaPickerSendActionSheetController
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder {
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder {
|
||||
self = [super initWithContext:context];
|
||||
if (self != nil) {
|
||||
_context = context;
|
||||
_isDark = isDark;
|
||||
_sendButtonFrame = sendButtonFrame;
|
||||
_canSendSilently = canSendSilently;
|
||||
_canSchedule = canSchedule;
|
||||
@ -109,19 +138,41 @@
|
||||
|
||||
_effectView = [[UIVisualEffectView alloc] initWithEffect:nil];
|
||||
if (iosMajorVersion() >= 9) {
|
||||
_effectView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
if (_isDark) {
|
||||
_effectView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
} else {
|
||||
_effectView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
|
||||
}
|
||||
}
|
||||
[self.view addSubview:_effectView];
|
||||
|
||||
/*
|
||||
let contextMenu = PresentationThemeContextMenu(
|
||||
dimColor: UIColor(rgb: 0x000a26, alpha: 0.2),
|
||||
backgroundColor: UIColor(rgb: 0xf9f9f9, alpha: 0.78),
|
||||
itemSeparatorColor: UIColor(rgb: 0x3c3c43, alpha: 0.2),
|
||||
sectionSeparatorColor: UIColor(rgb: 0x8a8a8a, alpha: 0.2),
|
||||
itemBackgroundColor: UIColor(rgb: 0x000000, alpha: 0.0),
|
||||
itemHighlightedBackgroundColor: UIColor(rgb: 0x3c3c43, alpha: 0.2),
|
||||
primaryColor: UIColor(rgb: 0x000000, alpha: 1.0),
|
||||
secondaryColor: UIColor(rgb: 0x000000, alpha: 0.8),
|
||||
destructiveColor: UIColor(rgb: 0xff3b30)
|
||||
)
|
||||
*/
|
||||
|
||||
_containerView = [[UIView alloc] init];
|
||||
_containerView.backgroundColor = UIColorRGB(0x1f1f1f);
|
||||
if (_isDark) {
|
||||
_containerView.backgroundColor = UIColorRGB(0x1f1f1f);
|
||||
} else {
|
||||
_containerView.backgroundColor = UIColorRGBA(0xf9f9f9, 0.78);
|
||||
}
|
||||
_containerView.clipsToBounds = true;
|
||||
_containerView.layer.cornerRadius = 12.0;
|
||||
[self.view addSubview:_containerView];
|
||||
|
||||
__weak TGMediaPickerSendActionSheetController *weakSelf = self;
|
||||
if (_canSendSilently) {
|
||||
_sendSilentlyButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.SendSilently") icon:TGComponentsImageNamed(@"MediaMute")];
|
||||
_sendSilentlyButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.SendSilently") icon:TGComponentsImageNamed(@"MediaMute") isDark:_isDark isLast:!_canSchedule];
|
||||
_sendSilentlyButton.pressed = ^{
|
||||
__strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf;
|
||||
[strongSelf sendSilentlyPressed];
|
||||
@ -130,7 +181,7 @@
|
||||
}
|
||||
|
||||
if (_canSchedule) {
|
||||
_scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(_reminder ? @"Conversation.SendMessage.SetReminder" : @"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"MediaSchedule")];
|
||||
_scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(_reminder ? @"Conversation.SendMessage.SetReminder" : @"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"MediaSchedule") isDark:_isDark isLast:true];
|
||||
_scheduleButton.pressed = ^{
|
||||
__strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf;
|
||||
[strongSelf schedulePressed];
|
||||
|
@ -19,14 +19,15 @@
|
||||
|
||||
@property (nonatomic, copy) id (^requestActivityHolder)();
|
||||
@property (nonatomic, copy) void (^micLevel)(CGFloat level);
|
||||
@property (nonatomic, copy) void(^finishedWithVideo)(NSURL *videoURL, UIImage *previewImage, NSUInteger fileSize, NSTimeInterval duration, CGSize dimensions, id liveUploadData, TGVideoEditAdjustments *adjustments);
|
||||
@property (nonatomic, copy) void(^finishedWithVideo)(NSURL *videoURL, UIImage *previewImage, NSUInteger fileSize, NSTimeInterval duration, CGSize dimensions, id liveUploadData, TGVideoEditAdjustments *adjustments, bool, int32_t);
|
||||
@property (nonatomic, copy) void(^onDismiss)(bool isAuto);
|
||||
@property (nonatomic, copy) void(^onStop)(void);
|
||||
@property (nonatomic, copy) void(^onCancel)(void);
|
||||
@property (nonatomic, copy) void(^didDismiss)(void);
|
||||
@property (nonatomic, copy) void(^displaySlowmodeTooltip)(void);
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(void (^)(int32_t));
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context assets:(TGVideoMessageCaptureControllerAssets *)assets transitionInView:(UIView *(^)(void))transitionInView parentController:(TGViewController *)parentController controlsFrame:(CGRect)controlsFrame isAlreadyLocked:(bool (^)(void))isAlreadyLocked liveUploadInterface:(id<TGLiveUploadInterface>)liveUploadInterface pallete:(TGModernConversationInputMicPallete *)pallete slowmodeTimestamp:(int32_t)slowmodeTimestamp slowmodeView:(UIView *(^)(void))slowmodeView;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context assets:(TGVideoMessageCaptureControllerAssets *)assets transitionInView:(UIView *(^)(void))transitionInView parentController:(TGViewController *)parentController controlsFrame:(CGRect)controlsFrame isAlreadyLocked:(bool (^)(void))isAlreadyLocked liveUploadInterface:(id<TGLiveUploadInterface>)liveUploadInterface pallete:(TGModernConversationInputMicPallete *)pallete slowmodeTimestamp:(int32_t)slowmodeTimestamp slowmodeView:(UIView *(^)(void))slowmodeView canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder;
|
||||
|
||||
- (void)buttonInteractionUpdate:(CGPoint)value;
|
||||
- (void)setLocked;
|
||||
|
@ -27,6 +27,9 @@
|
||||
#import "TGColor.h"
|
||||
#import "TGImageUtils.h"
|
||||
|
||||
#import "TGMediaPickerSendActionSheetController.h"
|
||||
#import "TGOverlayControllerWindow.h"
|
||||
|
||||
const NSTimeInterval TGVideoMessageMaximumDuration = 60.0;
|
||||
|
||||
typedef enum
|
||||
@ -129,6 +132,10 @@ typedef enum
|
||||
UIView * (^_slowmodeView)(void);
|
||||
|
||||
TGVideoMessageCaptureControllerAssets *_assets;
|
||||
|
||||
bool _canSendSilently;
|
||||
bool _canSchedule;
|
||||
bool _reminder;
|
||||
}
|
||||
|
||||
@property (nonatomic, copy) bool(^isAlreadyLocked)(void);
|
||||
@ -137,7 +144,7 @@ typedef enum
|
||||
|
||||
@implementation TGVideoMessageCaptureController
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context assets:(TGVideoMessageCaptureControllerAssets *)assets transitionInView:(UIView *(^)(void))transitionInView parentController:(TGViewController *)parentController controlsFrame:(CGRect)controlsFrame isAlreadyLocked:(bool (^)(void))isAlreadyLocked liveUploadInterface:(id<TGLiveUploadInterface>)liveUploadInterface pallete:(TGModernConversationInputMicPallete *)pallete slowmodeTimestamp:(int32_t)slowmodeTimestamp slowmodeView:(UIView *(^)(void))slowmodeView
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context assets:(TGVideoMessageCaptureControllerAssets *)assets transitionInView:(UIView *(^)(void))transitionInView parentController:(TGViewController *)parentController controlsFrame:(CGRect)controlsFrame isAlreadyLocked:(bool (^)(void))isAlreadyLocked liveUploadInterface:(id<TGLiveUploadInterface>)liveUploadInterface pallete:(TGModernConversationInputMicPallete *)pallete slowmodeTimestamp:(int32_t)slowmodeTimestamp slowmodeView:(UIView *(^)(void))slowmodeView canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder
|
||||
{
|
||||
self = [super initWithContext:context];
|
||||
if (self != nil)
|
||||
@ -148,6 +155,9 @@ typedef enum
|
||||
_liveUploadInterface = liveUploadInterface;
|
||||
_assets = assets;
|
||||
_pallete = pallete;
|
||||
_canSendSilently = canSendSilently;
|
||||
_canSchedule = canSchedule;
|
||||
_reminder = reminder;
|
||||
_slowmodeTimestamp = slowmodeTimestamp;
|
||||
_slowmodeView = [slowmodeView copy];
|
||||
|
||||
@ -367,6 +377,13 @@ typedef enum
|
||||
return false;
|
||||
}
|
||||
};
|
||||
_controlsView.sendLongPressed = ^bool{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
[strongSelf sendLongPressed];
|
||||
}
|
||||
return true;
|
||||
};
|
||||
[self.view addSubview:_controlsView];
|
||||
|
||||
_separatorView = [[UIView alloc] initWithFrame:CGRectMake(controlsFrame.origin.x, controlsFrame.origin.y - TGScreenPixel, controlsFrame.size.width, TGScreenPixel)];
|
||||
@ -681,13 +698,70 @@ typedef enum
|
||||
}
|
||||
}
|
||||
|
||||
[self finishWithURL:_url dimensions:CGSizeMake(240.0f, 240.0f) duration:_duration liveUploadData:_liveUploadData thumbnailImage:_thumbnailImage];
|
||||
[self finishWithURL:_url dimensions:CGSizeMake(240.0f, 240.0f) duration:_duration liveUploadData:_liveUploadData thumbnailImage:_thumbnailImage isSilent:false scheduleTimestamp:0];
|
||||
|
||||
_automaticDismiss = true;
|
||||
[self dismiss:false];
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)sendLongPressed {
|
||||
if (iosMajorVersion() >= 10) {
|
||||
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
|
||||
[generator impactOccurred];
|
||||
}
|
||||
|
||||
bool effectiveHasSchedule = true;
|
||||
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:_context isDark:self.pallete.isDark sendButtonFrame:[_controlsView convertRect:[_controlsView frameForSendButton] toView:nil] canSendSilently:_canSendSilently canSchedule:_canSchedule reminder:_reminder];
|
||||
__weak TGVideoMessageCaptureController *weakSelf = self;
|
||||
controller.send = ^{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf finishWithURL:strongSelf->_url dimensions:CGSizeMake(240.0f, 240.0f) duration:strongSelf->_duration liveUploadData:strongSelf->_liveUploadData thumbnailImage:strongSelf->_thumbnailImage isSilent:false scheduleTimestamp:0];
|
||||
|
||||
_automaticDismiss = true;
|
||||
[strongSelf dismiss:false];
|
||||
};
|
||||
controller.sendSilently = ^{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf finishWithURL:strongSelf->_url dimensions:CGSizeMake(240.0f, 240.0f) duration:strongSelf->_duration liveUploadData:strongSelf->_liveUploadData thumbnailImage:strongSelf->_thumbnailImage isSilent:true scheduleTimestamp:0];
|
||||
|
||||
_automaticDismiss = true;
|
||||
[strongSelf dismiss:false];
|
||||
};
|
||||
controller.schedule = ^{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strongSelf.presentScheduleController) {
|
||||
strongSelf.presentScheduleController(^(int32_t time) {
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf finishWithURL:strongSelf->_url dimensions:CGSizeMake(240.0f, 240.0f) duration:strongSelf->_duration liveUploadData:strongSelf->_liveUploadData thumbnailImage:strongSelf->_thumbnailImage isSilent:false scheduleTimestamp:time];
|
||||
|
||||
_automaticDismiss = true;
|
||||
[strongSelf dismiss:false];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithManager:[_context makeOverlayWindowManager] parentController:self contentController:controller];
|
||||
controllerWindow.hidden = false;
|
||||
}
|
||||
|
||||
- (void)unmutePressed
|
||||
{
|
||||
[self _updateMuted:false];
|
||||
@ -867,7 +941,7 @@ typedef enum
|
||||
[_buttonHandler ignoreEventsFor:1.0f andDisable:true];
|
||||
}
|
||||
|
||||
- (void)finishWithURL:(NSURL *)url dimensions:(CGSize)dimensions duration:(NSTimeInterval)duration liveUploadData:(id )liveUploadData thumbnailImage:(UIImage *)thumbnailImage
|
||||
- (void)finishWithURL:(NSURL *)url dimensions:(CGSize)dimensions duration:(NSTimeInterval)duration liveUploadData:(id )liveUploadData thumbnailImage:(UIImage *)thumbnailImage isSilent:(bool)isSilent scheduleTimestamp:(int32_t)scheduleTimestamp
|
||||
{
|
||||
if (duration < 1.0)
|
||||
_dismissed = true;
|
||||
@ -923,7 +997,7 @@ typedef enum
|
||||
}
|
||||
|
||||
if (!_dismissed && self.finishedWithVideo != nil)
|
||||
self.finishedWithVideo(url, image, fileSize, duration, dimensions, liveUploadData, adjustments);
|
||||
self.finishedWithVideo(url, image, fileSize, duration, dimensions, liveUploadData, adjustments, isSilent, scheduleTimestamp);
|
||||
else
|
||||
[[NSFileManager defaultManager] removeItemAtURL:url error:NULL];
|
||||
}
|
||||
@ -1125,7 +1199,7 @@ typedef enum
|
||||
}
|
||||
else
|
||||
{
|
||||
[self finishWithURL:_url dimensions:CGSizeMake(240.0f, 240.0f) duration:duration liveUploadData:liveUploadData thumbnailImage:thumbnailImage];
|
||||
[self finishWithURL:_url dimensions:CGSizeMake(240.0f, 240.0f) duration:duration liveUploadData:liveUploadData thumbnailImage:thumbnailImage isSilent:false scheduleTimestamp:0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
@property (nonatomic, copy) void (^cancel)(void);
|
||||
@property (nonatomic, copy) void (^deletePressed)(void);
|
||||
@property (nonatomic, copy) bool (^sendPressed)(void);
|
||||
@property (nonatomic, copy) bool (^sendLongPressed)(void);
|
||||
|
||||
@property (nonatomic, copy) bool(^isAlreadyLocked)(void);
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#import <LegacyComponents/LegacyComponents.h>
|
||||
|
||||
#import <LegacyComponents/TGModernButton.h>
|
||||
//#import "TGModernConversationInputMicButton.h"
|
||||
#import <LegacyComponents/TGVideoMessageScrubber.h>
|
||||
#import <SSignalKit/SSignalKit.h>
|
||||
|
||||
@ -41,6 +40,7 @@ static CGRect viewFrame(UIView *view)
|
||||
|
||||
TGModernButton *_deleteButton;
|
||||
TGModernButton *_sendButton;
|
||||
UILongPressGestureRecognizer *_longPressGestureRecognizer;
|
||||
|
||||
int32_t _slowmodeTimestamp;
|
||||
UIView * (^_generateSlowmodeView)(void);
|
||||
@ -373,6 +373,11 @@ static CGRect viewFrame(UIView *view)
|
||||
[_sendButton setImage:_assets.sendImage forState:UIControlStateNormal];
|
||||
_sendButton.adjustsImageWhenHighlighted = false;
|
||||
[_sendButton addTarget:self action:@selector(sendButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(doneButtonLongPressed:)];
|
||||
_longPressGestureRecognizer.minimumPressDuration = 0.4;
|
||||
[_sendButton addGestureRecognizer:_longPressGestureRecognizer];
|
||||
|
||||
[self addSubview:_sendButton];
|
||||
|
||||
if (_slowmodeTimestamp != 0) {
|
||||
@ -487,7 +492,16 @@ static CGRect viewFrame(UIView *view)
|
||||
_sendButton.userInteractionEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)doneButtonLongPressed:(UILongPressGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
if (self.sendLongPressed != nil) {
|
||||
self.sendLongPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelPressed
|
||||
|
@ -218,7 +218,6 @@ final class LocationActionListItemNode: ListViewItemNode {
|
||||
let iconLayout = self.venueIconNode.asyncLayout()
|
||||
|
||||
return { [weak self] item, params, hasSeparator in
|
||||
|
||||
let leftInset: CGFloat = 65.0 + params.leftInset
|
||||
let rightInset: CGFloat = params.rightInset
|
||||
let verticalInset: CGFloat = 8.0
|
||||
|
@ -557,7 +557,7 @@ func channelOwnershipTransferController(context: AccountContext, peer: Peer, mem
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let theme = AlertControllerTheme(presentationData: presentationData)
|
||||
|
||||
var title: NSAttributedString? = NSAttributedString(string: presentationData.strings.OwnershipTransfer_SecurityCheck, font: Font.medium(presentationData.fontSize.itemListBaseFontSize), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
var title: NSAttributedString? = NSAttributedString(string: presentationData.strings.OwnershipTransfer_SecurityCheck, font: Font.medium(presentationData.listsFontSize.itemListBaseFontSize), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
var text = presentationData.strings.OwnershipTransfer_SecurityRequirements
|
||||
var isGroup = true
|
||||
|
@ -1589,7 +1589,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String = presentationData.strings.UserInfo_TapToCall
|
||||
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true)
|
||||
controller.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak resultItemNode] in
|
||||
if let resultItemNode = resultItemNode {
|
||||
return (resultItemNode, callButtonFrame)
|
||||
|
@ -215,6 +215,17 @@ public final class MediaBox {
|
||||
return ResourceStorePaths(partial: "\(self.basePath)/\(cacheString)/\(fileNameForId(id))_partial:\(representation.uniqueId)", complete: "\(self.basePath)/\(cacheString)/\(fileNameForId(id)):\(representation.uniqueId)")
|
||||
}
|
||||
|
||||
public func cachedRepresentationCompletePath(_ id: MediaResourceId, representation: CachedMediaResourceRepresentation) -> String {
|
||||
let cacheString: String
|
||||
switch representation.keepDuration {
|
||||
case .general:
|
||||
cacheString = "cache"
|
||||
case .shortLived:
|
||||
cacheString = "short-cache"
|
||||
}
|
||||
return "\(self.basePath)/\(cacheString)/\(fileNameForId(id)):\(representation.uniqueId)"
|
||||
}
|
||||
|
||||
public func storeResourceData(_ id: MediaResourceId, data: Data, synchronous: Bool = false) {
|
||||
let begin = {
|
||||
let paths = self.storePathsForId(id)
|
||||
|
@ -148,6 +148,12 @@ public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, E>(queue: Que
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>, _ s8: Signal<T8, E>, _ s9: Signal<T9, E>, _ s10: Signal<T10, E>, _ s11: Signal<T11, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), E> {
|
||||
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7), signalOfAny(s8), signalOfAny(s9), signalOfAny(s10), signalOfAny(s11)], combine: { values in
|
||||
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7, values[7] as! T8, values[8] as! T9, values[9] as! T10, values[10] as! T11)
|
||||
}, initialValues: [:], queue: queue)
|
||||
}
|
||||
|
||||
public func combineLatest<T, E>(queue: Queue? = nil, _ signals: [Signal<T, E>]) -> Signal<[T], E> {
|
||||
if signals.count == 0 {
|
||||
return single([T](), E.self)
|
||||
|
@ -251,7 +251,7 @@ private func intentsSettingsControllerEntries(context: AccountContext, presentat
|
||||
entries.append(.privateChats(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedChatsPrivateChats, settings.privateChats))
|
||||
entries.append(.groups(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedChatsGroups, settings.groups))
|
||||
|
||||
entries.append(.chatsInfo(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedChatsInfo))
|
||||
entries.append(.chatsInfo(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedAndSpotlightChatsInfo))
|
||||
|
||||
entries.append(.suggestHeader(presentationData.theme, presentationData.strings.IntentsSettings_SuggestBy.uppercased()))
|
||||
entries.append(.suggestAll(presentationData.theme, presentationData.strings.IntentsSettings_SuggestByAll, !settings.onlyShared))
|
||||
|
@ -591,7 +591,7 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
|
||||
linkEnabled = false
|
||||
}
|
||||
entries.append(.forwardsPreviewHeader(presentationData.theme, presentationData.strings.Privacy_Forwards_Preview))
|
||||
entries.append(.forwardsPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peerName, linkEnabled, tootipText))
|
||||
entries.append(.forwardsPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peerName, linkEnabled, tootipText))
|
||||
}
|
||||
|
||||
entries.append(.settingHeader(presentationData.theme, settingTitle))
|
||||
|
@ -76,12 +76,14 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
let archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>
|
||||
let privacySettings: Signal<AccountPrivacySettings?, NoError>
|
||||
let hasWallet: Signal<Bool, NoError>
|
||||
let activeSessionsContext: Signal<ActiveSessionsContext?, NoError>
|
||||
let webSessionsContext: Signal<WebSessionsContext?, NoError>
|
||||
|
||||
private var updateActivity: ((Bool) -> Void)?
|
||||
private var activity: ValuePromise<Bool> = ValuePromise(ignoreRepeated: false)
|
||||
private let activityDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>) {
|
||||
init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>, activeSessionsContext: Signal<ActiveSessionsContext?, NoError>, webSessionsContext: Signal<WebSessionsContext?, NoError>) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.placeholder = placeholder
|
||||
@ -94,6 +96,8 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
self.archivedStickerPacks = archivedStickerPacks
|
||||
self.privacySettings = privacySettings
|
||||
self.hasWallet = hasWallet
|
||||
self.activeSessionsContext = activeSessionsContext
|
||||
self.webSessionsContext = webSessionsContext
|
||||
self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal<Bool, NoError> in
|
||||
if value {
|
||||
return .single(value) |> delay(0.2, queue: Queue.mainQueue())
|
||||
@ -157,7 +161,7 @@ final class SettingsSearchItem: ItemListControllerSearch {
|
||||
pushController(c)
|
||||
}, presentController: { c, a in
|
||||
presentController(c, a)
|
||||
}, getNavigationController: self.getNavigationController, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasWallet: self.hasWallet)
|
||||
}, getNavigationController: self.getNavigationController, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasWallet: self.hasWallet, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,7 +335,7 @@ private final class SettingsSearchContainerNode: SearchDisplayControllerContentN
|
||||
private var presentationDataDisposable: Disposable?
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
init(context: AccountContext, openResult: @escaping (SettingsSearchableItem) -> Void, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>) {
|
||||
init(context: AccountContext, openResult: @escaping (SettingsSearchableItem) -> Void, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>, activeSessionsContext: Signal<ActiveSessionsContext?, NoError>, webSessionsContext: Signal<WebSessionsContext?, NoError>) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
@ -355,7 +359,7 @@ private final class SettingsSearchContainerNode: SearchDisplayControllerContentN
|
||||
})
|
||||
|
||||
let searchableItems = Promise<[SettingsSearchableItem]>()
|
||||
searchableItems.set(settingsSearchableItems(context: context, notificationExceptionsList: exceptionsList, archivedStickerPacks: archivedStickerPacks, privacySettings: privacySettings, hasWallet: hasWallet))
|
||||
searchableItems.set(settingsSearchableItems(context: context, notificationExceptionsList: exceptionsList, archivedStickerPacks: archivedStickerPacks, privacySettings: privacySettings, hasWallet: hasWallet, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext))
|
||||
|
||||
let queryAndFoundItems = combineLatest(searchableItems.get(), faqSearchableItems(context: context))
|
||||
|> mapToSignal { searchableItems, faqSearchableItems -> Signal<(String, [SettingsSearchableItem])?, NoError> in
|
||||
@ -619,10 +623,12 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
let archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>
|
||||
let privacySettings: Signal<AccountPrivacySettings?, NoError>
|
||||
let hasWallet: Signal<Bool, NoError>
|
||||
let activeSessionsContext: Signal<ActiveSessionsContext?, NoError>
|
||||
let webSessionsContext: Signal<WebSessionsContext?, NoError>
|
||||
|
||||
var cancel: () -> Void
|
||||
|
||||
init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>) {
|
||||
init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?, exceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>, activeSessionsContext: Signal<ActiveSessionsContext?, NoError>, webSessionsContext: Signal<WebSessionsContext?, NoError>) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.cancel = cancel
|
||||
@ -633,6 +639,8 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
self.archivedStickerPacks = archivedStickerPacks
|
||||
self.privacySettings = privacySettings
|
||||
self.hasWallet = hasWallet
|
||||
self.activeSessionsContext = activeSessionsContext
|
||||
self.webSessionsContext = webSessionsContext
|
||||
|
||||
super.init()
|
||||
}
|
||||
@ -674,7 +682,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
|
||||
}
|
||||
})
|
||||
}
|
||||
}, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasWallet: self.hasWallet), cancel: { [weak self] in
|
||||
}, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasWallet: self.hasWallet, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext), cancel: { [weak self] in
|
||||
self?.cancel()
|
||||
})
|
||||
|
||||
|
@ -427,7 +427,7 @@ private func notificationSearchableItems(context: AccountContext, settings: Glob
|
||||
]
|
||||
}
|
||||
|
||||
private func privacySearchableItems(context: AccountContext, privacySettings: AccountPrivacySettings?) -> [SettingsSearchableItem] {
|
||||
private func privacySearchableItems(context: AccountContext, privacySettings: AccountPrivacySettings?, activeSessionsContext: ActiveSessionsContext?, webSessionsContext: WebSessionsContext?) -> [SettingsSearchableItem] {
|
||||
let icon: SettingsSearchableItemIcon = .privacy
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
@ -503,7 +503,7 @@ private func privacySearchableItems(context: AccountContext, privacySettings: Ac
|
||||
passcodeAlternate = synonyms(strings.SettingsSearch_Synonyms_Privacy_Passcode)
|
||||
}
|
||||
|
||||
return [
|
||||
return ([
|
||||
SettingsSearchableItem(id: .privacy(0), title: strings.Settings_PrivacySettings, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Title), icon: icon, breadcrumbs: [], present: { context, _, present in
|
||||
presentPrivacySettings(context, present, nil)
|
||||
}),
|
||||
@ -544,34 +544,37 @@ private func privacySearchableItems(context: AccountContext, privacySettings: Ac
|
||||
SettingsSearchableItem(id: .privacy(8), title: strings.PrivacySettings_TwoStepAuth, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_TwoStepAuth), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
present(.push, twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: true, data: nil)))
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(9), title: strings.PrivacySettings_WebSessions, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_AuthSessions), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
present(.push, recentSessionsController(context: context, activeSessionsContext: ActiveSessionsContext(account: context.account), webSessionsContext: WebSessionsContext(account: context.account), websitesOnly: true))
|
||||
activeSessionsContext == nil ? nil : SettingsSearchableItem(id: .privacy(9), title: strings.Settings_Devices, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_AuthSessions) + [strings.PrivacySettings_AuthSessions], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext!, webSessionsContext: webSessionsContext ?? WebSessionsContext(account: context.account), websitesOnly: false))
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(10), title: strings.PrivacySettings_DeleteAccountTitle, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
webSessionsContext == nil ? nil : SettingsSearchableItem(id: .privacy(10), title: strings.PrivacySettings_WebSessions, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_AuthSessions), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext ?? ActiveSessionsContext(account: context.account), webSessionsContext: webSessionsContext ?? WebSessionsContext(account: context.account), websitesOnly: true))
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(11), title: strings.PrivacySettings_DeleteAccountTitle, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
presentPrivacySettings(context, present, .accountTimeout)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(11), title: strings.PrivacySettings_DataSettings, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_Title), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(12), title: strings.PrivacySettings_DataSettings, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_Title), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(12), title: strings.Privacy_ContactsReset, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ContactsReset), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(13), title: strings.Privacy_ContactsReset, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ContactsReset), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(13), title: strings.Privacy_ContactsSync, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ContactsSync), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(14), title: strings.Privacy_ContactsSync, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ContactsSync), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(14), title: strings.Privacy_TopPeers, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_TopPeers), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(15), title: strings.Privacy_TopPeers, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_TopPeers), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(15), title: strings.Privacy_DeleteDrafts, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(16), title: strings.Privacy_DeleteDrafts, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(16), title: strings.Privacy_PaymentsClearInfo, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(17), title: strings.Privacy_PaymentsClearInfo, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
}),
|
||||
SettingsSearchableItem(id: .privacy(17), title: strings.Privacy_SecretChatsLinkPreviews, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings, strings.Privacy_SecretChatsTitle], present: { context, _, present in
|
||||
SettingsSearchableItem(id: .privacy(18), title: strings.Privacy_SecretChatsLinkPreviews, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings, strings.Privacy_SecretChatsTitle], present: { context, _, present in
|
||||
presentDataPrivacySettings(context, present)
|
||||
})
|
||||
]
|
||||
] as [SettingsSearchableItem?]).compactMap { $0 }
|
||||
}
|
||||
|
||||
private func dataSearchableItems(context: AccountContext) -> [SettingsSearchableItem] {
|
||||
@ -733,7 +736,7 @@ private func languageSearchableItems(context: AccountContext, localizations: [Lo
|
||||
return items
|
||||
}
|
||||
|
||||
func settingsSearchableItems(context: AccountContext, notificationExceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>) -> Signal<[SettingsSearchableItem], NoError> {
|
||||
func settingsSearchableItems(context: AccountContext, notificationExceptionsList: Signal<NotificationExceptionsList?, NoError>, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal<AccountPrivacySettings?, NoError>, hasWallet: Signal<Bool, NoError>, activeSessionsContext: Signal<ActiveSessionsContext?, NoError>, webSessionsContext: Signal<WebSessionsContext?, NoError>) -> Signal<[SettingsSearchableItem], NoError> {
|
||||
let watchAppInstalled = (context.watchManager?.watchAppInstalled ?? .single(false))
|
||||
|> take(1)
|
||||
|
||||
@ -810,8 +813,27 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
||||
}
|
||||
}
|
||||
|
||||
return combineLatest(watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasWallet)
|
||||
|> map { watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasWallet in
|
||||
let activeWebSessionsContext = webSessionsContext
|
||||
|> mapToSignal { webSessionsContext -> Signal<WebSessionsContext?, NoError> in
|
||||
if let webSessionsContext = webSessionsContext {
|
||||
return webSessionsContext.state
|
||||
|> map { state -> WebSessionsContext? in
|
||||
if !state.sessions.isEmpty {
|
||||
return webSessionsContext
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
return lhs !== rhs
|
||||
})
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|
||||
return combineLatest(watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasWallet, activeSessionsContext, activeWebSessionsContext)
|
||||
|> map { watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasWallet, activeSessionsContext, activeWebSessionsContext in
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
var allItems: [SettingsSearchableItem] = []
|
||||
@ -833,7 +855,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
||||
let notificationItems = notificationSearchableItems(context: context, settings: notificationSettings, exceptionsList: notificationExceptionsList)
|
||||
allItems.append(contentsOf: notificationItems)
|
||||
|
||||
let privacyItems = privacySearchableItems(context: context, privacySettings: privacySettings)
|
||||
let privacyItems = privacySearchableItems(context: context, privacySettings: privacySettings, activeSessionsContext: activeSessionsContext, webSessionsContext: activeWebSessionsContext)
|
||||
allItems.append(contentsOf: privacyItems)
|
||||
|
||||
let dataItems = dataSearchableItems(context: context)
|
||||
|
@ -1425,7 +1425,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
presentControllerImpl?(c, a)
|
||||
}, pushController: { c in
|
||||
pushControllerImpl?(c)
|
||||
}, getNavigationController: getNavigationControllerImpl, exceptionsList: notifyExceptions.get(), archivedStickerPacks: archivedPacks.get(), privacySettings: privacySettings.get(), hasWallet: hasWallet)
|
||||
}, getNavigationController: getNavigationControllerImpl, exceptionsList: notifyExceptions.get(), archivedStickerPacks: archivedPacks.get(), privacySettings: privacySettings.get(), hasWallet: hasWallet, activeSessionsContext: activeSessionsContextAndCountSignal |> map { $0.0 } |> distinctUntilChanged(isEqual: { $0 === $1 }), webSessionsContext: activeSessionsContextAndCountSignal |> map { $0.2 } |> distinctUntilChanged(isEqual: { $0 === $1 }))
|
||||
|
||||
let (hasWallet, hasPassport, hasWatchApp, enableQRLogin) = hasWalletPassportAndWatch
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: settingsEntries(account: context.account, presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, notifyExceptions: preferencesAndExceptions.1, notificationsAuthorizationStatus: preferencesAndExceptions.2, notificationsWarningSuppressed: preferencesAndExceptions.3, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1, privacySettings: preferencesAndExceptions.4, hasWallet: hasWallet, hasPassport: hasPassport, hasWatchApp: hasWatchApp, accountsAndPeers: accountsAndPeers.1, inAppNotificationSettings: inAppNotificationSettings, experimentalUISettings: experimentalUISettings, displayPhoneNumberConfirmation: preferencesAndExceptions.5, otherSessionCount: otherSessionCount, enableQRLogin: enableQRLogin), style: .blocks, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up))
|
||||
|
@ -58,7 +58,7 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode {
|
||||
self.contentTextNode.displaysAsynchronously = false
|
||||
self.contentTextNode.maximumNumberOfLines = 0
|
||||
|
||||
let fontSize = floor(presentationData.fontSize.baseDisplaySize * 15.0 / 17.0)
|
||||
let fontSize = floor(presentationData.listsFontSize.baseDisplaySize * 15.0 / 17.0)
|
||||
|
||||
self.contentTextNode.attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: presentationData.theme.list.itemPrimaryTextColor, linkColor: presentationData.theme.list.itemAccentColor, baseFont: Font.regular(fontSize), linkFont: Font.regular(fontSize), boldFont: Font.semibold(fontSize), italicFont: Font.italic(fontSize), boldItalicFont: Font.semiboldItalic(fontSize), fixedFont: Font.monospace(fontSize), blockQuoteFont: Font.regular(fontSize))
|
||||
|
||||
@ -68,12 +68,12 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode {
|
||||
self.leftActionTextNode = ImmediateTextNode()
|
||||
self.leftActionTextNode.displaysAsynchronously = false
|
||||
self.leftActionTextNode.isUserInteractionEnabled = false
|
||||
self.leftActionTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.PrivacyPolicy_Decline, font: Font.regular(presentationData.fontSize.baseDisplaySize), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
self.leftActionTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.PrivacyPolicy_Decline, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
self.rightActionNode = HighlightableButtonNode()
|
||||
self.rightActionTextNode = ImmediateTextNode()
|
||||
self.rightActionTextNode.displaysAsynchronously = false
|
||||
self.rightActionTextNode.isUserInteractionEnabled = false
|
||||
self.rightActionTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.PrivacyPolicy_Accept, font: Font.semibold(presentationData.fontSize.baseDisplaySize), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
self.rightActionTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.PrivacyPolicy_Accept, font: Font.semibold(presentationData.listsFontSize.baseDisplaySize), textColor: self.presentationData.theme.list.itemAccentColor)
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -52,7 +52,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
init(context: AccountContext, presentationThemeSettings: PresentationThemeSettings, dismiss: @escaping () -> Void, apply: @escaping (Bool, PresentationFontSize) -> Void) {
|
||||
init(context: AccountContext, presentationThemeSettings: PresentationThemeSettings, dismiss: @escaping () -> Void, apply: @escaping (Bool, PresentationFontSize, PresentationFontSize) -> Void) {
|
||||
self.context = context
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -133,7 +133,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
}
|
||||
if !dismissed {
|
||||
dismissed = true
|
||||
apply(strongSelf.presentationThemeSettings.useSystemFont, strongSelf.presentationThemeSettings.fontSize)
|
||||
apply(strongSelf.presentationThemeSettings.useSystemFont, strongSelf.presentationThemeSettings.fontSize, strongSelf.presentationThemeSettings.listsFontSize)
|
||||
}
|
||||
}
|
||||
self.toolbarNode.updateUseSystemFont = { [weak self] value in
|
||||
@ -147,7 +147,12 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.presentationThemeSettings.fontSize = value
|
||||
switch strongSelf.toolbarNode.customMode {
|
||||
case .chat:
|
||||
strongSelf.presentationThemeSettings.fontSize = value
|
||||
case .list:
|
||||
strongSelf.presentationThemeSettings.listsFontSize = value
|
||||
}
|
||||
strongSelf.updatePresentationThemeSettings(strongSelf.presentationThemeSettings)
|
||||
}
|
||||
|
||||
@ -177,6 +182,15 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
let bounds = scrollView.bounds
|
||||
if !bounds.width.isZero {
|
||||
self.pageControlNode.setPage(scrollView.contentOffset.x / bounds.width)
|
||||
let pageIndex = Int(round(scrollView.contentOffset.x / bounds.width))
|
||||
let customMode: TextSelectionCustomMode = pageIndex >= 1 ? .list : .chat
|
||||
if customMode != self.toolbarNode.customMode {
|
||||
self.toolbarNode.setCustomMode(customMode)
|
||||
if let (layout, navigationBarHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
self.recursivelyEnsureDisplaySynchronously(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +216,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, togglePeerSelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, activateChatPreview: { _, _, gesture in
|
||||
gesture?.cancel()
|
||||
})
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
|
||||
let peers = SimpleDictionary<PeerId, Peer>()
|
||||
let messages = SimpleDictionary<MessageId, Message>()
|
||||
@ -289,7 +303,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
}
|
||||
|
||||
private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
|
||||
var items: [ListViewItem] = []
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1)
|
||||
@ -303,20 +317,20 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||
|
||||
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
|
||||
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: MemoryBuffer(data: Data(base64Encoded: waveformBase64)!))]
|
||||
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
|
||||
|
||||
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message3, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message3, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let width: CGFloat
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
@ -384,13 +398,16 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
|
||||
func updatePresentationThemeSettings(_ presentationThemeSettings: PresentationThemeSettings) {
|
||||
let fontSize: PresentationFontSize
|
||||
let listsFontSize: PresentationFontSize
|
||||
if presentationThemeSettings.useSystemFont {
|
||||
let pointSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||
fontSize = PresentationFontSize(systemFontSize: pointSize)
|
||||
listsFontSize = fontSize
|
||||
} else {
|
||||
fontSize = presentationThemeSettings.fontSize
|
||||
listsFontSize = presentationThemeSettings.listsFontSize
|
||||
}
|
||||
self.presentationData = self.presentationData.withFontSize(fontSize)
|
||||
self.presentationData = self.presentationData.withFontSizes(chatFontSize: fontSize, listsFontSize: listsFontSize)
|
||||
self.toolbarNode.updatePresentationData(presentationData: self.presentationData)
|
||||
self.toolbarNode.updatePresentationThemeSettings(presentationThemeSettings: self.presentationThemeSettings)
|
||||
if let (layout, navigationBarHeight) = self.validLayout {
|
||||
@ -525,19 +542,20 @@ final class TextSizeSelectionController: ViewController {
|
||||
if let strongSelf = self {
|
||||
strongSelf.dismiss()
|
||||
}
|
||||
}, apply: { [weak self] useSystemFont, fontSize in
|
||||
}, apply: { [weak self] useSystemFont, fontSize, listsFontSize in
|
||||
if let strongSelf = self {
|
||||
strongSelf.apply(useSystemFont: useSystemFont, fontSize: fontSize)
|
||||
strongSelf.apply(useSystemFont: useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize)
|
||||
}
|
||||
})
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
private func apply(useSystemFont: Bool, fontSize: PresentationFontSize) {
|
||||
private func apply(useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize) {
|
||||
let _ = (updatePresentationThemeSettingsInteractively(accountManager: self.context.sharedContext.accountManager, { current in
|
||||
var current = current
|
||||
current.useSystemFont = useSystemFont
|
||||
current.fontSize = fontSize
|
||||
current.listsFontSize = listsFontSize
|
||||
return current
|
||||
})
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
@ -552,6 +570,11 @@ final class TextSizeSelectionController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private enum TextSelectionCustomMode {
|
||||
case list
|
||||
case chat
|
||||
}
|
||||
|
||||
private final class TextSelectionToolbarNode: ASDisplayNode {
|
||||
private var presentationThemeSettings: PresentationThemeSettings
|
||||
private var presentationData: PresentationData
|
||||
@ -564,6 +587,8 @@ private final class TextSelectionToolbarNode: ASDisplayNode {
|
||||
private var switchItemNode: ItemListSwitchItemNode
|
||||
private var fontSizeItemNode: ThemeSettingsFontSizeItemNode
|
||||
|
||||
private(set) var customMode: TextSelectionCustomMode = .chat
|
||||
|
||||
var cancel: (() -> Void)?
|
||||
var done: (() -> Void)?
|
||||
|
||||
@ -621,6 +646,10 @@ private final class TextSelectionToolbarNode: ASDisplayNode {
|
||||
self.doneButton.isUserInteractionEnabled = enabled
|
||||
}
|
||||
|
||||
func setCustomMode(_ customMode: TextSelectionCustomMode) {
|
||||
self.customMode = customMode
|
||||
}
|
||||
|
||||
func updatePresentationData(presentationData: PresentationData) {
|
||||
self.backgroundColor = presentationData.theme.rootController.tabBar.backgroundColor
|
||||
self.separatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor
|
||||
@ -640,7 +669,7 @@ private final class TextSelectionToolbarNode: ASDisplayNode {
|
||||
let switchItem = ItemListSwitchItem(presentationData: ItemListPresentationData(self.presentationData), title: self.presentationData.strings.Appearance_TextSize_UseSystem, value: self.presentationThemeSettings.useSystemFont, disableLeadingInset: true, sectionId: 0, style: .blocks, updated: { [weak self] value in
|
||||
self?.updateUseSystemFont?(value)
|
||||
})
|
||||
let fontSizeItem = ThemeSettingsFontSizeItem(theme: self.presentationData.theme, fontSize: self.presentationThemeSettings.fontSize, enabled: !self.presentationThemeSettings.useSystemFont, disableLeadingInset: true, sectionId: 0, updated: { [weak self] value in
|
||||
let fontSizeItem = ThemeSettingsFontSizeItem(theme: self.presentationData.theme, fontSize: self.customMode == .chat ? self.presentationThemeSettings.fontSize : self.presentationThemeSettings.listsFontSize, enabled: !self.presentationThemeSettings.useSystemFont, disableLeadingInset: true, force: true, sectionId: 0, updated: { [weak self] value in
|
||||
self?.updateCustomFontSize?(value)
|
||||
})
|
||||
|
||||
|
@ -253,7 +253,7 @@ private func editThemeControllerEntries(presentationData: PresentationData, stat
|
||||
entries.append(.slugInfo(presentationData.theme, infoText))
|
||||
|
||||
entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased()))
|
||||
entries.append(.chatPreview(presentationData.theme, previewTheme, previewTheme.chat.defaultWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (previewIncomingReplyName, previewIncomingReplyText), text: previewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: previewOutgoingText)]))
|
||||
entries.append(.chatPreview(presentationData.theme, previewTheme, previewTheme.chat.defaultWallpaper, presentationData.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (previewIncomingReplyName, previewIncomingReplyText), text: previewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: previewOutgoingText)]))
|
||||
|
||||
entries.append(.changeColors(presentationData.theme, presentationData.strings.EditTheme_ChangeColors))
|
||||
if !hasSettings {
|
||||
@ -556,7 +556,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|
||||
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
|
||||
themeSpecificChatWallpapers[themeReference.index] = nil
|
||||
|
||||
return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
}) |> deliverOnMainQueue).start(completed: {
|
||||
if !hasCustomFile {
|
||||
saveThemeTemplateFile(state.title, themeResource, {
|
||||
@ -590,7 +590,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|
||||
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
|
||||
themeSpecificChatWallpapers[themeReference.index] = nil
|
||||
|
||||
return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
}) |> deliverOnMainQueue).start(completed: {
|
||||
if let themeResource = themeResource, !hasCustomFile {
|
||||
saveThemeTemplateFile(state.title, themeResource, {
|
||||
|
@ -276,7 +276,7 @@ final class ThemeAccentColorController: ViewController {
|
||||
var themeSpecificAccentColors = current.themeSpecificAccentColors
|
||||
themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index)
|
||||
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
})
|
||||
|> castError(CreateThemeError.self)
|
||||
} else {
|
||||
@ -305,7 +305,7 @@ final class ThemeAccentColorController: ViewController {
|
||||
var themeSpecificAccentColors = current.themeSpecificAccentColors
|
||||
themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index)
|
||||
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
})
|
||||
|> castError(CreateThemeError.self)
|
||||
} else {
|
||||
|
@ -768,7 +768,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, togglePeerSelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, activateChatPreview: { _, _, gesture in
|
||||
gesture?.cancel()
|
||||
})
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
|
||||
let peers = SimpleDictionary<PeerId, Peer>()
|
||||
let messages = SimpleDictionary<MessageId, Message>()
|
||||
@ -836,7 +836,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
}
|
||||
|
||||
private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
|
||||
var items: [ListViewItem] = []
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1)
|
||||
@ -878,7 +878,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
sampleMessages.append(message8)
|
||||
|
||||
items = sampleMessages.reversed().map { message in
|
||||
let item = self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: { [weak self] message in
|
||||
let item = self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: { [weak self] message in
|
||||
if message.flags.contains(.Incoming) {
|
||||
self?.updateSection(.accent)
|
||||
self?.requestSectionUpdate?(.accent)
|
||||
|
@ -353,7 +353,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _ in }, togglePeerSelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, activateChatPreview: { _, _, gesture in
|
||||
gesture?.cancel()
|
||||
})
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.previewTheme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.previewTheme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
|
||||
let peers = SimpleDictionary<PeerId, Peer>()
|
||||
let messages = SimpleDictionary<MessageId, Message>()
|
||||
@ -442,7 +442,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder)
|
||||
|
||||
var items: [ListViewItem] = []
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1)
|
||||
@ -484,7 +484,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
sampleMessages.append(message8)
|
||||
|
||||
items = sampleMessages.reversed().map { message in
|
||||
self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.previewTheme.chat.defaultWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: nil, clickThroughMessage: nil)
|
||||
self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.previewTheme.chat.defaultWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: nil, clickThroughMessage: nil)
|
||||
}
|
||||
|
||||
let width: CGFloat
|
||||
|
@ -429,7 +429,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData,
|
||||
let strings = presentationData.strings
|
||||
let title = presentationData.autoNightModeTriggered ? strings.Appearance_ColorThemeNight.uppercased() : strings.Appearance_ColorTheme.uppercased()
|
||||
entries.append(.themeListHeader(presentationData.theme, title))
|
||||
entries.append(.chatPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (presentationData.strings.Appearance_PreviewReplyAuthor, presentationData.strings.Appearance_PreviewReplyText), text: presentationData.strings.Appearance_PreviewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: presentationData.strings.Appearance_PreviewOutgoingText)]))
|
||||
entries.append(.chatPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (presentationData.strings.Appearance_PreviewReplyAuthor, presentationData.strings.Appearance_PreviewReplyText), text: presentationData.strings.Appearance_PreviewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: presentationData.strings.Appearance_PreviewOutgoingText)]))
|
||||
|
||||
let generalThemes: [PresentationThemeReference] = availableThemes.filter { reference in
|
||||
if case let .cloud(theme) = reference {
|
||||
@ -490,7 +490,11 @@ private func themeSettingsControllerEntries(presentationData: PresentationData,
|
||||
if presentationThemeSettings.useSystemFont {
|
||||
textSizeValue = strings.Appearance_TextSize_Automatic
|
||||
} else {
|
||||
textSizeValue = "\(Int(presentationThemeSettings.fontSize.baseDisplaySize))pt"
|
||||
if presentationThemeSettings.fontSize.baseDisplaySize == presentationThemeSettings.listsFontSize.baseDisplaySize {
|
||||
textSizeValue = "\(Int(presentationThemeSettings.fontSize.baseDisplaySize))pt"
|
||||
} else {
|
||||
textSizeValue = "\(Int(presentationThemeSettings.fontSize.baseDisplaySize))pt / \(Int(presentationThemeSettings.listsFontSize.baseDisplaySize))pt"
|
||||
}
|
||||
}
|
||||
entries.append(.textSize(presentationData.theme, strings.Appearance_TextSizeSetting, textSizeValue))
|
||||
|
||||
@ -550,10 +554,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
|
||||
let arguments = ThemeSettingsControllerArguments(context: context, selectTheme: { theme in
|
||||
selectThemeImpl?(theme)
|
||||
}, selectFontSize: { fontSize in
|
||||
let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||
return current.withUpdatedFontSize(fontSize)
|
||||
}).start()
|
||||
}, selectFontSize: { _ in
|
||||
}, openWallpaperSettings: {
|
||||
pushControllerImpl?(ThemeGridController(context: context))
|
||||
}, selectAccentColor: { accentColor in
|
||||
@ -989,7 +990,6 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
|> map { presentationData, sharedData, cloudThemes, availableAppIcons, currentAppIconName, removedThemeIndexes -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings
|
||||
|
||||
let fontSize = presentationData.fontSize
|
||||
let dateTimeFormat = presentationData.dateTimeFormat
|
||||
let largeEmoji = presentationData.largeEmoji
|
||||
let disableAnimations = presentationData.disableAnimations
|
||||
@ -1270,7 +1270,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
}
|
||||
}
|
||||
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
}).start()
|
||||
|
||||
presentCrossfadeControllerImpl?(true)
|
||||
|
@ -16,16 +16,18 @@ class ThemeSettingsFontSizeItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let fontSize: PresentationFontSize
|
||||
let disableLeadingInset: Bool
|
||||
let force: Bool
|
||||
let enabled: Bool
|
||||
let sectionId: ItemListSectionId
|
||||
let updated: (PresentationFontSize) -> Void
|
||||
let tag: ItemListItemTag?
|
||||
|
||||
init(theme: PresentationTheme, fontSize: PresentationFontSize, enabled: Bool = true, disableLeadingInset: Bool = false, sectionId: ItemListSectionId, updated: @escaping (PresentationFontSize) -> Void, tag: ItemListItemTag? = nil) {
|
||||
init(theme: PresentationTheme, fontSize: PresentationFontSize, enabled: Bool = true, disableLeadingInset: Bool = false, force: Bool = false, sectionId: ItemListSectionId, updated: @escaping (PresentationFontSize) -> Void, tag: ItemListItemTag? = nil) {
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.enabled = enabled
|
||||
self.disableLeadingInset = disableLeadingInset
|
||||
self.force = force
|
||||
self.sectionId = sectionId
|
||||
self.updated = updated
|
||||
self.tag = tag
|
||||
@ -201,7 +203,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let firstTime = strongSelf.item == nil
|
||||
let firstTime = strongSelf.item == nil || item.force
|
||||
strongSelf.item = item
|
||||
strongSelf.layoutParams = params
|
||||
|
||||
|
@ -832,10 +832,10 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let theme = self.presentationData.theme.withUpdated(preview: true)
|
||||
|
||||
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.fontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil))
|
||||
|
||||
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height)
|
||||
if let messageNodes = self.messageNodes {
|
||||
|
@ -232,10 +232,18 @@ final class CallControllerNode: ASDisplayNode {
|
||||
text += "\n\(self.statusNode.subtitle)"
|
||||
}
|
||||
statusValue = .text(text)
|
||||
case let .active(timestamp, reception, keyVisualHash):
|
||||
case .active(let timestamp, let reception, let keyVisualHash), .reconnecting(let timestamp, let reception, let keyVisualHash):
|
||||
let strings = self.presentationData.strings
|
||||
var isReconnecting = false
|
||||
if case .reconnecting = callState {
|
||||
isReconnecting = true
|
||||
}
|
||||
statusValue = .timer({ value in
|
||||
return strings.Call_StatusOngoing(value).0
|
||||
if isReconnecting {
|
||||
return strings.Call_StatusConnecting
|
||||
} else {
|
||||
return strings.Call_StatusOngoing(value).0
|
||||
}
|
||||
}, timestamp)
|
||||
if self.keyTextData?.0 != keyVisualHash {
|
||||
let text = stringForEmojiHashOfData(keyVisualHash, 4)!
|
||||
|
@ -461,6 +461,15 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
self.activeTimestamp = timestamp
|
||||
}
|
||||
presentationState = .active(timestamp, reception, keyVisualHash)
|
||||
case .reconnecting:
|
||||
let timestamp: Double
|
||||
if let activeTimestamp = self.activeTimestamp {
|
||||
timestamp = activeTimestamp
|
||||
} else {
|
||||
timestamp = CFAbsoluteTimeGetCurrent()
|
||||
self.activeTimestamp = timestamp
|
||||
}
|
||||
presentationState = .reconnecting(timestamp, reception, keyVisualHash)
|
||||
}
|
||||
} else {
|
||||
presentationState = .connecting(keyVisualHash)
|
||||
@ -520,7 +529,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
if let presentationState = presentationState {
|
||||
self.statePromise.set(presentationState)
|
||||
self.updateTone(presentationState, previous: previous)
|
||||
self.updateTone(presentationState, callContextState: callContextState, previous: previous)
|
||||
}
|
||||
|
||||
if !self.shouldPresentCallRating {
|
||||
@ -530,9 +539,11 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateTone(_ state: PresentationCallState, previous: CallSession?) {
|
||||
private func updateTone(_ state: PresentationCallState, callContextState: OngoingCallContextState?, previous: CallSession?) {
|
||||
var tone: PresentationCallTone?
|
||||
if let previous = previous {
|
||||
if let callContextState = callContextState, case .reconnecting = callContextState {
|
||||
tone = .connecting
|
||||
} else if let previous = previous {
|
||||
switch previous.state {
|
||||
case .accepting, .active, .dropping, .requesting:
|
||||
switch state {
|
||||
|
@ -865,6 +865,11 @@ public class Account {
|
||||
public var networkType: Signal<NetworkType, NoError> {
|
||||
return self.networkTypeValue.get()
|
||||
}
|
||||
private let atomicCurrentNetworkType = Atomic<NetworkType>(value: .none)
|
||||
public var immediateNetworkType: NetworkType {
|
||||
return self.atomicCurrentNetworkType.with { $0 }
|
||||
}
|
||||
private var networkTypeDisposable: Disposable?
|
||||
|
||||
private let _loggedOut = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
public var loggedOut: Signal<Bool, NoError> {
|
||||
@ -972,6 +977,10 @@ public class Account {
|
||||
|> distinctUntilChanged)
|
||||
|
||||
self.networkTypeValue.set(currentNetworkType())
|
||||
let atomicCurrentNetworkType = self.atomicCurrentNetworkType
|
||||
self.networkTypeDisposable = self.networkTypeValue.get().start(next: { value in
|
||||
let _ = atomicCurrentNetworkType.swap(value)
|
||||
})
|
||||
|
||||
let serviceTasksMasterBecomeMaster = self.shouldBeServiceTaskMaster.get()
|
||||
|> distinctUntilChanged
|
||||
@ -1127,6 +1136,7 @@ public class Account {
|
||||
self.managedOperationsDisposable.dispose()
|
||||
self.storageSettingsDisposable?.dispose()
|
||||
self.smallLogPostDisposable.dispose()
|
||||
self.networkTypeDisposable?.dispose()
|
||||
}
|
||||
|
||||
private func postSmallLogIfNeeded() {
|
||||
|
@ -72,7 +72,7 @@ public extension ActionSheetControllerTheme {
|
||||
let presentationTheme = presentationData.theme
|
||||
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(dimColor: actionSheet.dimColor, backgroundType: actionSheet.backgroundType == .light ? .light : .dark, itemBackgroundColor: actionSheet.itemBackgroundColor, itemHighlightedBackgroundColor: actionSheet.itemHighlightedBackgroundColor, standardActionTextColor: actionSheet.standardActionTextColor, destructiveActionTextColor: actionSheet.destructiveActionTextColor, disabledActionTextColor: actionSheet.disabledActionTextColor, primaryTextColor: actionSheet.primaryTextColor, secondaryTextColor: actionSheet.secondaryTextColor, controlAccentColor: actionSheet.controlAccentColor, controlColor: presentationTheme.list.disclosureArrowColor, switchFrameColor: presentationTheme.list.itemSwitchColors.frameColor, switchContentColor: presentationTheme.list.itemSwitchColors.contentColor, switchHandleColor: presentationTheme.list.itemSwitchColors.handleColor, baseFontSize: presentationData.fontSize.baseDisplaySize)
|
||||
self.init(dimColor: actionSheet.dimColor, backgroundType: actionSheet.backgroundType == .light ? .light : .dark, itemBackgroundColor: actionSheet.itemBackgroundColor, itemHighlightedBackgroundColor: actionSheet.itemHighlightedBackgroundColor, standardActionTextColor: actionSheet.standardActionTextColor, destructiveActionTextColor: actionSheet.destructiveActionTextColor, disabledActionTextColor: actionSheet.disabledActionTextColor, primaryTextColor: actionSheet.primaryTextColor, secondaryTextColor: actionSheet.secondaryTextColor, controlAccentColor: actionSheet.controlAccentColor, controlColor: presentationTheme.list.disclosureArrowColor, switchFrameColor: presentationTheme.list.itemSwitchColors.frameColor, switchContentColor: presentationTheme.list.itemSwitchColors.contentColor, switchHandleColor: presentationTheme.list.itemSwitchColors.handleColor, baseFontSize: presentationData.listsFontSize.baseDisplaySize)
|
||||
}
|
||||
|
||||
convenience init(presentationTheme: PresentationTheme, fontSize: PresentationFontSize) {
|
||||
@ -96,7 +96,7 @@ public extension AlertControllerTheme {
|
||||
convenience init(presentationData: PresentationData) {
|
||||
let presentationTheme = presentationData.theme
|
||||
let actionSheet = presentationTheme.actionSheet
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, baseFontSize: presentationData.fontSize.baseDisplaySize)
|
||||
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor, baseFontSize: presentationData.listsFontSize.baseDisplaySize)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,19 +53,21 @@ public final class PresentationData: Equatable {
|
||||
public let theme: PresentationTheme
|
||||
public let autoNightModeTriggered: Bool
|
||||
public let chatWallpaper: TelegramWallpaper
|
||||
public let fontSize: PresentationFontSize
|
||||
public let chatFontSize: PresentationFontSize
|
||||
public let listsFontSize: PresentationFontSize
|
||||
public let dateTimeFormat: PresentationDateTimeFormat
|
||||
public let nameDisplayOrder: PresentationPersonNameOrder
|
||||
public let nameSortOrder: PresentationPersonNameOrder
|
||||
public let disableAnimations: Bool
|
||||
public let largeEmoji: Bool
|
||||
|
||||
public init(strings: PresentationStrings, theme: PresentationTheme, autoNightModeTriggered: Bool, chatWallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool) {
|
||||
public init(strings: PresentationStrings, theme: PresentationTheme, autoNightModeTriggered: Bool, chatWallpaper: TelegramWallpaper, chatFontSize: PresentationFontSize, listsFontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool) {
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.autoNightModeTriggered = autoNightModeTriggered
|
||||
self.chatWallpaper = chatWallpaper
|
||||
self.fontSize = fontSize
|
||||
self.chatFontSize = chatFontSize
|
||||
self.listsFontSize = listsFontSize
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.nameSortOrder = nameSortOrder
|
||||
@ -74,7 +76,7 @@ public final class PresentationData: Equatable {
|
||||
}
|
||||
|
||||
public static func ==(lhs: PresentationData, rhs: PresentationData) -> Bool {
|
||||
return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.fontSize == rhs.fontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.disableAnimations == rhs.disableAnimations && lhs.largeEmoji == rhs.largeEmoji
|
||||
return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatFontSize == rhs.chatFontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.disableAnimations == rhs.disableAnimations && lhs.largeEmoji == rhs.largeEmoji
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,7 +265,10 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager, s
|
||||
}
|
||||
let nameDisplayOrder = contactSettings.nameDisplayOrder
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, fontSize: resolveFontSize(settings: themeSettings), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings)
|
||||
|
||||
let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings)
|
||||
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings)
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,7 +599,9 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI
|
||||
let nameDisplayOrder = contactSettings.nameDisplayOrder
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
|
||||
return PresentationData(strings: stringsValue, theme: themeValue, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, fontSize: resolveFontSize(settings: themeSettings), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji)
|
||||
let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings)
|
||||
|
||||
return PresentationData(strings: stringsValue, theme: themeValue, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji)
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
@ -604,15 +611,18 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI
|
||||
}
|
||||
}
|
||||
|
||||
public func resolveFontSize(settings: PresentationThemeSettings) -> PresentationFontSize {
|
||||
private func resolveFontSize(settings: PresentationThemeSettings) -> (chat: PresentationFontSize, lists: PresentationFontSize) {
|
||||
let fontSize: PresentationFontSize
|
||||
let listsFontSize: PresentationFontSize
|
||||
if settings.useSystemFont {
|
||||
let pointSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||
fontSize = PresentationFontSize(systemFontSize: pointSize)
|
||||
listsFontSize = fontSize
|
||||
} else {
|
||||
fontSize = settings.fontSize
|
||||
listsFontSize = settings.listsFontSize
|
||||
}
|
||||
return fontSize
|
||||
return (fontSize, listsFontSize)
|
||||
}
|
||||
|
||||
public func defaultPresentationData() -> PresentationData {
|
||||
@ -621,15 +631,18 @@ public func defaultPresentationData() -> PresentationData {
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
|
||||
let themeSettings = PresentationThemeSettings.defaultSettings
|
||||
return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, autoNightModeTriggered: false, chatWallpaper: .builtin(WallpaperSettings()), fontSize: resolveFontSize(settings: themeSettings), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji)
|
||||
|
||||
let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings)
|
||||
|
||||
return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, autoNightModeTriggered: false, chatWallpaper: .builtin(WallpaperSettings()), chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji)
|
||||
}
|
||||
|
||||
public extension PresentationData {
|
||||
func withFontSize(_ fontSize: PresentationFontSize) -> PresentationData {
|
||||
return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, fontSize: fontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji)
|
||||
func withFontSizes(chatFontSize: PresentationFontSize, listsFontSize: PresentationFontSize) -> PresentationData {
|
||||
return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji)
|
||||
}
|
||||
|
||||
func withStrings(_ strings: PresentationStrings) -> PresentationData {
|
||||
return PresentationData(strings: strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, fontSize: self.fontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji)
|
||||
return PresentationData(strings: strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,17 +2,7 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "StickerKeyboardTrendingIcon@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "StickerKeyboardTrendingIcon@3x.png",
|
||||
"scale" : "3x"
|
||||
"filename" : "ic_addstickers.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 933 B |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Media/TrendingIcon.imageset/ic_addstickers.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Input/Media/TrendingIcon.imageset/ic_addstickers.pdf
vendored
Normal file
Binary file not shown.
@ -112,7 +112,7 @@ private func isTopmostChatController(_ controller: ChatControllerImpl) -> Bool {
|
||||
if let _ = controller.navigationController {
|
||||
var hasOther = false
|
||||
controller.window?.forEachController({ c in
|
||||
if c is ChatControllerImpl {
|
||||
if c is ChatControllerImpl && controller !== c {
|
||||
hasOther = true
|
||||
}
|
||||
})
|
||||
@ -346,7 +346,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
isScheduledMessages = true
|
||||
}
|
||||
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.fontSize, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, isScheduledMessages: isScheduledMessages)
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, isScheduledMessages: isScheduledMessages)
|
||||
|
||||
var mediaAccessoryPanelVisibility = MediaAccessoryPanelVisibility.none
|
||||
if case .standard = mode {
|
||||
@ -1582,7 +1582,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let strongSelf = self {
|
||||
if let node = node {
|
||||
strongSelf.messageTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
strongSelf.messageTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.messageTooltipController === tooltipController {
|
||||
@ -3637,7 +3637,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
tooltipController.updateContent(.text(banDescription), animated: true, extendTimer: true)
|
||||
} else if let rect = rect {
|
||||
strongSelf.mediaRestrictedTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .text(banDescription), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize)
|
||||
let tooltipController = TooltipController(content: .text(banDescription), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize)
|
||||
strongSelf.mediaRestrictedTooltipController = tooltipController
|
||||
strongSelf.mediaRestrictedTooltipControllerMode = isStickers
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
@ -3673,7 +3673,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
if let location = location, let icon = icon {
|
||||
strongSelf.videoUnmuteTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .iconAndText(icon, strongSelf.presentationInterfaceState.strings.Conversation_PressVolumeButtonForSound), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, timeout: 3.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
let tooltipController = TooltipController(content: .iconAndText(icon, strongSelf.presentationInterfaceState.strings.Conversation_PressVolumeButtonForSound), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, timeout: 3.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
strongSelf.videoUnmuteTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.videoUnmuteTooltipController === tooltipController {
|
||||
@ -3928,7 +3928,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let tooltipController = strongSelf.silentPostTooltipController {
|
||||
tooltipController.updateContent(.text(text), animated: true, extendTimer: true)
|
||||
} else if let rect = rect {
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize)
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize)
|
||||
strongSelf.silentPostTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.silentPostTooltipController === tooltipController {
|
||||
@ -4162,7 +4162,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, displaySearchResultsTooltip: { [weak self] node, nodeRect in
|
||||
if let strongSelf = self {
|
||||
strongSelf.searchResultsTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.ChatSearch_ResultsTooltip), baseFontSize: strongSelf.presentationData.fontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.ChatSearch_ResultsTooltip), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
strongSelf.searchResultsTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.searchResultsTooltipController === tooltipController {
|
||||
@ -6225,7 +6225,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.recorderFeedback?.prepareImpact(.light)
|
||||
}
|
||||
|
||||
self.videoRecorder.set(.single(legacyInstantVideoController(theme: self.presentationData.theme, panelFrame: self.view.convert(currentInputPanelFrame, to: nil), context: self.context, peerId: peerId, slowmodeState: !self.presentationInterfaceState.isScheduledMessages ? self.presentationInterfaceState.slowmodeState : nil, send: { [weak self] message in
|
||||
self.videoRecorder.set(.single(legacyInstantVideoController(theme: self.presentationData.theme, panelFrame: self.view.convert(currentInputPanelFrame, to: nil), context: self.context, peerId: peerId, slowmodeState: !self.presentationInterfaceState.isScheduledMessages ? self.presentationInterfaceState.slowmodeState : nil, hasSchedule: !self.presentationInterfaceState.isScheduledMessages && peerId.namespace != Namespaces.Peer.SecretChat, send: { [weak self] message in
|
||||
if let strongSelf = self {
|
||||
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
|
||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||
@ -6240,6 +6240,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}, displaySlowmodeTooltip: { [weak self] node, rect in
|
||||
self?.interfaceInteraction?.displaySlowmodeTooltip(node, rect)
|
||||
}, presentSchedulePicker: { [weak self] done in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
|
||||
if let strongSelf = self {
|
||||
done(time)
|
||||
if !strongSelf.presentationInterfaceState.isScheduledMessages && time != scheduleWhenOnlineTimestamp {
|
||||
strongSelf.openScheduledMessages()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})))
|
||||
}
|
||||
}
|
||||
@ -7906,7 +7917,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let tooltipController = self.mediaRecordingModeTooltipController {
|
||||
tooltipController.updateContent(.text(text), animated: true, extendTimer: true)
|
||||
} else if let rect = rect {
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.fontSize.baseDisplaySize)
|
||||
let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize)
|
||||
self.mediaRecordingModeTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak self, weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.mediaRecordingModeTooltipController === tooltipController {
|
||||
@ -7927,7 +7938,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
self.sendingOptionsTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .text(self.presentationData.strings.Conversation_SendingOptionsTooltip), baseFontSize: self.presentationData.fontSize.baseDisplaySize, timeout: 3.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
let tooltipController = TooltipController(content: .text(self.presentationData.strings.Conversation_SendingOptionsTooltip), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, timeout: 3.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
self.sendingOptionsTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak self, weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.sendingOptionsTooltipController === tooltipController {
|
||||
|
@ -251,7 +251,7 @@ public final class ChatHistoryGridNode: GridNode, ChatHistoryNode {
|
||||
|
||||
self.chatPresentationDataPromise.set(context.sharedContext.presentationData
|
||||
|> map { presentationData in
|
||||
return ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji)
|
||||
return ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji)
|
||||
})
|
||||
|
||||
self.floatingSections = true
|
||||
|
@ -505,7 +505,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
self.mode = mode
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: 1.0)
|
||||
self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: 1.0)
|
||||
|
||||
self.chatPresentationDataPromise = Promise(self.currentPresentationData)
|
||||
|
||||
@ -880,7 +880,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings || previousWallpaper != presentationData.chatWallpaper || previousDisableAnimations != presentationData.disableAnimations || previousAnimatedEmojiScale != animatedEmojiConfig.scale {
|
||||
let themeData = ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper)
|
||||
let chatPresentationData = ChatPresentationData(theme: themeData, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: animatedEmojiConfig.scale)
|
||||
let chatPresentationData = ChatPresentationData(theme: themeData, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: animatedEmojiConfig.scale)
|
||||
|
||||
strongSelf.currentPresentationData = chatPresentationData
|
||||
strongSelf.dynamicBounceEnabled = !presentationData.disableAnimations
|
||||
@ -1194,14 +1194,18 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
if let visibleRange = self.displayedItemRange.loadedRange {
|
||||
var index = historyView.filteredEntries.count - 1
|
||||
loop: for entry in historyView.filteredEntries {
|
||||
if index >= visibleRange.firstIndex && index <= visibleRange.lastIndex {
|
||||
if case let .MessageEntry(message, _, _, _, _, _) = entry {
|
||||
let isVisible = index >= visibleRange.firstIndex && index <= visibleRange.lastIndex
|
||||
if case let .MessageEntry(message, _, _, _, _, _) = entry {
|
||||
if !isVisible || currentMessage == nil {
|
||||
currentMessage = message
|
||||
break loop
|
||||
} else if case let .MessageGroupEntry(_, messages, _) = entry {
|
||||
currentMessage = messages.first?.0
|
||||
break loop
|
||||
}
|
||||
} else if case let .MessageGroupEntry(_, messages, _) = entry {
|
||||
if !isVisible || currentMessage == nil {
|
||||
currentMessage = messages.first?.0
|
||||
}
|
||||
}
|
||||
if isVisible {
|
||||
break loop
|
||||
}
|
||||
index -= 1
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.dateTimeFormat, self.presentationData.fontSize))
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.dateTimeFormat, self.presentationData.listsFontSize))
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
|
||||
@ -228,7 +228,7 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
||||
|
||||
self.presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.themeAndStringsPromise.set(.single((presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.fontSize)))
|
||||
strongSelf.themeAndStringsPromise.set(.single((presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.listsFontSize)))
|
||||
|
||||
strongSelf.emptyResultsTitleNode.attributedText = NSAttributedString(string: presentationData.strings.SharedMedia_SearchNoResults, font: Font.semibold(17.0), textColor: presentationData.theme.list.freeTextColor, paragraphAlignment: .center)
|
||||
|
||||
|
@ -88,7 +88,7 @@ enum ChatMediaInputGridEntry: Equatable, Comparable, Identifiable {
|
||||
case search(theme: PresentationTheme, strings: PresentationStrings)
|
||||
case peerSpecificSetup(theme: PresentationTheme, strings: PresentationStrings, dismissed: Bool)
|
||||
case sticker(index: ItemCollectionViewEntryIndex, stickerItem: StickerPackItem, stickerPackInfo: StickerPackCollectionInfo?, canManagePeerSpecificPack: Bool?, theme: PresentationTheme)
|
||||
case trending(TrendingPaneEntry)
|
||||
case trending(TrendingPanePackEntry)
|
||||
|
||||
var index: ChatMediaInputGridEntryIndex {
|
||||
switch self {
|
||||
|
@ -496,7 +496,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
var getItemIsPreviewedImpl: ((StickerPackItem) -> Bool)?
|
||||
self.trendingPane = ChatMediaInputTrendingPane(context: context, controllerInteraction: controllerInteraction, getItemIsPreviewed: { item in
|
||||
return getItemIsPreviewedImpl?(item) ?? false
|
||||
})
|
||||
}, isPane: true)
|
||||
|
||||
self.paneArrangement = ChatMediaInputPaneArrangement(panes: [.gifs, .stickers, .trending], currentIndex: 1, indexTransition: 0.0)
|
||||
|
||||
@ -754,6 +754,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
strongSelf.controllerInteraction.presentController(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}, getItemIsPreviewed: { item in
|
||||
return getItemIsPreviewedImpl?(item) ?? false
|
||||
}, openSearch: {
|
||||
})
|
||||
|
||||
let previousView = Atomic<ItemCollectionsView?>(value: nil)
|
||||
@ -803,7 +804,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
var index = 0
|
||||
for item in trendingPacks {
|
||||
if !installedPacks.contains(item.info.id) {
|
||||
gridEntries.append(.trending(TrendingPaneEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: true)))
|
||||
gridEntries.append(.trending(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: true)))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -877,6 +878,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
|
||||
self.stickerPane.inputNodeInteraction = self.inputNodeInteraction
|
||||
self.gifPane.inputNodeInteraction = self.inputNodeInteraction
|
||||
self.trendingPane.inputNodeInteraction = self.inputNodeInteraction
|
||||
|
||||
paneDidScrollImpl = { [weak self] pane, state, transition in
|
||||
self?.updatePaneDidScroll(pane: pane, state: state, transition: transition)
|
||||
@ -1387,14 +1389,20 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
var placeholderNode: PaneSearchBarPlaceholderNode?
|
||||
if let searchMode = searchMode {
|
||||
switch searchMode {
|
||||
case .gif:
|
||||
placeholderNode = self.gifPane.searchPlaceholderNode
|
||||
case .sticker:
|
||||
self.stickerPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
case .gif:
|
||||
placeholderNode = self.gifPane.searchPlaceholderNode
|
||||
case .sticker:
|
||||
self.stickerPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
}
|
||||
case .trending:
|
||||
self.trendingPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1558,15 +1566,22 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
var placeholderNode: PaneSearchBarPlaceholderNode?
|
||||
if let searchMode = searchMode {
|
||||
switch searchMode {
|
||||
case .gif:
|
||||
placeholderNode = self.gifPane.searchPlaceholderNode
|
||||
paneIsEmpty = self.gifPane.isEmpty
|
||||
case .sticker:
|
||||
self.stickerPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
case .gif:
|
||||
placeholderNode = self.gifPane.searchPlaceholderNode
|
||||
paneIsEmpty = self.gifPane.isEmpty
|
||||
case .sticker:
|
||||
self.stickerPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
}
|
||||
case .trending:
|
||||
self.trendingPane.gridNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
|
||||
placeholderNode = itemNode
|
||||
}
|
||||
}
|
||||
paneIsEmpty = true
|
||||
}
|
||||
}
|
||||
if let placeholderNode = placeholderNode {
|
||||
|
@ -18,15 +18,17 @@ final class TrendingPaneInteraction {
|
||||
let installPack: (ItemCollectionInfo) -> Void
|
||||
let openPack: (ItemCollectionInfo) -> Void
|
||||
let getItemIsPreviewed: (StickerPackItem) -> Bool
|
||||
let openSearch: () -> Void
|
||||
|
||||
init(installPack: @escaping (ItemCollectionInfo) -> Void, openPack: @escaping (ItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
|
||||
init(installPack: @escaping (ItemCollectionInfo) -> Void, openPack: @escaping (ItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, openSearch: @escaping () -> Void) {
|
||||
self.installPack = installPack
|
||||
self.openPack = openPack
|
||||
self.getItemIsPreviewed = getItemIsPreviewed
|
||||
self.openSearch = openSearch
|
||||
}
|
||||
}
|
||||
|
||||
final class TrendingPaneEntry: Identifiable, Comparable {
|
||||
final class TrendingPanePackEntry: Identifiable, Comparable {
|
||||
let index: Int
|
||||
let info: StickerPackCollectionInfo
|
||||
let theme: PresentationTheme
|
||||
@ -51,7 +53,7 @@ final class TrendingPaneEntry: Identifiable, Comparable {
|
||||
return self.info.id
|
||||
}
|
||||
|
||||
static func ==(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
|
||||
static func ==(lhs: TrendingPanePackEntry, rhs: TrendingPanePackEntry) -> Bool {
|
||||
if lhs.index != rhs.index {
|
||||
return false
|
||||
}
|
||||
@ -79,7 +81,7 @@ final class TrendingPaneEntry: Identifiable, Comparable {
|
||||
return true
|
||||
}
|
||||
|
||||
static func <(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
|
||||
static func <(lhs: TrendingPanePackEntry, rhs: TrendingPanePackEntry) -> Bool {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
@ -95,6 +97,67 @@ final class TrendingPaneEntry: Identifiable, Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
private enum TrendingPaneEntryId: Hashable {
|
||||
case search
|
||||
case pack(ItemCollectionId)
|
||||
}
|
||||
|
||||
private enum TrendingPaneEntry: Identifiable, Comparable {
|
||||
case search(theme: PresentationTheme, strings: PresentationStrings)
|
||||
case pack(TrendingPanePackEntry)
|
||||
|
||||
var stableId: TrendingPaneEntryId {
|
||||
switch self {
|
||||
case .search:
|
||||
return .search
|
||||
case let .pack(pack):
|
||||
return .pack(pack.stableId)
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .search(lhsTheme, lhsStrings):
|
||||
if case let .search(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .pack(pack):
|
||||
if case .pack(pack) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func <(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
|
||||
switch lhs {
|
||||
case .search:
|
||||
return false
|
||||
case let .pack(lhsPack):
|
||||
switch rhs {
|
||||
case .search:
|
||||
return false
|
||||
case let .pack(rhsPack):
|
||||
return lhsPack < rhsPack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func item(account: Account, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
|
||||
switch self {
|
||||
case let .search(theme, strings):
|
||||
return PaneSearchBarPlaceholderItem(theme: theme, strings: strings, type: .stickers, activate: {
|
||||
interaction.openSearch()
|
||||
})
|
||||
case let .pack(pack):
|
||||
return pack.item(account: account, interaction: interaction, grid: grid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct TrendingPaneTransition {
|
||||
let deletions: [Int]
|
||||
let insertions: [GridNodeInsertItem]
|
||||
@ -112,12 +175,15 @@ private func preparedTransition(from fromEntries: [TrendingPaneEntry], to toEntr
|
||||
return TrendingPaneTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial)
|
||||
}
|
||||
|
||||
func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings) -> [TrendingPaneEntry] {
|
||||
private func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings, isPane: Bool) -> [TrendingPaneEntry] {
|
||||
var result: [TrendingPaneEntry] = []
|
||||
var index = 0
|
||||
if isPane {
|
||||
result.append(.search(theme: theme, strings: strings))
|
||||
}
|
||||
for item in trendingEntries {
|
||||
if !installedPacks.contains(item.info.id) {
|
||||
result.append(TrendingPaneEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: index != 0))
|
||||
result.append(.pack(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: index != 0)))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -128,6 +194,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
private let context: AccountContext
|
||||
private let controllerInteraction: ChatControllerInteraction
|
||||
private let getItemIsPreviewed: (StickerPackItem) -> Bool
|
||||
private let isPane: Bool
|
||||
|
||||
let gridNode: GridNode
|
||||
|
||||
@ -147,10 +214,11 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
|
||||
private let installDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
|
||||
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, isPane: Bool) {
|
||||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
self.getItemIsPreviewed = getItemIsPreviewed
|
||||
self.isPane = isPane
|
||||
|
||||
self.gridNode = GridNode()
|
||||
|
||||
@ -220,7 +288,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.12, queue: Queue.mainQueue())
|
||||
|> delay(1.0, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
installSignal = installSignal
|
||||
@ -267,8 +335,12 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
})
|
||||
strongSelf.controllerInteraction.presentController(controller, nil)
|
||||
}
|
||||
}, getItemIsPreviewed: self.getItemIsPreviewed)
|
||||
}, getItemIsPreviewed: self.getItemIsPreviewed,
|
||||
openSearch: { [weak self] in
|
||||
self?.inputNodeInteraction?.toggleSearch(true, .trending)
|
||||
})
|
||||
|
||||
let isPane = self.isPane
|
||||
let previousEntries = Atomic<[TrendingPaneEntry]?>(value: nil)
|
||||
let context = self.context
|
||||
self.disposable = (combineLatest(context.account.viewTracker.featuredStickerPacks(), context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]), context.sharedContext.presentationData)
|
||||
@ -281,7 +353,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
}
|
||||
}
|
||||
}
|
||||
let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings)
|
||||
let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, isPane: isPane)
|
||||
let previous = previousEntries.swap(entries)
|
||||
|
||||
return preparedTransition(from: previous ?? [], to: entries, account: context.account, interaction: interaction, initial: previous == nil)
|
||||
|
@ -82,6 +82,7 @@ enum ChatMediaInputMode {
|
||||
enum ChatMediaInputSearchMode {
|
||||
case gif
|
||||
case sticker
|
||||
case trending
|
||||
}
|
||||
|
||||
enum ChatMediaInputExpanded: Equatable {
|
||||
|
@ -111,9 +111,9 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
self.emptyNode = ChatRecentActionsEmptyNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper)
|
||||
self.emptyNode.alpha = 0.0
|
||||
|
||||
self.state = ChatRecentActionsControllerState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.fontSize)
|
||||
self.state = ChatRecentActionsControllerState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize)
|
||||
|
||||
self.chatPresentationDataPromise = Promise(ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations, largeEmoji: self.presentationData.largeEmoji))
|
||||
self.chatPresentationDataPromise = Promise(ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.chatFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations, largeEmoji: self.presentationData.largeEmoji))
|
||||
|
||||
self.eventLogContext = ChannelAdminEventLogContext(postbox: self.context.account.postbox, network: self.context.account.network, peerId: self.peer.id)
|
||||
|
||||
@ -493,7 +493,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.chatPresentationDataPromise.set(.single(ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji)))
|
||||
strongSelf.chatPresentationDataPromise.set(.single(ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji)))
|
||||
|
||||
strongSelf.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings)
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
self.searchResult = searchResult
|
||||
self.searchState = searchState
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
|
||||
self.listNode = ListView()
|
||||
self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
@ -292,8 +292,8 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
let previousTheme = self.presentationData.theme
|
||||
self.presentationData = presentationData
|
||||
self.presentationDataPromise.set(.single(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)))
|
||||
|
||||
self.presentationDataPromise.set(.single(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)))
|
||||
|
||||
self.listNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||
itemHeaderNode.updateTheme(theme: presentationData.theme)
|
||||
|
@ -265,9 +265,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
self.toMessageTextNode.attributedText = toAttributedText
|
||||
}
|
||||
} else {
|
||||
self.fromMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.Conversation_InputTextPlaceholder, attributes: [NSAttributedString.Key.foregroundColor: self.presentationData.theme.chat.inputPanel.inputPlaceholderColor, NSAttributedString.Key.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)])
|
||||
self.fromMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.Conversation_InputTextPlaceholder, attributes: [NSAttributedString.Key.foregroundColor: self.presentationData.theme.chat.inputPanel.inputPlaceholderColor, NSAttributedString.Key.font: Font.regular(self.presentationData.chatFontSize.baseDisplaySize)])
|
||||
|
||||
self.toMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ForwardedMessages(Int32(forwardedCount ?? 0)), attributes: [NSAttributedString.Key.foregroundColor: self.presentationData.theme.chat.message.outgoing.primaryTextColor, NSAttributedString.Key.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)])
|
||||
self.toMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ForwardedMessages(Int32(forwardedCount ?? 0)), attributes: [NSAttributedString.Key.foregroundColor: self.presentationData.theme.chat.message.outgoing.primaryTextColor, NSAttributedString.Key.font: Font.regular(self.presentationData.chatFontSize.baseDisplaySize)])
|
||||
}
|
||||
self.messageBackgroundNode.contentMode = .scaleToFill
|
||||
|
||||
|
@ -24,7 +24,7 @@ final class ChatSlowmodeHintController: TooltipController {
|
||||
init(presentationData: PresentationData, slowmodeState: ChatSlowmodeState) {
|
||||
self.strings = presentationData.strings
|
||||
self.slowmodeState = slowmodeState
|
||||
super.init(content: .text(timeoutValue(strings: presentationData.strings, slowmodeState: slowmodeState)), baseFontSize: presentationData.fontSize.baseDisplaySize, timeout: 2.0, dismissByTapOutside: false, dismissByTapOutsideSource: true)
|
||||
super.init(content: .text(timeoutValue(strings: presentationData.strings, slowmodeState: slowmodeState)), baseFontSize: presentationData.listsFontSize.baseDisplaySize, timeout: 2.0, dismissByTapOutside: false, dismissByTapOutsideSource: true)
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
|
@ -99,7 +99,9 @@ func legacyInputMicPalette(from theme: PresentationTheme) -> TGModernConversatio
|
||||
return TGModernConversationInputMicPallete(dark: theme.overallDarkAppearance, buttonColor: inputPanelTheme.actionControlFillColor, iconColor: inputPanelTheme.actionControlForegroundColor, backgroundColor: inputPanelTheme.panelBackgroundColor, borderColor: inputPanelTheme.panelSeparatorColor, lock: inputPanelTheme.panelControlAccentColor, textColor: inputPanelTheme.primaryTextColor, secondaryTextColor: inputPanelTheme.secondaryTextColor, recording: inputPanelTheme.mediaRecordingDotColor)
|
||||
}
|
||||
|
||||
func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, context: AccountContext, peerId: PeerId, slowmodeState: ChatSlowmodeState?, send: @escaping (EnqueueMessage) -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void) -> InstantVideoController {
|
||||
func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, context: AccountContext, peerId: PeerId, slowmodeState: ChatSlowmodeState?, hasSchedule: Bool, send: @escaping (EnqueueMessage) -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) -> InstantVideoController {
|
||||
let isSecretChat = peerId.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let legacyController = InstantVideoController(presentation: .custom, theme: theme)
|
||||
legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .all)
|
||||
legacyController.lockOrientation = true
|
||||
@ -127,8 +129,13 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect,
|
||||
let node = ChatSendButtonRadialStatusView(color: theme.chat.inputPanel.panelControlAccentColor)
|
||||
node.slowmodeState = slowmodeState
|
||||
return node
|
||||
})!
|
||||
controller.finishedWithVideo = { videoUrl, previewImage, _, duration, dimensions, liveUploadData, adjustments in
|
||||
}, canSendSilently: !isSecretChat, canSchedule: hasSchedule, reminder: peerId == context.account.peerId)!
|
||||
controller.presentScheduleController = { done in
|
||||
presentSchedulePicker { time in
|
||||
done?(time)
|
||||
}
|
||||
}
|
||||
controller.finishedWithVideo = { videoUrl, previewImage, _, duration, dimensions, liveUploadData, adjustments, isSilent, scheduleTimestamp in
|
||||
guard let videoUrl = videoUrl else {
|
||||
return
|
||||
}
|
||||
@ -179,8 +186,29 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect,
|
||||
}
|
||||
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.FileName(fileName: "video.mp4"), .Video(duration: Int(finalDuration), size: PixelDimensions(finalDimensions), flags: [.instantRoundVideo])])
|
||||
let attributes: [MessageAttribute] = []
|
||||
send(.message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
var message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil)
|
||||
|
||||
let scheduleTime: Int32? = scheduleTimestamp > 0 ? scheduleTimestamp : nil
|
||||
|
||||
message = message.withUpdatedAttributes { attributes in
|
||||
var attributes = attributes
|
||||
for i in (0 ..< attributes.count).reversed() {
|
||||
if attributes[i] is NotificationInfoMessageAttribute {
|
||||
attributes.remove(at: i)
|
||||
} else if let _ = scheduleTime, attributes[i] is OutgoingScheduleInfoMessageAttribute {
|
||||
attributes.remove(at: i)
|
||||
}
|
||||
}
|
||||
if isSilent {
|
||||
attributes.append(NotificationInfoMessageAttribute(flags: .muted))
|
||||
}
|
||||
if let scheduleTime = scheduleTime {
|
||||
attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: scheduleTime))
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
|
||||
send(message)
|
||||
}
|
||||
controller.didDismiss = { [weak legacyController] in
|
||||
if let legacyController = legacyController {
|
||||
|
@ -339,12 +339,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
let controller = ShareController(context: params.context, subject: .media(.standalone(media: file)), immediateExternalShare: true)
|
||||
params.present(controller, nil)
|
||||
} else if let rootController = params.navigationController?.view.window?.rootViewController {
|
||||
if let fileName = file.fileName, fileName.hasSuffix(".svgbg") {
|
||||
let controller = WallpaperGalleryController(context: params.context, source: .wallpaper(.file(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: true, isDark: false, slug: "", file: file, settings: WallpaperSettings()), nil, nil, nil, nil, nil, nil))
|
||||
params.present(controller, nil)
|
||||
} else {
|
||||
presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file)
|
||||
}
|
||||
presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file)
|
||||
}
|
||||
return true
|
||||
case let .audio(file):
|
||||
|
@ -49,10 +49,10 @@ final class PaneSearchContainerNode: ASDisplayNode {
|
||||
self.controllerInteraction = controllerInteraction
|
||||
self.inputNodeInteraction = inputNodeInteraction
|
||||
switch mode {
|
||||
case .gif:
|
||||
self.contentNode = GifPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction, trendingPromise: trendingGifsPromise)
|
||||
case .sticker:
|
||||
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction)
|
||||
case .gif:
|
||||
self.contentNode = GifPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction, trendingPromise: trendingGifsPromise)
|
||||
case .sticker, .trending:
|
||||
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction)
|
||||
}
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
|
||||
@ -92,10 +92,10 @@ final class PaneSearchContainerNode: ASDisplayNode {
|
||||
|
||||
let placeholder: String
|
||||
switch mode {
|
||||
case .gif:
|
||||
placeholder = strings.Gif_Search
|
||||
case .sticker:
|
||||
placeholder = strings.Stickers_Search
|
||||
case .gif:
|
||||
placeholder = strings.Gif_Search
|
||||
case .sticker, .trending:
|
||||
placeholder = strings.Stickers_Search
|
||||
}
|
||||
self.searchBar.placeholderString = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.chat.inputMediaPanel.stickersSearchPlaceholderColor)
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ class PeerMediaCollectionControllerNode: ASDisplayNode {
|
||||
self.historyEmptyNode = PeerMediaCollectionEmptyNode(mode: self.mediaCollectionInterfaceState.mode, theme: self.presentationData.theme, strings: self.presentationData.strings)
|
||||
self.historyEmptyNode.isHidden = true
|
||||
|
||||
self.chatPresentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: self.presentationData.fontSize, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false)
|
||||
self.chatPresentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: self.presentationData.listsFontSize, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false)
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -84,8 +84,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
self.segmentedControlNode = nil
|
||||
}
|
||||
|
||||
|
||||
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, controlsHistoryPreload: false, mode: .peers(filter: filter), theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
self.chatListNode = ChatListNode(context: context, groupId: .root, previewing: false, controlsHistoryPreload: false, mode: .peers(filter: filter), theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
|
||||
super.init()
|
||||
|
||||
@ -145,7 +144,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
private func updateThemeAndStrings() {
|
||||
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
self.searchDisplayController?.updatePresentationData(self.presentationData)
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
|
||||
self.toolbarBackgroundNode?.backgroundColor = self.presentationData.theme.rootController.navigationBar.backgroundColor
|
||||
self.toolbarSeparatorNode?.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
|
||||
|
Binary file not shown.
@ -598,7 +598,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
resolvedText = .inProgress(nil)
|
||||
case .terminated:
|
||||
resolvedText = .none
|
||||
case let .active(timestamp, _, _):
|
||||
case .active(let timestamp, _, _), .reconnecting(let timestamp, _, _):
|
||||
resolvedText = .inProgress(timestamp)
|
||||
}
|
||||
} else {
|
||||
@ -654,15 +654,29 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
|
||||
self.updateNotificationTokensRegistration()
|
||||
|
||||
if applicationBindings.isMainApp && false {
|
||||
if applicationBindings.isMainApp {
|
||||
self.widgetDataContext = WidgetDataContext(basePath: self.basePath, activeAccount: self.activeAccounts
|
||||
|> map { primary, _, _ in
|
||||
return primary
|
||||
}, presentationData: self.presentationData)
|
||||
self.spotlightDataContext = SpotlightDataContext(accounts: self.activeAccounts |> map { _, accounts, _ in
|
||||
|
||||
let enableSpotlight = accountManager.sharedData(keys: Set([ApplicationSpecificSharedDataKeys.intentsSettings]))
|
||||
|> map { sharedData -> Bool in
|
||||
let intentsSettings: IntentsSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.intentsSettings] as? IntentsSettings ?? .defaultSettings
|
||||
return intentsSettings.contacts
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
self.spotlightDataContext = SpotlightDataContext(appBasePath: applicationBindings.containerPath, accountManager: accountManager, accounts: combineLatest(enableSpotlight, self.activeAccounts
|
||||
|> map { _, accounts, _ in
|
||||
return accounts.map { _, account, _ in
|
||||
return account
|
||||
}
|
||||
}) |> map { enableSpotlight, accounts in
|
||||
if enableSpotlight {
|
||||
return accounts
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -22,39 +22,198 @@ private let roundCorners = { () -> UIImage in
|
||||
return image
|
||||
}()
|
||||
|
||||
private struct SpotlightAccountContact: Equatable, Codable {
|
||||
var id: Int64
|
||||
var title: String
|
||||
var avatarPath: String?
|
||||
private struct SpotlightIndexStorageItem: Codable, Equatable {
|
||||
var firstName: String
|
||||
var lastName: String
|
||||
var avatarSourcePath: String?
|
||||
}
|
||||
|
||||
private func manageableSpotlightContacts(accounts: Signal<[Account], NoError>) -> Signal<[Int64: SpotlightAccountContact], NoError> {
|
||||
let queue = Queue()
|
||||
return accounts
|
||||
|> mapToSignal { accounts -> Signal<[[SpotlightAccountContact]], NoError> in
|
||||
return combineLatest(queue: queue, accounts.map { account -> Signal<[SpotlightAccountContact], NoError> in
|
||||
return account.postbox.contactPeersView(accountPeerId: account.peerId, includePresences: false)
|
||||
|> map { view -> [SpotlightAccountContact] in
|
||||
var result: [SpotlightAccountContact] = []
|
||||
for peer in view.peers {
|
||||
if let user = peer as? TelegramUser {
|
||||
result.append(SpotlightAccountContact(id: user.id.toInt64(), title: user.debugDisplayTitle, avatarPath: smallestImageRepresentation(user.photo).flatMap { representation in
|
||||
return account.postbox.mediaBox.resourcePath(representation.resource)
|
||||
}))
|
||||
private final class SpotlightIndexStorage {
|
||||
private let appBasePath: String
|
||||
private let basePath: String
|
||||
private var items: [PeerId: SpotlightIndexStorageItem] = [:]
|
||||
|
||||
init(appBasePath: String, basePath: String) {
|
||||
self.appBasePath = appBasePath
|
||||
self.basePath = basePath
|
||||
|
||||
let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
self.reload()
|
||||
|
||||
if self.items.isEmpty {
|
||||
CSSearchableIndex.default().deleteSearchableItems(withDomainIdentifiers: ["telegram-contacts"], completionHandler: { _ in })
|
||||
}
|
||||
}
|
||||
|
||||
private func path(peerId: PeerId) -> String {
|
||||
return self.basePath + "/p:\(UInt64(bitPattern: peerId.toInt64()))"
|
||||
}
|
||||
|
||||
private func reload() {
|
||||
self.items.removeAll()
|
||||
|
||||
guard let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: self.basePath), includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsSubdirectoryDescendants], errorHandler: nil) else {
|
||||
return
|
||||
}
|
||||
|
||||
while let item = enumerator.nextObject() {
|
||||
guard let url = item as? NSURL else {
|
||||
continue
|
||||
}
|
||||
guard let resourceValues = try? url.resourceValues(forKeys: [.isDirectoryKey]) else {
|
||||
continue
|
||||
}
|
||||
if let value = resourceValues[.isDirectoryKey] as? Bool, !value {
|
||||
continue
|
||||
}
|
||||
if let path = url.path, let directoryName = url.lastPathComponent, directoryName.hasPrefix("p:") {
|
||||
let peerIdString = directoryName[directoryName.index(directoryName.startIndex, offsetBy: 2)...]
|
||||
if let peerIdValue = UInt64(peerIdString) {
|
||||
let peerId = PeerId(Int64(bitPattern: peerIdValue))
|
||||
|
||||
let item: SpotlightIndexStorageItem
|
||||
if let itemData = try? Data(contentsOf: URL(fileURLWithPath: path + "/data.json")), let decodedItem = try? JSONDecoder().decode(SpotlightIndexStorageItem.self, from: itemData) {
|
||||
item = decodedItem
|
||||
} else {
|
||||
let _ = try? FileManager.default.removeItem(atPath: path + "/data.json")
|
||||
let _ = try? FileManager.default.removeItem(atPath: path + "/avatar.png")
|
||||
item = SpotlightIndexStorageItem(firstName: "", lastName: "", avatarSourcePath: nil)
|
||||
}
|
||||
|
||||
self.items[peerId] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func update(items: [PeerId: SpotlightIndexStorageItem]) {
|
||||
let validPeerIds = Set(items.keys)
|
||||
var removePeerIds: [PeerId] = []
|
||||
for (peerId, item) in self.items {
|
||||
if !validPeerIds.contains(peerId) {
|
||||
removePeerIds.append(peerId)
|
||||
}
|
||||
}
|
||||
if !removePeerIds.isEmpty {
|
||||
for peerId in removePeerIds {
|
||||
let _ = try? FileManager.default.removeItem(atPath: self.path(peerId: peerId))
|
||||
self.items.removeValue(forKey: peerId)
|
||||
}
|
||||
|
||||
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: removePeerIds.map { peerId in
|
||||
return "contact-\(peerId.toInt64())"
|
||||
})
|
||||
}
|
||||
|
||||
var addToIndexItems: [CSSearchableItem] = []
|
||||
|
||||
for (peerId, item) in items {
|
||||
let previousItem = self.items[peerId]
|
||||
if previousItem != item {
|
||||
var updatedAvatarSourcePath: String?
|
||||
if let avatarSourcePath = item.avatarSourcePath, let _ = fileSize(self.appBasePath + "/" + avatarSourcePath) {
|
||||
updatedAvatarSourcePath = avatarSourcePath
|
||||
}
|
||||
|
||||
var encodeItem = item
|
||||
encodeItem.avatarSourcePath = updatedAvatarSourcePath
|
||||
|
||||
if encodeItem == previousItem {
|
||||
continue
|
||||
}
|
||||
|
||||
print("Spotlight: updating \(item.firstName) \(item.lastName)")
|
||||
let path = self.path(peerId: peerId)
|
||||
let _ = try? FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
var resolvedAvatarPath: String?
|
||||
if previousItem?.avatarSourcePath != updatedAvatarSourcePath {
|
||||
let avatarPath = path + "/avatar.png"
|
||||
let _ = try? FileManager.default.removeItem(atPath: avatarPath)
|
||||
|
||||
if let updatedAvatarSourcePathValue = updatedAvatarSourcePath, let avatarData = try? Data(contentsOf: URL(fileURLWithPath: self.appBasePath + "/" + updatedAvatarSourcePathValue)), let image = UIImage(data: avatarData) {
|
||||
let size = CGSize(width: 120.0, height: 120.0)
|
||||
let context = DrawingContext(size: size, scale: 1.0, clear: true)
|
||||
context.withFlippedContext { c in
|
||||
c.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
||||
c.setBlendMode(.destinationOut)
|
||||
c.draw(roundCorners.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
||||
}
|
||||
if let resultImage = context.generateImage(), let resultData = resultImage.pngData(), let _ = try? resultData.write(to: URL(fileURLWithPath: avatarPath)) {
|
||||
resolvedAvatarPath = avatarPath
|
||||
} else {
|
||||
updatedAvatarSourcePath = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let itemDataPath = path + "/data.json"
|
||||
|
||||
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
|
||||
attributeSet.version = "\(UInt64.random(in: 0 ..< UInt64.max))"
|
||||
if !item.firstName.isEmpty && !item.lastName.isEmpty {
|
||||
attributeSet.title = "\(item.firstName) \(item.lastName)"
|
||||
} else if !item.firstName.isEmpty {
|
||||
attributeSet.title = item.firstName
|
||||
} else {
|
||||
attributeSet.title = item.lastName
|
||||
}
|
||||
attributeSet.thumbnailURL = resolvedAvatarPath.flatMap(URL.init(fileURLWithPath:))
|
||||
let indexItem = CSSearchableItem(uniqueIdentifier: "contact-\(peerId.toInt64())", domainIdentifier: "telegram-contacts", attributeSet: attributeSet)
|
||||
addToIndexItems.append(indexItem)
|
||||
|
||||
encodeItem.avatarSourcePath = updatedAvatarSourcePath
|
||||
if let data = try? JSONEncoder().encode(encodeItem) {
|
||||
let _ = try? data.write(to: URL(fileURLWithPath: itemDataPath), options: [.atomic])
|
||||
}
|
||||
|
||||
self.items[peerId] = item
|
||||
}
|
||||
}
|
||||
|
||||
if !addToIndexItems.isEmpty {
|
||||
CSSearchableIndex.default().indexSearchableItems(addToIndexItems, completionHandler: { error in
|
||||
if let error = error {
|
||||
Logger.shared.log("CSSearchableIndex", "indexSearchableItems error: \(error)")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func manageableSpotlightContacts(appBasePath: String, accounts: Signal<[Account], NoError>) -> Signal<[PeerId: SpotlightIndexStorageItem], NoError> {
|
||||
let queue = Queue()
|
||||
return accounts
|
||||
|> mapToSignal { accounts -> Signal<[[PeerId: SpotlightIndexStorageItem]], NoError> in
|
||||
return combineLatest(queue: queue, accounts.map { account -> Signal<[PeerId: SpotlightIndexStorageItem], NoError> in
|
||||
return account.postbox.contactPeersView(accountPeerId: account.peerId, includePresences: false)
|
||||
|> map { view -> [PeerId: SpotlightIndexStorageItem] in
|
||||
var result: [PeerId: SpotlightIndexStorageItem] = [:]
|
||||
for peer in view.peers {
|
||||
if let user = peer as? TelegramUser {
|
||||
let avatarSourcePath = smallestImageRepresentation(user.photo).flatMap { representation -> String? in
|
||||
let resourcePath = account.postbox.mediaBox.resourcePath(representation.resource)
|
||||
if resourcePath.hasPrefix(appBasePath + "/") {
|
||||
return String(resourcePath[resourcePath.index(resourcePath.startIndex, offsetBy: appBasePath.count + 1)...])
|
||||
} else {
|
||||
return resourcePath
|
||||
}
|
||||
}
|
||||
result[user.id] = SpotlightIndexStorageItem(firstName: user.firstName ?? "", lastName: user.lastName ?? "", avatarSourcePath: avatarSourcePath)
|
||||
}
|
||||
}
|
||||
result.sort(by: { $0.id < $1.id })
|
||||
return result
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
})
|
||||
}
|
||||
|> map { accountContacts -> [Int64: SpotlightAccountContact] in
|
||||
var result: [Int64: SpotlightAccountContact] = [:]
|
||||
|> map { accountContacts -> [PeerId: SpotlightIndexStorageItem] in
|
||||
var result: [PeerId: SpotlightIndexStorageItem] = [:]
|
||||
for singleAccountContacts in accountContacts {
|
||||
for contact in singleAccountContacts {
|
||||
if result[contact.id] == nil {
|
||||
result[contact.id] = contact
|
||||
for (peerId, contact) in singleAccountContacts {
|
||||
if result[peerId] == nil {
|
||||
result[peerId] = contact
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,76 +221,21 @@ private func manageableSpotlightContacts(accounts: Signal<[Account], NoError>) -
|
||||
}
|
||||
}
|
||||
|
||||
private final class SpotlightContactContext {
|
||||
private let indexQueue: Queue
|
||||
private let disposable = MetaDisposable()
|
||||
private var contact: SpotlightAccountContact?
|
||||
|
||||
init(indexQueue: Queue) {
|
||||
self.indexQueue = indexQueue
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
func update(contact: SpotlightAccountContact) {
|
||||
if self.contact == contact {
|
||||
return
|
||||
}
|
||||
let photoUpdated = self.contact?.avatarPath != contact.avatarPath
|
||||
self.contact = contact
|
||||
|
||||
let indexQueue = self.indexQueue
|
||||
let indexSignal: Signal<Never, NoError> = Signal { subscriber in
|
||||
indexQueue.async {
|
||||
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
|
||||
attributeSet.title = contact.title
|
||||
if let avatarPath = contact.avatarPath, let avatarData = try? Data(contentsOf: URL(fileURLWithPath: avatarPath)), let image = UIImage(data: avatarData) {
|
||||
let size = CGSize(width: 120.0, height: 120.0)
|
||||
let context = DrawingContext(size: size, scale: 1.0, clear: true)
|
||||
context.withFlippedContext { c in
|
||||
c.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
||||
c.setBlendMode(.destinationOut)
|
||||
c.draw(roundCorners.cgImage!, in: CGRect(origin: CGPoint(), size: size))
|
||||
}
|
||||
if let resultImage = context.generateImage(), let resultData = resultImage.pngData() {
|
||||
attributeSet.thumbnailData = resultData
|
||||
}
|
||||
}
|
||||
let item = CSSearchableItem(uniqueIdentifier: "contact-\(contact.id)", domainIdentifier: "telegram-contacts", attributeSet: attributeSet)
|
||||
Logger.shared.log("SpotlightDataContext", "index \(contact.id) title: \(contact.title)")
|
||||
CSSearchableIndex.default().indexSearchableItems([item], completionHandler: { error in
|
||||
if let error = error {
|
||||
Logger.shared.log("CSSearchableIndex", "error: \(error)")
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
||||
self.disposable.set(indexSignal.start())
|
||||
}
|
||||
}
|
||||
|
||||
private final class SpotlightDataContextImpl {
|
||||
private let queue: Queue
|
||||
private let indexQueue: Queue = Queue()
|
||||
private var contactContexts: [Int64: SpotlightContactContext] = [:]
|
||||
private let appBasePath: String
|
||||
private let accountManager: AccountManager
|
||||
private let indexStorage: SpotlightIndexStorage
|
||||
|
||||
private var listDisposable: Disposable?
|
||||
|
||||
init(queue: Queue, accounts: Signal<[Account], NoError>) {
|
||||
init(queue: Queue, appBasePath: String, accountManager: AccountManager, accounts: Signal<[Account], NoError>) {
|
||||
self.queue = queue
|
||||
self.appBasePath = appBasePath
|
||||
self.accountManager = accountManager
|
||||
self.indexStorage = SpotlightIndexStorage(appBasePath: appBasePath, basePath: accountManager.basePath + "/spotlight")
|
||||
|
||||
self.indexQueue.async {
|
||||
Logger.shared.log("SpotlightDataContext", "deleteSearchableItems")
|
||||
CSSearchableIndex.default().deleteSearchableItems(withDomainIdentifiers: ["telegram-contacts"], completionHandler: { _ in })
|
||||
}
|
||||
|
||||
self.listDisposable = (manageableSpotlightContacts(accounts: accounts
|
||||
self.listDisposable = (manageableSpotlightContacts(appBasePath: appBasePath, accounts: accounts
|
||||
|> map { accounts in
|
||||
return accounts.sorted(by: { $0.id < $1.id })
|
||||
}
|
||||
@ -146,48 +250,26 @@ private final class SpotlightDataContextImpl {
|
||||
}
|
||||
return true
|
||||
}))
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] contacts in
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] items in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.updateContacts(contacts: contacts)
|
||||
strongSelf.updateContacts(items: items)
|
||||
})
|
||||
}
|
||||
|
||||
private func updateContacts(contacts: [Int64: SpotlightAccountContact]) {
|
||||
var validIds = Set<Int64>()
|
||||
for (_, contact) in contacts {
|
||||
validIds.insert(contact.id)
|
||||
|
||||
let context: SpotlightContactContext
|
||||
if let current = self.contactContexts[contact.id] {
|
||||
context = current
|
||||
} else {
|
||||
context = SpotlightContactContext(indexQueue: self.indexQueue)
|
||||
self.contactContexts[contact.id] = context
|
||||
}
|
||||
context.update(contact: contact)
|
||||
}
|
||||
|
||||
var removeIds: [Int64] = []
|
||||
for id in self.contactContexts.keys {
|
||||
if !validIds.contains(id) {
|
||||
removeIds.append(id)
|
||||
}
|
||||
}
|
||||
for id in removeIds {
|
||||
self.contactContexts.removeValue(forKey: id)
|
||||
}
|
||||
private func updateContacts(items: [PeerId: SpotlightIndexStorageItem]) {
|
||||
self.indexStorage.update(items: items)
|
||||
}
|
||||
}
|
||||
|
||||
public final class SpotlightDataContext {
|
||||
private let impl: QueueLocalObject<SpotlightDataContextImpl>
|
||||
|
||||
public init(accounts: Signal<[Account], NoError>) {
|
||||
public init(appBasePath: String, accountManager: AccountManager, accounts: Signal<[Account], NoError>) {
|
||||
let queue = Queue()
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return SpotlightDataContextImpl(queue: queue, accounts: accounts)
|
||||
return SpotlightDataContextImpl(queue: queue, appBasePath: appBasePath, accountManager: accountManager, accounts: accounts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
|
||||
self.trendingPane = ChatMediaInputTrendingPane(context: context, controllerInteraction: controllerInteraction, getItemIsPreviewed: { [weak inputNodeInteraction] item in
|
||||
return inputNodeInteraction?.previewedStickerPackItem == .pack(item)
|
||||
})
|
||||
}, isPane: false)
|
||||
|
||||
self.gridNode = GridNode()
|
||||
|
||||
|
@ -139,7 +139,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager {
|
||||
theme = updatedTheme
|
||||
}
|
||||
|
||||
return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
})
|
||||
}).start()
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager {
|
||||
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
|
||||
themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper
|
||||
themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: current.themeSpecificAccentColors[themeReference.index])] = updatedWallpaper
|
||||
return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
|
||||
})).start()
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,17 @@ public enum MediaAutoDownloadNetworkType {
|
||||
case cellular
|
||||
}
|
||||
|
||||
public extension MediaAutoDownloadNetworkType {
|
||||
init(_ networkType: NetworkType) {
|
||||
switch networkType {
|
||||
case .none, .cellular:
|
||||
self = .cellular
|
||||
case .wifi:
|
||||
self = .wifi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MediaAutoDownloadPreset: Int32 {
|
||||
case low
|
||||
case medium
|
||||
|
@ -529,6 +529,7 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper]
|
||||
public var useSystemFont: Bool
|
||||
public var fontSize: PresentationFontSize
|
||||
public var listsFontSize: PresentationFontSize
|
||||
public var automaticThemeSwitchSetting: AutomaticThemeSwitchSetting
|
||||
public var largeEmoji: Bool
|
||||
public var disableAnimations: Bool
|
||||
@ -569,15 +570,16 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
}
|
||||
|
||||
public static var defaultSettings: PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true)
|
||||
return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, listsFontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true)
|
||||
}
|
||||
|
||||
public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) {
|
||||
public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) {
|
||||
self.theme = theme
|
||||
self.themeSpecificAccentColors = themeSpecificAccentColors
|
||||
self.themeSpecificChatWallpapers = themeSpecificChatWallpapers
|
||||
self.useSystemFont = useSystemFont
|
||||
self.fontSize = fontSize
|
||||
self.listsFontSize = listsFontSize
|
||||
self.automaticThemeSwitchSetting = automaticThemeSwitchSetting
|
||||
self.largeEmoji = largeEmoji
|
||||
self.disableAnimations = disableAnimations
|
||||
@ -599,7 +601,9 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
})
|
||||
|
||||
self.useSystemFont = decoder.decodeInt32ForKey("useSystemFont", orElse: 1) != 0
|
||||
self.fontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("f", orElse: PresentationFontSize.regular.rawValue)) ?? .regular
|
||||
let fontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("f", orElse: PresentationFontSize.regular.rawValue)) ?? .regular
|
||||
self.fontSize = fontSize
|
||||
self.listsFontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("lf", orElse: PresentationFontSize.regular.rawValue)) ?? fontSize
|
||||
self.automaticThemeSwitchSetting = (decoder.decodeObjectForKey("automaticThemeSwitchSetting", decoder: { AutomaticThemeSwitchSetting(decoder: $0) }) as? AutomaticThemeSwitchSetting) ?? AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night))
|
||||
self.largeEmoji = decoder.decodeBoolForKey("largeEmoji", orElse: true)
|
||||
self.disableAnimations = decoder.decodeBoolForKey("disableAnimations", orElse: true)
|
||||
@ -615,6 +619,7 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
})
|
||||
encoder.encodeInt32(self.useSystemFont ? 1 : 0, forKey: "useSystemFont")
|
||||
encoder.encodeInt32(self.fontSize.rawValue, forKey: "f")
|
||||
encoder.encodeInt32(self.listsFontSize.rawValue, forKey: "lf")
|
||||
encoder.encodeObject(self.automaticThemeSwitchSetting, forKey: "automaticThemeSwitchSetting")
|
||||
encoder.encodeBool(self.largeEmoji, forKey: "largeEmoji")
|
||||
encoder.encodeBool(self.disableAnimations, forKey: "disableAnimations")
|
||||
@ -629,39 +634,39 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
}
|
||||
|
||||
public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool {
|
||||
return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations
|
||||
return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations
|
||||
}
|
||||
|
||||
public func withUpdatedTheme(_ theme: PresentationThemeReference) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedThemeSpecificAccentColors(_ themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedThemeSpecificChatWallpapers(_ themeSpecificChatWallpapers: [Int64: TelegramWallpaper]) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedUseSystemFont(_ useSystemFont: Bool) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedFontSize(_ fontSize: PresentationFontSize) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
public func withUpdatedFontSizes(fontSize: PresentationFontSize, listsFontSize: PresentationFontSize) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedAutomaticThemeSwitchSetting(_ automaticThemeSwitchSetting: AutomaticThemeSwitchSetting) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedLargeEmoji(_ largeEmoji: Bool) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations)
|
||||
}
|
||||
|
||||
public func withUpdatedDisableAnimations(_ disableAnimations: Bool) -> PresentationThemeSettings {
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations)
|
||||
return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,7 @@ private let setupLogs: Bool = {
|
||||
public enum OngoingCallContextState {
|
||||
case initializing
|
||||
case connected
|
||||
case reconnecting
|
||||
case failed
|
||||
}
|
||||
|
||||
@ -151,6 +152,8 @@ public final class OngoingCallContext {
|
||||
return .connected
|
||||
case .failed:
|
||||
return .failed
|
||||
case .reconnecting:
|
||||
return .reconnecting
|
||||
default:
|
||||
return .failed
|
||||
}
|
||||
|
Binary file not shown.
@ -448,12 +448,12 @@ public final class WalletStrings: Equatable {
|
||||
public var Wallet_SecureStorageReset_Title: String { return self._s[218]! }
|
||||
public var Wallet_Receive_CommentHeader: String { return self._s[219]! }
|
||||
public var Wallet_Info_ReceiveGrams: String { return self._s[220]! }
|
||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||
let form = getPluralizationForm(self.lc, value)
|
||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
}
|
||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||
let form = getPluralizationForm(self.lc, value)
|
||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
|
@ -18,7 +18,8 @@
|
||||
typedef NS_ENUM(int32_t, OngoingCallState) {
|
||||
OngoingCallStateInitializing,
|
||||
OngoingCallStateConnected,
|
||||
OngoingCallStateFailed
|
||||
OngoingCallStateFailed,
|
||||
OngoingCallStateReconnecting
|
||||
};
|
||||
|
||||
typedef NS_ENUM(int32_t, OngoingCallNetworkType) {
|
||||
|
@ -374,6 +374,9 @@ static int callControllerDataSavingForType(OngoingCallDataSaving type) {
|
||||
case tgvoip::STATE_FAILED:
|
||||
callState = OngoingCallStateFailed;
|
||||
break;
|
||||
case tgvoip::STATE_RECONNECTING:
|
||||
callState = OngoingCallStateReconnecting;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user