Merge commit 'a2fcff1b35c8f117c6bb3a068dc28bbe52530a1a'

This commit is contained in:
Peter 2019-10-04 13:43:58 +04:00
commit c3db8f3146
82 changed files with 4008 additions and 3895 deletions

2
.gitignore vendored
View File

@ -31,3 +31,5 @@ Project.xcodeproj/*
Watch/Watch.xcodeproj/*
AppBundle.xcworkspace/*
tools/buck
*.xcodeproj
!*_Xcode.xcodeproj

View File

@ -256,6 +256,7 @@
<string>firefox-focus</string>
<string>ddgQuickLink</string>
<string>moovit</string>
<string>alook</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>

View File

@ -4056,6 +4056,7 @@ Unused sets are archived when you add more.";
"LogoutOptions.ContactSupportText" = "Tell us about any issues; logging out doesn't usually help.";
"LogoutOptions.LogOut" = "Log Out";
"LogoutOptions.LogOutInfo" = "Remember, logging out kills all your Secret Chats.";
"LogoutOptions.LogOutWalletInfo" = "Logging out will cancel all your secret chats and unlink your Gram wallet from the app.";
"GroupPermission.PermissionGloballyDisabled" = "This permission is disabled in this group.";
@ -4778,8 +4779,8 @@ Any member of this group will be able to see messages in the channel.";
"Wallet.Info.YourBalance" = "your balance";
"Wallet.Info.Receive" = "Receive";
"Wallet.Info.Send" = "Send";
"Wallet.Info.RefreshErrorTitle" = "An Error Occurred";
"Wallet.Info.RefreshErrorText" = "The wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.RefreshErrorTitle" = "No network";
"Wallet.Info.RefreshErrorText" = "Couldn't refresh balance. Please make sure your internet connection is working and try again.";
"Wallet.Info.RefreshErrorNetworkText" = "The wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.UnknownTransaction" = "Empty Transaction";
"Wallet.Info.TransactionTo" = "to";
@ -4883,16 +4884,20 @@ Any member of this group will be able to see messages in the channel.";
"Wallet.Words.NotDoneText" = "You didn't have enough time to write those words down.";
"Wallet.Words.NotDoneOk" = "OK, Sorry";
"Wallet.Words.NotDoneResponse" = "Apologies Accepted";
"Wallet.Send.NetworkError" = "Network Error";
"Wallet.Send.ErrorNotEnoughFunds" = "Not Enough Funds";
"Wallet.Send.NetworkErrorTitle" = "No network";
"Wallet.Send.NetworkErrorText" = "Couldn't send grams. Please make sure your internet connection is working and try again.";
"Wallet.Send.ErrorNotEnoughFundsTitle" = "Insufficient Grams";
"Wallet.Send.ErrorNotEnoughFundsText" = "Unfortunately, your transfer couldn't be completed. You don't have enough grams.";
"Wallet.Send.ErrorInvalidAddress" = "Invalid wallet address. Please correct and try again.";
"Wallet.Send.ErrorDecryptionFailed" = "Please make sure that your device has a passcode set in iOS Settings and try again.";
"Wallet.Send.UninitializedTitle" = "Warning";
"Wallet.Send.UninitializedText" = "This address belongs to an empty wallet. Are you sure you want to transfer grams to it?";
"Wallet.Send.SendAnyway" = "Send Anyway";
"Wallet.Receive.CreateInvoice" = "Create Invoice";
"Wallet.Receive.CreateInvoiceInfo" = "You can specify amount and purpose of the payment to save the sender some time.";
"Conversation.WalletRequiredTitle" = "Gram Wallet Required";
"Conversation.WalletRequiredText" = "This link can be used to send money on the TON Blockchain. To do this, you need to set up a Gram wallet first.";
"Conversation.WalletRequiredNotNow" = "Not Now";
"Conversation.WalletRequiredSetup" = "Set Up";
"Wallet.CreateInvoice.Title" = "Create Invoice";

View File

@ -209,9 +209,7 @@ public func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: C
return
}
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId).lz4v"
let path = NSTemporaryDirectory() + "\(arc4random64()).lz4v"
guard let fileContext = ManagedFile(queue: nil, path: path, mode: .readwrite) else {
return
}

View File

@ -188,6 +188,8 @@ final class CallListControllerNode: ASDisplayNode {
private let callListDisposable = MetaDisposable()
private let listNode: ListView
private let leftOverlayNode: ASDisplayNode
private let rightOverlayNode: ASDisplayNode
private let emptyTextNode: ASTextNode
private let call: (PeerId) -> Void
@ -210,6 +212,10 @@ final class CallListControllerNode: ASDisplayNode {
self.listNode = ListView()
self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
self.leftOverlayNode = ASDisplayNode()
self.leftOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode = ASDisplayNode()
self.rightOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.emptyTextNode = ASTextNode()
self.emptyTextNode.alpha = 0.0
@ -385,6 +391,8 @@ final class CallListControllerNode: ASDisplayNode {
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, disableAnimations: Bool) {
if theme !== self.currentState.theme || strings !== self.currentState.strings || disableAnimations != self.currentState.disableAnimations {
self.leftOverlayNode.backgroundColor = theme.list.blocksBackgroundColor
self.rightOverlayNode.backgroundColor = theme.list.blocksBackgroundColor
switch self.mode {
case .tab:
self.backgroundColor = theme.chatList.backgroundColor
@ -536,7 +544,6 @@ final class CallListControllerNode: ASDisplayNode {
let size = layout.size
let contentRect = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom))
let textSize = self.emptyTextNode.measure(CGSize(width: size.width - 20.0, height: size.height))
transition.updateFrame(node: self.emptyTextNode, frame: CGRect(origin: CGPoint(x: contentRect.minX + floor((contentRect.width - textSize.width) / 2.0), y: contentRect.minY + floor((contentRect.height - textSize.height) / 2.0)), size: textSize))
}
@ -552,7 +559,7 @@ final class CallListControllerNode: ASDisplayNode {
self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height)
self.listNode.position = CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0)
updateLayout(layout, navigationBarHeight: navigationBarHeight, transition: transition)
self.updateLayout(layout, navigationBarHeight: navigationBarHeight, transition: transition)
var duration: Double = 0.0
var curve: UInt = 0

View File

@ -339,6 +339,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
private var peerPresenceManager: PeerPresenceStatusManager?
private var cachedChatListText: (String, String)?
private var cachedChatListSearchResult: CachedChatListSearchResult?
var layoutParams: (ChatListItem, first: Bool, last: Bool, firstWithHeader: Bool, nextIsPinned: Bool, ListViewItemLayoutParams, countersSize: CGFloat)?
@ -648,6 +649,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let currentItem = self.layoutParams?.0
let currentContentImageMedia = self.contentImageMedia
let currentChatListText = self.cachedChatListText
let currentChatListSearchResult = self.cachedChatListSearchResult
return { item, params, first, last, firstWithHeader, nextIsPinned in
@ -804,17 +806,56 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
}
var contentImageMedia: Media?
var chatListText: (String, String)?
var chatListSearchResult: CachedChatListSearchResult?
switch contentData {
case let .chat(itemPeer, _, _, messageText):
let messageText = messageText.replacingOccurrences(of: "\n\n", with: " ")
case let .chat(itemPeer, _, _, text):
var peerText: String?
if case .groupReference = item.content {
if let messagePeer = itemPeer.chatMainPeer {
peerText = messagePeer.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
} else if let message = message, let author = message.author as? TelegramUser, let peer = itemPeer.chatMainPeer, !(peer is TelegramUser) {
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
} else if !displayAsMessage {
peerText = author.id == account.peerId ? item.presentationData.strings.DialogList_You : author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
}
func foldLineBreaks(_ text: String, allowTwoLines: Bool) -> String {
var lines = text.split { $0.isNewline }
var startedBothLines = false
var result = ""
for line in lines {
if result.isEmpty {
result += line
} else {
if allowTwoLines && !startedBothLines {
result += "\n" + line
startedBothLines = true
} else {
result += " " + line
}
}
}
return result
}
let messageText: String
if let currentChatListText = currentChatListText, currentChatListText.0 == text {
messageText = currentChatListText.1
chatListText = currentChatListText
} else {
messageText = foldLineBreaks(text, allowTwoLines: peerText == nil)
chatListText = (text, messageText)
}
if inlineAuthorPrefix == nil, let embeddedState = embeddedState as? ChatEmbeddedInterfaceState {
hasDraft = true
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
attributedText = NSAttributedString(string: embeddedState.text.string.replacingOccurrences(of: "\n\n", with: " "), font: textFont, textColor: theme.messageTextColor)
attributedText = NSAttributedString(string: foldLineBreaks(embeddedState.text.string.replacingOccurrences(of: "\n\n", with: " "), allowTwoLines: false), font: textFont, textColor: theme.messageTextColor)
} else if let message = message {
let composedString: NSMutableAttributedString
if let inlineAuthorPrefix = inlineAuthorPrefix {
@ -829,37 +870,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if let cached = currentChatListSearchResult, cached.matches(text: composedString.string, searchQuery: searchQuery) {
chatListSearchResult = cached
} else {
var ranges: [Range<String.Index>] = []
let queryWords = searchQuery.split { !$0.isLetter }.filter { !$0.isEmpty }.map { $0.lowercased() }
let searchRange = composedString.string.startIndex ..< composedString.string.endIndex
composedString.string.enumerateSubstrings(in: searchRange, options: .byWords) { (substring, range, _, _) in
guard let substring = substring?.lowercased() else {
return
}
for word in queryWords {
var count = 0
inner: for (c1, c2) in zip(word, substring) {
if c1 != c2 {
break inner
}
count += 1
}
if count > 0 {
let length = Double(max(word.count, substring.count))
if length > 0 {
let difference = abs(length - Double(count))
let rating = difference / length
if rating < 0.33 {
ranges.append(range)
}
}
}
}
}
chatListSearchResult = CachedChatListSearchResult(text: composedString.string, searchQuery: searchQuery, resultRanges: ranges)
let (ranges, text) = findSubstringRanges(in: composedString.string, query: searchQuery)
chatListSearchResult = CachedChatListSearchResult(text: text, searchQuery: searchQuery, resultRanges: ranges)
}
} else {
chatListSearchResult = nil
@ -867,24 +879,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if let chatListSearchResult = chatListSearchResult {
for range in chatListSearchResult.resultRanges {
composedString.addAttribute(.foregroundColor, value: theme.messageHighlightedTextColor, range: NSRange(range, in: composedString.string))
composedString.addAttribute(.foregroundColor, value: theme.messageHighlightedTextColor, range: NSRange(range, in: chatListSearchResult.text))
}
}
attributedText = composedString
var peerText: String?
if case .groupReference = item.content {
if let messagePeer = itemPeer.chatMainPeer {
peerText = messagePeer.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
} else if let author = message.author as? TelegramUser, let peer = itemPeer.chatMainPeer, !(peer is TelegramUser) {
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
} else if !displayAsMessage {
peerText = author.id == account.peerId ? item.presentationData.strings.DialogList_You : author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
}
}
if let peerText = peerText {
authorAttributedString = NSAttributedString(string: peerText, font: textFont, textColor: theme.authorNameColor)
}
@ -1215,6 +1215,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if let strongSelf = self {
strongSelf.layoutParams = (item, first, last, firstWithHeader, nextIsPinned, params, countersSize)
strongSelf.contentImageMedia = contentImageMedia
strongSelf.cachedChatListText = chatListText
strongSelf.cachedChatListSearchResult = chatListSearchResult
strongSelf.contextContainer.frame = CGRect(origin: CGPoint(), size: layout.contentSize)

View File

@ -185,7 +185,7 @@ class CreatePollOptionActionItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -342,7 +342,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -105,7 +105,7 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo
}
var canCall = true
if let user = peer as? TelegramUser, let cachedUserData = transaction.getPeerCachedData(peerId: peerId) as? CachedUserData, !user.flags.contains(.isSupport) && cachedUserData.callsPrivate {
if let user = peer as? TelegramUser, let cachedUserData = transaction.getPeerCachedData(peerId: peerId) as? CachedUserData, user.flags.contains(.isSupport) || cachedUserData.callsPrivate {
canCall = false
}

View File

@ -17,6 +17,7 @@ public protocol ContainableController: class {
func combinedSupportedOrientations(currentOrientationToLock: UIInterfaceOrientationMask) -> ViewControllerSupportedOrientations
var deferScreenEdgeGestures: UIRectEdge { get }
var prefersOnScreenNavigationHidden: Bool { get }
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition)
func updateToInterfaceOrientation(_ orientation: UIInterfaceOrientation)

View File

@ -108,6 +108,9 @@ open class NavigationController: UINavigationController, ContainableController,
public var lockOrientation: Bool = false
public var deferScreenEdgeGestures: UIRectEdge = UIRectEdge()
public var prefersOnScreenNavigationHidden: Bool {
return (self.topViewController as? ViewController)?.prefersOnScreenNavigationHidden ?? false
}
private let mode: NavigationControllerMode
private var theme: NavigationControllerTheme
@ -153,6 +156,14 @@ open class NavigationController: UINavigationController, ContainableController,
return self._viewControllers.last
}
var topOverlayController: ViewController? {
if let overlayContainer = self.overlayContainers.last {
return overlayContainer.controller
} else {
return nil
}
}
private var _displayNode: ASDisplayNode?
public var displayNode: ASDisplayNode {
if let value = self._displayNode {

View File

@ -0,0 +1,43 @@
import UIKit
public func findSubstringRanges(in string: String, query: String) -> ([Range<String.Index>], String) {
var ranges: [Range<String.Index>] = []
let queryWords = query.split { !$0.isLetter && !$0.isNumber && $0 != "#" && $0 != "@" }.filter { !$0.isEmpty && !["#", "@"].contains($0) }.map { $0.lowercased() }
let text = string.lowercased()
let searchRange = text.startIndex ..< text.endIndex
text.enumerateSubstrings(in: searchRange, options: .byWords) { (substring, range, _, _) in
guard let substring = substring else {
return
}
for var word in queryWords {
var count = 0
var hasLeadingSymbol = false
if word.hasPrefix("#") || word.hasPrefix("@") {
hasLeadingSymbol = true
word.removeFirst()
}
inner: for (c1, c2) in zip(word, substring) {
if c1 != c2 {
break inner
}
count += 1
}
if count > 0 {
let length = Double(max(word.count, substring.count))
if length > 0 {
let difference = abs(length - Double(count))
let rating = difference / length
if rating < 0.33 {
var range = range
if hasLeadingSymbol && range.lowerBound > searchRange.lowerBound {
range = text.index(before: range.lowerBound)..<range.upperBound
}
ranges.append(range)
}
}
}
}
}
return (ranges, text)
}

View File

@ -453,41 +453,12 @@ public final class TextNodeLayout: NSObject {
return []
}
var ranges: [Range<String.Index>] = []
let queryWords = text.split { !$0.isLetter }.filter { !$0.isEmpty }.map { $0.lowercased() }
let text = attributedString.string.lowercased()
let searchRange = text.startIndex ..< text.endIndex
text.enumerateSubstrings(in: searchRange, options: .byWords) { (substring, range, _, _) in
guard let substring = substring else {
return
}
for word in queryWords {
var count = 0
inner: for (c1, c2) in zip(word, substring) {
if c1 != c2 {
break inner
}
count += 1
}
if count > 0 {
let length = Double(max(word.count, substring.count))
if length > 0 {
let difference = abs(length - Double(count))
let rating = difference / length
if rating < 0.33 {
ranges.append(range)
}
}
}
}
}
let (ranges, searchText) = findSubstringRanges(in: attributedString.string, query: text)
var result: [[CGRect]] = []
for stringRange in ranges {
var rects: [CGRect] = []
let range = NSRange(stringRange, in: text)
let range = NSRange(stringRange, in: searchText)
for line in self.lines {
let lineRange = NSIntersectionRange(range, line.range)
if lineRange.length != 0 {

View File

@ -1221,7 +1221,11 @@ public class Window1 {
}
private func collectPrefersOnScreenNavigationHidden() -> Bool {
var hidden = self.presentationContext.combinedPrefersOnScreenNavigationHidden()
var hidden = false
if let navigationController = self._rootController as? NavigationController, let overlayController = navigationController.topOverlayController {
hidden = hidden || overlayController.prefersOnScreenNavigationHidden
}
hidden = hidden || self.presentationContext.combinedPrefersOnScreenNavigationHidden()
for controller in self.topLevelOverlayControllers {
if let controller = controller as? ViewController {

View File

@ -467,7 +467,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
let separatorHeight = UIScreenPixel
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
let contentSize: CGSize
var insets: UIEdgeInsets
let itemBackgroundColor: UIColor

View File

@ -215,7 +215,7 @@ class ItemListPeerActionItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -686,7 +686,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -542,7 +542,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -357,7 +357,7 @@ open class ItemListControllerNode<Entry: ItemListNodeEntry>: ASDisplayNode, UISc
insets.top += navigationBarHeight
var addedInsets: UIEdgeInsets?
if case .tablet = layout.deviceMetrics.type, layout.size.width > 460.0 {
if layout.size.width > 480.0 {
let inset = max(20.0, floor((layout.size.width - 674.0) / 2.0))
insets.left += inset
insets.right += inset
@ -386,8 +386,8 @@ open class ItemListControllerNode<Entry: ItemListNodeEntry>: ASDisplayNode, UISc
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, duration: duration, curve: listViewCurve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.leftOverlayNode.frame = CGRect(x: 0.0, y: insets.top + 1.0, width: insets.left, height: layout.size.height - insets.top)
self.rightOverlayNode.frame = CGRect(x: layout.size.width - insets.right, y: insets.top + 1.0, width: insets.right, height: layout.size.height - insets.top)
self.leftOverlayNode.frame = CGRect(x: 0.0, y: 0.0, width: insets.left, height: layout.size.height)
self.rightOverlayNode.frame = CGRect(x: layout.size.width - insets.right, y: 0.0, width: insets.right, height: layout.size.height)
if let emptyStateNode = self.emptyStateNode {
var layout = layout

View File

@ -144,3 +144,7 @@ public func itemListNeighborsGroupedInsets(_ neighbors: ItemListNeighbors) -> UI
}
return UIEdgeInsets(top: topInset, left: 0.0, bottom: bottomInset, right: 0.0)
}
public func itemListHasRoundedBlockLayout(_ params: ListViewItemLayoutParams) -> Bool {
return params.width > 480.0
}

View File

@ -235,7 +235,7 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -220,7 +220,7 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
if strongSelf.maskNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -378,7 +378,7 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -291,7 +291,7 @@ class InfoItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
if let neighbors = neighbors {

View File

@ -303,7 +303,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -266,7 +266,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -329,7 +329,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -320,7 +320,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -450,7 +450,7 @@
_checked3dTouch = true;
if (_intent == TGMediaAssetsControllerSetProfilePhotoIntent || _intent == TGMediaAssetsControllerSetSignupProfilePhotoIntent) {
if (_intent == TGMediaAssetsControllerSetProfilePhotoIntent || _intent == TGMediaAssetsControllerSetSignupProfilePhotoIntent || _intent == TGMediaAssetsControllerSetCustomWallpaperIntent) {
return;
}

View File

@ -124,6 +124,7 @@ private final class MediaPlayerContext {
private var lastStatusUpdateTimestamp: Double?
private let playerStatus: Promise<MediaPlayerStatus>
private let playerStatusValue = Atomic<MediaPlayerStatus?>(value: nil)
fileprivate var actionAtEnd: MediaPlayerActionAtEnd = .stop
@ -290,10 +291,12 @@ private final class MediaPlayerContext {
loadedDuration = duration
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play), soundEnabled: self.enableSound)
self.playerStatus.set(.single(status))
self.playerStatusValue.swap(status)
} else {
let duration = seekState?.duration ?? 0.0
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play), soundEnabled: self.enableSound)
self.playerStatus.set(.single(status))
self.playerStatusValue.swap(status)
}
let frameSource = FFMpegMediaFrameSource(queue: self.queue, postbox: self.postbox, resourceReference: self.resourceReference, tempFilePath: self.tempFilePath, streamable: self.streamable.enabled, video: self.video, preferSoftwareDecoding: self.preferSoftwareDecoding, fetchAutomatically: self.fetchAutomatically, stallDuration: self.streamable.parameters.0, lowWaterDuration: self.streamable.parameters.1, highWaterDuration: self.streamable.parameters.2)
@ -579,6 +582,12 @@ private final class MediaPlayerContext {
self.lastStatusUpdateTimestamp = nil
self.tick()
self.audioRenderer?.renderer.setBaseRate(baseRate)
if case .seeking = self.state, let status = self.playerStatusValue.with({ $0 }) {
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: status.duration, dimensions: status.dimensions, timestamp: status.timestamp, baseRate: self.baseRate, seekId: self.seekId, status: status.status, soundEnabled: status.soundEnabled)
self.playerStatus.set(.single(status))
self.playerStatusValue.swap(status)
}
}
fileprivate func setForceAudioToSpeaker(_ value: Bool) {
@ -868,6 +877,7 @@ private final class MediaPlayerContext {
}
let status = MediaPlayerStatus(generationTimestamp: statusTimestamp, duration: duration, dimensions: CGSize(), timestamp: min(max(reportTimestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: playbackStatus, soundEnabled: self.enableSound)
self.playerStatus.set(.single(status))
self.playerStatusValue.swap(status)
}
if performActionAtEndNow {

View File

@ -20,21 +20,24 @@
#define IPHONE_4_NAMESTRING @"iPhone 4"
#define IPHONE_4S_NAMESTRING @"iPhone 4S"
#define IPHONE_5_NAMESTRING @"iPhone 5"
#define IPHONE_5S_NAMESTRING @"iPhone 5S"
#define IPHONE_5S_NAMESTRING @"iPhone 5S"
#define IPHONE_6_NAMESTRING @"iPhone 6"
#define IPHONE_6Plus_NAMESTRING @"iPhone 6 Plus"
#define IPHONE_6S_NAMESTRING @"iPhone 6S"
#define IPHONE_6SPlus_NAMESTRING @"iPhone 6S Plus"
#define IPHONE_6Plus_NAMESTRING @"iPhone 6 Plus"
#define IPHONE_6S_NAMESTRING @"iPhone 6S"
#define IPHONE_6SPlus_NAMESTRING @"iPhone 6S Plus"
#define IPHONE_7_NAMESTRING @"iPhone 7"
#define IPHONE_7Plus_NAMESTRING @"iPhone 7 Plus"
#define IPHONE_7Plus_NAMESTRING @"iPhone 7 Plus"
#define IPHONE_8_NAMESTRING @"iPhone 8"
#define IPHONE_8Plus_NAMESTRING @"iPhone 8 Plus"
#define IPHONE_8Plus_NAMESTRING @"iPhone 8 Plus"
#define IPHONE_X_NAMESTRING @"iPhone X"
#define IPHONE_SE_NAMESTRING @"iPhone SE"
#define IPHONE_SE_NAMESTRING @"iPhone SE"
#define IPHONE_XS_NAMESTRING @"iPhone XS"
#define IPHONE_XSMAX_NAMESTRING @"iPhone XS Max"
#define IPHONE_XR_NAMESTRING @"iPhone XR"
#define IPHONE_11_NAMESTRING @"iPhone 11"
#define IPHONE_11PRO_NAMESTRING @"iPhone 11 Pro"
#define IPHONE_11PROMAX_NAMESTRING @"iPhone 11 Pro Max"
#define IPHONE_UNKNOWN_NAMESTRING @"Unknown iPhone"
#define IPHONE_XS_NAMESTRING @"iPhone XS"
#define IPHONE_XSMAX_NAMESTRING @"iPhone XS Max"
#define IPHONE_XR_NAMESTRING @"iPhone XR"
#define IPOD_1G_NAMESTRING @"iPod touch 1G"
#define IPOD_2G_NAMESTRING @"iPod touch 2G"
@ -42,6 +45,7 @@
#define IPOD_4G_NAMESTRING @"iPod touch 4G"
#define IPOD_5G_NAMESTRING @"iPod touch 5G"
#define IPOD_6G_NAMESTRING @"iPod touch 6G"
#define IPOD_7G_NAMESTRING @"iPod touch 7G"
#define IPOD_UNKNOWN_NAMESTRING @"Unknown iPod"
#define IPAD_1G_NAMESTRING @"iPad 1G"
@ -49,12 +53,12 @@
#define IPAD_3G_NAMESTRING @"iPad 3G"
#define IPAD_4G_NAMESTRING @"iPad 4G"
#define IPAD_5G_NAMESTRING @"iPad Air 2"
#define IPAD_6G_NAMESTRING @"iPad Pro"
#define IPAD_PRO_3G_NAMESTRING @"iPad Pro 12.9 (3rd gen)"
#define IPAD_PRO_11_NAMESTRING @"iPad Pro 11"
#define IPAD_PRO_6G_NAMESTRING @"iPad (6th gen)"
#define IPAD_PRO_10_5_NAMESTRING @"iPad Pro 10.5"
#define IPAD_PRO_12_9_NAMESTRING @"iPad Pro 12.9"
#define IPAD_6G_NAMESTRING @"iPad Pro"
#define IPAD_PRO_3G_NAMESTRING @"iPad Pro 12.9 inch (3rd gen)"
#define IPAD_PRO_11_NAMESTRING @"iPad Pro 11 inch"
#define IPAD_PRO_6G_NAMESTRING @"iPad (6th gen)"
#define IPAD_PRO_10_5_NAMESTRING @"iPad Pro 10.5 inch"
#define IPAD_PRO_12_9_NAMESTRING @"iPad Pro 12.9 inch"
#define IPAD_UNKNOWN_NAMESTRING @"Unknown iPad"
#define APPLETV_2G_NAMESTRING @"Apple TV 2G"
@ -67,7 +71,7 @@
#define SIMULATOR_NAMESTRING @"iPhone Simulator"
#define SIMULATOR_IPHONE_NAMESTRING @"iPhone Simulator"
#define SIMULATOR_IPAD_NAMESTRING @"iPad Simulator"
#define SIMULATOR_APPLETV_NAMESTRING @"Apple TV Simulator" // :)
#define SIMULATOR_APPLETV_NAMESTRING @"Apple TV Simulator"
/*
iPad8,5, iPad8,6, iPad8,7, iPad8,8 - iPad Pro 12.9" (3rd gen)
@ -105,6 +109,9 @@ typedef enum {
UIDeviceXSiPhone,
UIDeviceXSMaxiPhone,
UIDeviceXRiPhone,
UIDevice11iPhone,
UIDevice11ProiPhone,
UIDevice11ProMaxiPhone,
UIDevice1GiPod,
UIDevice2GiPod,
@ -112,6 +119,7 @@ typedef enum {
UIDevice4GiPod,
UIDevice5GiPod,
UIDevice6GiPod,
UIDevice7GiPod,
UIDevice1GiPad,
UIDevice2GiPad,
@ -592,7 +600,9 @@ NSString *suffix = @"";
case UIDeviceXSiPhone: return IPHONE_XS_NAMESTRING;
case UIDeviceXSMaxiPhone: return IPHONE_XSMAX_NAMESTRING;
case UIDeviceXRiPhone: return IPHONE_XR_NAMESTRING;
case UIDevice11iPhone: return IPHONE_11_NAMESTRING;
case UIDevice11ProiPhone: return IPHONE_11PRO_NAMESTRING;
case UIDevice11ProMaxiPhone: return IPHONE_11PROMAX_NAMESTRING;
case UIDeviceUnknowniPhone: return IPHONE_UNKNOWN_NAMESTRING;
case UIDevice1GiPod: return IPOD_1G_NAMESTRING;
@ -601,6 +611,7 @@ NSString *suffix = @"";
case UIDevice4GiPod: return IPOD_4G_NAMESTRING;
case UIDevice5GiPod: return IPOD_5G_NAMESTRING;
case UIDevice6GiPod: return IPOD_6G_NAMESTRING;
case UIDevice7GiPod: return IPOD_7G_NAMESTRING;
case UIDeviceUnknowniPod: return IPOD_UNKNOWN_NAMESTRING;
case UIDevice1GiPad : return IPAD_1G_NAMESTRING;
@ -684,6 +695,10 @@ NSString *suffix = @"";
if ([platform isEqualToString:@"iPhone11,4"]) return UIDeviceXSMaxiPhone;
if ([platform isEqualToString:@"iPhone11,8"]) return UIDeviceXRiPhone;
if ([platform isEqualToString:@"iPhone12,1"]) return UIDevice11iPhone;
if ([platform isEqualToString:@"iPhone12,3"]) return UIDevice11ProiPhone;
if ([platform isEqualToString:@"iPhone12,5"]) return UIDevice11ProMaxiPhone;
if ([platform isEqualToString:@"iPhone8,4"]) return UIDeviceSEPhone;
// iPod
@ -693,6 +708,7 @@ NSString *suffix = @"";
if ([platform hasPrefix:@"iPod4"]) return UIDevice4GiPod;
if ([platform hasPrefix:@"iPod5"]) return UIDevice5GiPod;
if ([platform hasPrefix:@"iPod7"]) return UIDevice6GiPod;
if ([platform hasPrefix:@"iPod9"]) return UIDevice7GiPod;
// iPad
if ([platform hasPrefix:@"iPad1"]) return UIDevice1GiPad;

View File

@ -119,6 +119,9 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
return .openUrl(url: "ddgQuickLink://\(url)")
}))
options.append(OpenInOption(application: .other(title: "Alook Browser", identifier: 1261944766, scheme: "alook", store: nil), action: {
return .openUrl(url: "alook://\(url)")
}))
case let .location(location, withDirections):
let lat = location.latitude

View File

@ -156,8 +156,7 @@ private func processedLegacySecureIdAttachmentItems(postbox: Postbox, signal: SS
guard let image = image else {
return []
}
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let randomId = arc4random64()
let tempFilePath = NSTemporaryDirectory() + "\(randomId).jpeg"
let scaledSize = image.size.aspectFitted(CGSize(width: 2048.0, height: 2048.0))
if let scaledImage = TGScaleImageToPixelSize(image, scaledSize), let scaledImageData = compressImageToJPEG(scaledImage, quality: 0.84) {

View File

@ -1238,10 +1238,10 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
guard let controller = controller else {
return
}
controller.view.endEditing(true)
if let navigationController = controller.navigationController as? NavigationController {
navigationController.filterController(controller, animated: animated)
} else {
controller.view.endEditing(true)
controller.dismiss()
}
}

View File

@ -45,13 +45,33 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|> map { data, size, bytesPerRow in
return { arguments in
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
let start = CFAbsoluteTimeGetCurrent()
let mid = Int(size / 2)
let cutout: (Int, Int)?
if case .none = icon {
cutout = nil
} else {
switch size {
case 39:
cutout = (14, 24)
case 43:
cutout = (15, 27)
case 47:
cutout = (17, 29)
case 51:
cutout = (19, 31)
case 55:
cutout = (21, 33)
case 59:
cutout = (22, 36)
case 63:
cutout = (23, 39)
default:
cutout = (16, 26)
}
}
func valueAt(x: Int, y: Int) -> Bool {
if x >= 0 && x < size && y >= 0 && y < size {
if x > (mid - 5) && x < (mid + 5) && y > (mid - 5) && y < (mid + 5) {
if let cutout = cutout, x > cutout.0 && x < cutout.1 && y > cutout.0 && y < cutout.1 {
return false
}
@ -67,8 +87,8 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
}
}
let side = Int(floor(arguments.drawingSize.width / CGFloat(size)))
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * size)) / 2.0)
let side = floorToScreenPixels(arguments.drawingSize.width / CGFloat(size))
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0)
let squareSize = CGSize(width: side, height: side)
let tmpContext = DrawingContext(size: CGSize(width: squareSize.width * 4.0, height: squareSize.height), scale: arguments.scale ?? 0.0, clear: true)
@ -106,14 +126,14 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
let halfLen = scaledSquareSize * 4 / 2
let blockLen = scaledSquareSize * 4 * 2
func drawAt(x: Int, y: Int, black: Bool, corners: UIRectCorner) {
if !black && corners.isEmpty {
func drawAt(x: Int, y: Int, fill: Bool, corners: UIRectCorner) {
if !fill && corners.isEmpty {
return
}
for i in 0 ..< scaledSquareSize {
var dst = context.bytes.advanced(by: (scaledPadding + y * scaledSquareSize + i) * context.bytesPerRow + (scaledPadding + x * scaledSquareSize) * 4)
let srcOffset = (black ? 0 : scaledSquareSize * 4)
let srcOffset = (fill ? 0 : scaledSquareSize * 4)
let src = tmpContext.bytes.advanced(by: i * tmpContext.bytesPerRow + srcOffset)
if corners.contains(i < scaledSquareSize / 2 ? .topLeft : .bottomLeft) {
@ -169,8 +189,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
corners.remove(.topRight)
corners.remove(.bottomRight)
}
drawAt(x: x, y: y, black: true, corners: corners)
drawAt(x: x, y: y, fill: true, corners: corners)
} else {
if valueAt(x: x - 1, y: y - 1) && valueAt(x: x - 1, y: y) && valueAt(x: x, y: y - 1) {
corners.insert(.topLeft)
@ -184,8 +203,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
if valueAt(x: x + 1, y: y + 1) && valueAt(x: x + 1, y: y) && valueAt(x: x, y: y + 1) {
corners.insert(.bottomRight)
}
drawAt(x: x, y: y, black: false, corners: corners)
drawAt(x: x, y: y, fill: false, corners: corners)
}
}
}
@ -218,30 +236,14 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
let drawingRect = arguments.drawingRect
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
if let backgroundColor = backgroundColor {
c.setFillColor(backgroundColor.cgColor)
} else {
c.setBlendMode(.clear)
c.setFillColor(UIColor.clear.cgColor)
}
let codeScale = 43.0 / CGFloat(size)
let codeScale: CGFloat = 43.0 / 39.0
let clipSide = 56.0 * fittedRect.width / 267.0 * codeScale
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
switch icon {
case .cutout, .proxy, .custom:
break
//c.fill(clipRect)
default:
break
}
c.setBlendMode(.normal)
switch icon {
case .proxy:
let iconScale = fittedRect.width / 445.0 * codeScale
let iconScale = fittedRect.width / 420.0 * codeScale
let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale)
let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0)
c.translateBy(x: point.x, y: point.y)
@ -275,124 +277,6 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
}
}
let end = CFAbsoluteTimeGetCurrent() - start
print(end)
return context
}
}
}
public func aqrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M") -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
var icon: QrCodeIcon = .none
return Signal<CIImage, NoError> { subscriber in
if let data = string.data(using: .isoLatin1, allowLossyConversion: false), let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
filter.setValue(ecl, forKey: "inputCorrectionLevel")
if let output = filter.outputImage {
subscriber.putNext(output)
}
}
subscriber.putCompletion()
return EmptyDisposable
}
|> map { inputImage in
return { arguments in
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
let drawingRect = arguments.drawingRect
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
let scale = arguments.drawingRect.size.width / inputImage.extent.width * context.scale
let transformed = inputImage.transformed(by: CGAffineTransform.init(scaleX: scale, y: scale))
let codeScale = 43.0 / inputImage.extent.width
let invertFilter = CIFilter(name: "CIColorInvert")
invertFilter?.setValue(transformed, forKey: kCIInputImageKey)
let alphaFilter = CIFilter(name: "CIMaskToAlpha")
alphaFilter?.setValue(invertFilter?.outputImage, forKey: kCIInputImageKey)
var image: CGImage?
let ciContext = CIContext(options: nil)
if let finalImage = alphaFilter?.outputImage, let cgImage = ciContext.createCGImage(finalImage, from: finalImage.extent) {
image = cgImage
}
context.withContext { c in
if let backgroundColor = backgroundColor {
c.setFillColor(backgroundColor.cgColor)
c.fill(drawingRect)
}
c.setBlendMode(.normal)
if let image = image {
c.saveGState()
c.translateBy(x: fittedRect.midX, y: fittedRect.midY)
c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: -fittedRect.midX, y: -fittedRect.midY)
c.clip(to: fittedRect, mask: image)
c.setFillColor(color.cgColor)
c.fill(fittedRect)
c.restoreGState()
}
if let backgroundColor = backgroundColor {
c.setFillColor(backgroundColor.cgColor)
} else {
c.setBlendMode(.clear)
c.setFillColor(UIColor.clear.cgColor)
}
let clipSide = 56.0 * fittedRect.width / 267.0 * codeScale
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
switch icon {
case .cutout, .proxy, .custom:
c.fill(clipRect)
default:
break
}
c.setBlendMode(.normal)
switch icon {
case .proxy:
let iconScale = fittedRect.width / 445.0 * codeScale
let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale)
let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0)
c.translateBy(x: point.x, y: point.y)
c.scaleBy(x: iconScale, y: iconScale)
c.setFillColor(color.cgColor)
let _ = try? drawSvgPath(c, path: "M0.0,40 C0,20.3664202 20.1230605,0.0 32.5,0.0 C44.8769395,0.0 65,20.3664202 65,40 C65,47.217934 65,55.5505326 65,64.9977957 L32.5,79 L0.0,64.9977957 C0.0,55.0825772 0.0,46.7499786 0.0,40 Z")
if let backgroundColor = backgroundColor {
c.setFillColor(backgroundColor.cgColor)
} else {
c.setBlendMode(.clear)
c.setFillColor(UIColor.clear.cgColor)
}
let _ = try? drawSvgPath(c, path: "M7.03608247,43.556701 L18.9836689,32.8350515 L32.5,39.871134 L45.8888139,32.8350515 L57.9639175,43.556701 L57.9639175,60.0 L32.5,71.0 L7.03608247,60.0 Z")
c.setBlendMode(.normal)
c.setFillColor(color.cgColor)
let _ = try? drawSvgPath(c, path: "M24.1237113,50.5927835 L40.8762887,50.5927835 L40.8762887,60.9793814 L32.5,64.0928525 L24.1237113,60.9793814 Z")
case let .custom(image):
if let image = image {
let fittedSize = image.size.aspectFitted(clipRect.size)
let fittedRect = CGRect(origin: CGPoint(x: fittedRect.midX - fittedSize.width / 2.0, y: fittedRect.midY - fittedSize.height / 2.0), size: fittedSize)
c.translateBy(x: fittedRect.midX, y: fittedRect.midY)
c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: -fittedRect.midX, y: -fittedRect.midY)
c.draw(image.cgImage!, in: fittedRect)
}
break
default:
break
}
}
return context
}
}

View File

@ -261,7 +261,7 @@ class AutodownloadDataUsagePickerItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -231,7 +231,7 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -184,7 +184,7 @@ class CalculatingCacheSizeItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -188,7 +188,7 @@ class ProxySettingsActionItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -370,7 +370,7 @@ class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -104,7 +104,7 @@ private enum LogoutOptionsEntry: ItemListNodeEntry, Equatable {
}
}
private func logoutOptionsEntries(presentationData: PresentationData, canAddAccounts: Bool, hasPasscode: Bool) -> [LogoutOptionsEntry] {
private func logoutOptionsEntries(presentationData: PresentationData, canAddAccounts: Bool, hasPasscode: Bool, hasWallets: Bool) -> [LogoutOptionsEntry] {
var entries: [LogoutOptionsEntry] = []
entries.append(.alternativeHeader(presentationData.theme, presentationData.strings.LogoutOptions_AlternativeOptionsSection))
if canAddAccounts {
@ -117,7 +117,11 @@ private func logoutOptionsEntries(presentationData: PresentationData, canAddAcco
entries.append(.changePhoneNumber(presentationData.theme, presentationData.strings.LogoutOptions_ChangePhoneNumberTitle, presentationData.strings.LogoutOptions_ChangePhoneNumberText))
entries.append(.contactSupport(presentationData.theme, presentationData.strings.LogoutOptions_ContactSupportTitle, presentationData.strings.LogoutOptions_ContactSupportText))
entries.append(.logout(presentationData.theme, presentationData.strings.LogoutOptions_LogOut))
entries.append(.logoutInfo(presentationData.theme, presentationData.strings.LogoutOptions_LogOutInfo))
if hasWallets {
entries.append(.logoutInfo(presentationData.theme, presentationData.strings.LogoutOptions_LogOutWalletInfo))
} else {
entries.append(.logoutInfo(presentationData.theme, presentationData.strings.LogoutOptions_LogOutInfo))
}
return entries
}
@ -211,8 +215,17 @@ func logoutOptionsController(context: AccountContext, navigationController: Navi
presentControllerImpl?(alertController, nil)
})
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, context.sharedContext.accountManager.accessChallengeData())
|> map { presentationData, accessChallengeData -> (ItemListControllerState, (ItemListNodeState<LogoutOptionsEntry>, LogoutOptionsEntry.ItemGenerationArguments)) in
let hasWallets = availableWallets(postbox: context.account.postbox)
|> map { wallets in
return !wallets.wallets.isEmpty
}
let signal = combineLatest(queue: .mainQueue(),
context.sharedContext.presentationData,
context.sharedContext.accountManager.accessChallengeData(),
hasWallets
)
|> map { presentationData, accessChallengeData, hasWallets -> (ItemListControllerState, (ItemListNodeState<LogoutOptionsEntry>, LogoutOptionsEntry.ItemGenerationArguments)) in
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
dismissImpl?()
})
@ -226,7 +239,7 @@ func logoutOptionsController(context: AccountContext, navigationController: Navi
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.LogoutOptions_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(entries: logoutOptionsEntries(presentationData: presentationData, canAddAccounts: canAddAccounts, hasPasscode: hasPasscode), style: .blocks)
let listState = ItemListNodeState(entries: logoutOptionsEntries(presentationData: presentationData, canAddAccounts: canAddAccounts, hasPasscode: hasPasscode, hasWallets: hasWallets), style: .blocks)
return (controllerState, (listState, arguments))
}

View File

@ -345,7 +345,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -345,7 +345,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -37,7 +37,7 @@ final class ThemeAccentColorController: ViewController {
color = defaultDayAccentColor
}
self.initialColor = color
self.initialTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: nil, preview: true)
self.initialTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: nil, preview: true) ?? defaultPresentationTheme
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -70,7 +70,7 @@ final class ThemeAccentColorController: ViewController {
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: strongSelf.currentTheme, accentColor: UIColor(rgb: strongSelf.controllerNode.color), serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: color.baseColor)
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: strongSelf.currentTheme, accentColor: UIColor(rgb: strongSelf.controllerNode.color), serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: color.baseColor) ?? defaultPresentationTheme
var chatWallpaper = current.chatWallpaper
if let wallpaper = current.themeSpecificChatWallpapers[current.theme.index], wallpaper.hasWallpaper {
} else {

View File

@ -140,7 +140,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.colorDisposable = (self.colorValue.get()
|> deliverOn(Queue.concurrentDefaultQueue())
|> map { color -> PresentationTheme in
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: nil, preview: true)
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: nil, preview: true) ?? defaultPresentationTheme
let wallpaper = context.sharedContext.currentPresentationData.with { $0 }.chatWallpaper
let _ = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: theme, wallpaper: wallpaper, gradientBubbles: context.sharedContext.immediateExperimentalUISettings.gradientBubbles)
@ -191,10 +191,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
override func didLoad() {
super.didLoad()
self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true
self.scrollNode.view.showsHorizontalScrollIndicator = false
self.scrollNode.view.isPagingEnabled = true
self.scrollNode.view.delegate = self
self.pageControlNode.setPage(0.0)
self.colorPanelNode.view.disablesInteractiveTransitionGestureRecognizer = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {

View File

@ -497,7 +497,9 @@ public func themeAutoNightSettingsController(context: AccountContext) -> ViewCon
}
}))
}, updateTheme: { theme in
let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, serviceBackgroundColor: .black, baseColor: nil)
guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, serviceBackgroundColor: .black, baseColor: nil) else {
return
}
let resolvedWallpaper: Signal<TelegramWallpaper?, NoError>
if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 {

View File

@ -78,6 +78,8 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
private var customColorItem: ItemListActionItem
let gridNode: GridNode
private let leftOverlayNode: ASDisplayNode
private let rightOverlayNode: ASDisplayNode
private var queuedTransitions: [ThemeColorsGridEntryTransition] = []
private var validLayout: (ContainerViewLayout, CGFloat)?
@ -92,6 +94,10 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
self.gridNode = GridNode()
self.gridNode.showVerticalScrollIndicator = true
self.leftOverlayNode = ASDisplayNode()
self.leftOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode = ASDisplayNode()
self.rightOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
@ -210,7 +216,9 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
self.presentationData = presentationData
self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
self.leftOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.customColorItem = ItemListActionItem(theme: presentationData.theme, title: presentationData.strings.WallpaperColors_SetCustomColor, kind: .generic, alignment: .natural, sectionId: 0, style: .blocks, action: { [weak self] in
self?.presentColorPicker()
})
@ -259,8 +267,29 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height))
let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1))
var listInsets = insets
if layout.size.width > 480.0 {
let inset = max(20.0, floor((layout.size.width - 674.0) / 2.0))
listInsets.left += inset
listInsets.right += inset
if self.leftOverlayNode.supernode == nil {
self.gridNode.addSubnode(self.leftOverlayNode)
}
if self.rightOverlayNode.supernode == nil {
self.gridNode.addSubnode(self.rightOverlayNode)
}
} else {
if self.leftOverlayNode.supernode != nil {
self.leftOverlayNode.removeFromSupernode()
}
if self.rightOverlayNode.supernode != nil {
self.rightOverlayNode.removeFromSupernode()
}
}
let makeColorLayout = self.customColorItemNode.asyncLayout()
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: insets.left, rightInset: insets.right)
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: listInsets.left, rightInset: listInsets.right)
let (colorLayout, colorApply) = makeColorLayout(self.customColorItem, params, ItemListNeighbors(top: .none, bottom: .none))
colorApply()
@ -275,6 +304,9 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -buttonOffset + buttonInset - UIScreenPixel), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
transition.updateFrame(node: self.customColorItemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -buttonOffset + buttonTopInset), size: colorLayout.contentSize))
self.leftOverlayNode.frame = CGRect(x: 0.0, y: -buttonOffset, width: listInsets.left, height: buttonTopInset + colorLayout.contentSize.height)
self.rightOverlayNode.frame = CGRect(x: layout.size.width - listInsets.right, y: -buttonOffset, width: listInsets.right, height: buttonTopInset + colorLayout.contentSize.height)
insets.top += spacing + buttonInset
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: layout.size, insets: insets, scrollIndicatorInsets: scrollIndicatorInsets, preloadSize: 300.0, type: .fixed(itemSize: imageSize, fillWidth: nil, lineSpacing: spacing, itemSpacing: nil)), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil), completion: { _ in })

View File

@ -218,6 +218,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
private var selectionPanelBackgroundNode: ASDisplayNode?
let gridNode: GridNode
private let leftOverlayNode: ASDisplayNode
private let rightOverlayNode: ASDisplayNode
var navigationBar: NavigationBar?
private var queuedTransitions: [ThemeGridEntryTransition] = []
@ -244,6 +246,10 @@ final class ThemeGridControllerNode: ASDisplayNode {
self.gridNode = GridNode()
self.gridNode.showVerticalScrollIndicator = true
self.leftOverlayNode = ASDisplayNode()
self.leftOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode = ASDisplayNode()
self.rightOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
@ -516,6 +522,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
self.searchDisplayController?.updatePresentationData(self.presentationData)
self.leftOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.backgroundNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
self.bottomBackgroundNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor
@ -609,7 +617,28 @@ final class ThemeGridControllerNode: ASDisplayNode {
let makeGalleryLayout = self.galleryItemNode.asyncLayout()
let makeDescriptionLayout = self.descriptionItemNode.asyncLayout()
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: insets.left, rightInset: insets.right)
var listInsets = insets
if layout.size.width > 480.0 {
let inset = max(20.0, floor((layout.size.width - 674.0) / 2.0))
listInsets.left += inset
listInsets.right += inset
if self.leftOverlayNode.supernode == nil {
self.gridNode.addSubnode(self.leftOverlayNode)
}
if self.rightOverlayNode.supernode == nil {
self.gridNode.addSubnode(self.rightOverlayNode)
}
} else {
if self.leftOverlayNode.supernode != nil {
self.leftOverlayNode.removeFromSupernode()
}
if self.rightOverlayNode.supernode != nil {
self.rightOverlayNode.removeFromSupernode()
}
}
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: listInsets.left, rightInset: listInsets.right)
let (colorLayout, colorApply) = makeColorLayout(self.colorItem, params, ItemListNeighbors(top: .none, bottom: .sameSection(alwaysPlain: false)))
let (galleryLayout, galleryApply) = makeGalleryLayout(self.galleryItem, params, ItemListNeighbors(top: .sameSection(alwaysPlain: false), bottom: .sameSection(alwaysPlain: true)))
let (descriptionLayout, descriptionApply) = makeDescriptionLayout(self.descriptionItem, params, ItemListNeighbors(top: .none, bottom: .none))
@ -632,6 +661,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
transition.updateFrame(node: self.galleryItemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -buttonOffset + buttonTopInset + colorLayout.contentSize.height), size: galleryLayout.contentSize))
transition.updateFrame(node: self.descriptionItemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -buttonOffset + buttonTopInset + colorLayout.contentSize.height + galleryLayout.contentSize.height), size: descriptionLayout.contentSize))
self.leftOverlayNode.frame = CGRect(x: 0.0, y: -buttonOffset, width: listInsets.left, height: buttonTopInset + colorLayout.contentSize.height + galleryLayout.contentSize.height)
self.rightOverlayNode.frame = CGRect(x: layout.size.width - listInsets.right, y: -buttonOffset, width: listInsets.right, height: buttonTopInset + colorLayout.contentSize.height + galleryLayout.contentSize.height)
insets.top += spacing + buttonInset
if self.currentState.editing {

View File

@ -270,7 +270,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -241,7 +241,7 @@ class ThemeSettingsAppIconItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -176,7 +176,7 @@ class ThemeSettingsBrightnessItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -231,7 +231,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -58,7 +58,7 @@ func themeDisplayName(strings: PresentationStrings, reference: PresentationTheme
private final class ThemeSettingsControllerArguments {
let context: AccountContext
let updateTheme: (PresentationThemeReference) -> Void
let selectTheme: (PresentationThemeReference) -> Void
let selectFontSize: (PresentationFontSize) -> Void
let openWallpaperSettings: () -> Void
let selectAccentColor: (PresentationThemeAccentColor) -> Void
@ -70,9 +70,9 @@ private final class ThemeSettingsControllerArguments {
let editTheme: (PresentationCloudTheme) -> Void
let contextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void
init(context: AccountContext, updateTheme: @escaping (PresentationThemeReference) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, PresentationThemeAccentColor?) -> Void, openAutoNightTheme: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, contextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void) {
init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, PresentationThemeAccentColor?) -> Void, openAutoNightTheme: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, contextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void) {
self.context = context
self.updateTheme = updateTheme
self.selectTheme = selectTheme
self.selectFontSize = selectFontSize
self.openWallpaperSettings = openWallpaperSettings
self.selectAccentColor = selectAccentColor
@ -319,7 +319,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
arguments.editTheme(theme)
}
} else {
arguments.updateTheme(theme)
arguments.selectTheme(theme)
}
}, contextAction: { theme, node, gesture in
arguments.contextAction(theme.index == currentTheme.index, theme, node, gesture)
@ -393,7 +393,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
var presentInGlobalOverlayImpl: ((ViewController, Any?) -> Void)?
var getNavigationControllerImpl: (() -> NavigationController?)?
var updateThemeImpl: ((PresentationThemeReference) -> Void)?
var selectThemeImpl: ((PresentationThemeReference) -> Void)?
var moreImpl: (() -> Void)?
let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start()
@ -414,8 +414,8 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager)
cloudThemes.set(updatedCloudThemes)
let arguments = ThemeSettingsControllerArguments(context: context, updateTheme: { theme in
updateThemeImpl?(theme)
let arguments = ThemeSettingsControllerArguments(context: context, selectTheme: { theme in
selectThemeImpl?(theme)
}, selectFontSize: { size in
let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: size, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
@ -424,12 +424,13 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
pushControllerImpl?(ThemeGridController(context: context))
}, selectAccentColor: { color in
let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: current.theme, accentColor: color.color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: color.baseColor) else {
return current
}
var themeSpecificAccentColors = current.themeSpecificAccentColors
themeSpecificAccentColors[current.theme.index] = color
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: current.theme, accentColor: color.color, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: color.baseColor)
var chatWallpaper = current.chatWallpaper
if let wallpaper = current.themeSpecificChatWallpapers[current.theme.index], wallpaper.hasWallpaper {
} else {
@ -468,6 +469,9 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
return makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: nil, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: .blue)
}
|> deliverOnMainQueue).start(next: { theme in
guard let theme = theme else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let strings = presentationData.strings
let themeController = ThemePreviewController(context: context, previewTheme: theme, source: .settings(reference))
@ -476,7 +480,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
if !isCurrent {
items.append(.action(ContextMenuActionItem(text: strings.Theme_Context_Apply, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in
c.dismiss(completion: {
updateThemeImpl?(reference)
selectThemeImpl?(reference)
})
})))
}
@ -517,7 +521,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
} else {
newTheme = .builtin(.nightAccent)
}
updateThemeImpl?(newTheme)
selectThemeImpl?(newTheme)
}
let _ = deleteThemeInteractively(account: context.account, accountManager: context.sharedContext.accountManager, theme: theme.theme).start()
@ -548,7 +552,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
let disableAnimations = presentationData.disableAnimations
let accentColor = settings.themeSpecificAccentColors[settings.theme.index]?.color
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: settings.theme, accentColor: accentColor, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: settings.themeSpecificAccentColors[settings.theme.index]?.baseColor ?? .blue, preview: true)
let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: settings.theme, accentColor: accentColor, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: settings.themeSpecificAccentColors[settings.theme.index]?.baseColor ?? .blue, preview: true) ?? defaultPresentationTheme
let wallpaper: TelegramWallpaper
if let themeSpecificWallpaper = settings.themeSpecificChatWallpapers[settings.theme.index] {
@ -590,8 +594,10 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
getNavigationControllerImpl = { [weak controller] in
return controller?.navigationController as? NavigationController
}
updateThemeImpl = { theme in
let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, serviceBackgroundColor: .black, baseColor: nil)
selectThemeImpl = { theme in
guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, serviceBackgroundColor: .black, baseColor: nil) else {
return
}
let resolvedWallpaper: Signal<TelegramWallpaper?, NoError>
if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 {
@ -628,7 +634,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
if let themeSpecificWallpaper = current.themeSpecificChatWallpapers[updatedTheme.index] {
chatWallpaper = themeSpecificWallpaper
} else {
let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: updatedTheme, accentColor: current.themeSpecificAccentColors[updatedTheme.index]?.color, serviceBackgroundColor: .black, baseColor: nil)
let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: updatedTheme, accentColor: current.themeSpecificAccentColors[updatedTheme.index]?.color, serviceBackgroundColor: .black, baseColor: nil) ?? defaultPresentationTheme
chatWallpaper = resolvedWallpaper ?? presentationTheme.chat.defaultWallpaper
}

View File

@ -203,7 +203,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -346,7 +346,7 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = params.width > 480
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {

View File

@ -384,9 +384,16 @@ public class WallpaperGalleryController: ViewController {
let wallpaper = wallpaper.withUpdatedSettings(updatedSettings)
let _ = (updatePresentationThemeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { current in
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[current.theme.index] = wallpaper
return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
var chatWallpaper = current.chatWallpaper
if automaticThemeShouldSwitchNow(settings: current.automaticThemeSwitchSetting, currentTheme: current.theme) {
themeSpecificChatWallpapers[current.automaticThemeSwitchSetting.theme.index] = wallpaper
} else {
themeSpecificChatWallpapers[current.theme.index] = wallpaper
chatWallpaper = wallpaper
}
return PresentationThemeSettings(chatWallpaper: chatWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations)
}) |> deliverOnMainQueue).start(completed: {
self?.dismiss(forceAway: true)
})

View File

@ -21,6 +21,7 @@ static_library(
"//submodules/RadialStatusNode:RadialStatusNode",
"//submodules/ActivityIndicator:ActivityIndicator",
"//submodules/AppBundle:AppBundle",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -13,6 +13,7 @@ import LocalizedPeerData
import UrlEscaping
import StickerResources
import SaveToCameraRoll
import TelegramStringFormatting
public struct ShareControllerAction {
let title: String
@ -90,10 +91,12 @@ private enum ExternalShareItemsState {
private struct CollectableExternalShareItem {
let url: String?
let text: String
let author: String?
let timestamp: Int32?
let mediaReference: AnyMediaReference?
}
private func collectExternalShareItems(strings: PresentationStrings, postbox: Postbox, collectableItems: [CollectableExternalShareItem], takeOne: Bool = true) -> Signal<ExternalShareItemsState, NoError> {
private func collectExternalShareItems(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, postbox: Postbox, collectableItems: [CollectableExternalShareItem], takeOne: Bool = true) -> Signal<ExternalShareItemsState, NoError> {
var signals: [Signal<ExternalShareItemStatus, NoError>] = []
for item in collectableItems {
if let mediaReference = item.mediaReference, let file = mediaReference.media as? TelegramMediaFile {
@ -163,7 +166,18 @@ private func collectExternalShareItems(strings: PresentationStrings, postbox: Po
}
signals.append(.single(.done(.text(text))))
} else if let mediaReference = item.mediaReference, let contact = mediaReference.media as? TelegramMediaContact {
let contactData: DeviceContactExtendedData
if let vCard = contact.vCardData, let vCardData = vCard.data(using: .utf8), let parsed = DeviceContactExtendedData(vcard: vCardData) {
contactData = parsed
} else {
contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: contact.firstName, lastName: contact.lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: contact.phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [])
}
if let vCard = contactData.serializedVCard() {
let path = NSTemporaryDirectory() + "\(arc4random64()).lz4v"
let fullName = [contact.firstName, contact.lastName].filter { $0.isEmpty }.joined(separator: " ")
signals.append(.single(.done(.file(URL(fileURLWithPath: path), "\(fullName).vcf", "text/x-vcard"))))
}
}
if let url = item.url, let parsedUrl = URL(string: url) {
if signals.isEmpty || !takeOne {
@ -172,7 +186,18 @@ private func collectExternalShareItems(strings: PresentationStrings, postbox: Po
}
if !item.text.isEmpty {
if signals.isEmpty || !takeOne {
signals.append(.single(.done(.text(item.text))))
var text: String = item.text
var metadata: [String] = []
if let author = item.author {
metadata.append(author)
}
if let timestamp = item.timestamp {
metadata.append("[\(stringForFullDate(timestamp: timestamp, strings: strings, dateTimeFormat: dateTimeFormat))]")
}
if !metadata.isEmpty {
text = metadata.joined(separator: ", ") + "\n" + text + "\n"
}
signals.append(.single(.done(.text(text))))
}
}
}
@ -519,19 +544,19 @@ public final class ShareController: ViewController {
var collectableItems: [CollectableExternalShareItem] = []
switch strongSelf.subject {
case let .url(text):
collectableItems.append(CollectableExternalShareItem(url: explicitUrl(text), text: "", mediaReference: nil))
collectableItems.append(CollectableExternalShareItem(url: explicitUrl(text), text: "", author: nil, timestamp: nil, mediaReference: nil))
case let .text(string):
collectableItems.append(CollectableExternalShareItem(url: "", text: string, mediaReference: nil))
collectableItems.append(CollectableExternalShareItem(url: "", text: string, author: nil, timestamp: nil, mediaReference: nil))
case let .quote(text, url):
collectableItems.append(CollectableExternalShareItem(url: "", text: "\"\(text)\"\n\n\(url)", mediaReference: nil))
collectableItems.append(CollectableExternalShareItem(url: "", text: "\"\(text)\"\n\n\(url)", author: nil, timestamp: nil, mediaReference: nil))
case let .image(representations):
let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil)
collectableItems.append(CollectableExternalShareItem(url: "", text: "", mediaReference: .standalone(media: media)))
collectableItems.append(CollectableExternalShareItem(url: "", text: "", author: nil, timestamp: nil, mediaReference: .standalone(media: media)))
case let .media(mediaReference):
collectableItems.append(CollectableExternalShareItem(url: "", text: "", mediaReference: mediaReference))
collectableItems.append(CollectableExternalShareItem(url: "", text: "", author: nil, timestamp: nil, mediaReference: mediaReference))
case let .mapMedia(media):
let latLong = "\(media.latitude),\(media.longitude)"
collectableItems.append(CollectableExternalShareItem(url: "https://maps.apple.com/maps?ll=\(latLong)&q=\(latLong)&t=m", text: "", mediaReference: nil))
collectableItems.append(CollectableExternalShareItem(url: "https://maps.apple.com/maps?ll=\(latLong)&q=\(latLong)&t=m", text: "", author: nil, timestamp: nil, mediaReference: nil))
case let .messages(messages):
for message in messages {
var url: String?
@ -561,12 +586,18 @@ public final class ShareController: ViewController {
url = "https://t.me/\(addressName)/\(message.id.id)"
}
}
collectableItems.append(CollectableExternalShareItem(url: url, text: message.text, mediaReference: selectedMedia.flatMap({ AnyMediaReference.message(message: MessageReference(message), media: $0) })))
var peer: Peer?
if let authorPeerId = message.author?.id {
peer = message.peers[authorPeerId]
} else if let mainPeer = messageMainPeer(message) {
peer = mainPeer
}
collectableItems.append(CollectableExternalShareItem(url: url, text: message.text, author: peer?.displayTitle, timestamp: message.timestamp, mediaReference: selectedMedia.flatMap({ AnyMediaReference.message(message: MessageReference(message), media: $0) })))
}
case .fromExternal:
break
}
return (collectExternalShareItems(strings: strongSelf.presentationData.strings, postbox: strongSelf.currentAccount.postbox, collectableItems: collectableItems, takeOne: !strongSelf.immediateExternalShare)
return (collectExternalShareItems(strings: strongSelf.presentationData.strings, dateTimeFormat: strongSelf.presentationData.dateTimeFormat, postbox: strongSelf.currentAccount.postbox, collectableItems: collectableItems, takeOne: !strongSelf.immediateExternalShare)
|> deliverOnMainQueue)
|> map { state in
switch state {

View File

@ -20,9 +20,7 @@ public func requestStartBot(account: Account, botPeerId: PeerId, payload: String
return account.postbox.loadedPeerWithId(botPeerId)
|> mapToSignal { botPeer -> Signal<Void, NoError> in
if let inputUser = apiInputUser(botPeer) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let r = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: .inputPeerEmpty, randomId: randomId, startParam: payload))
let r = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: .inputPeerEmpty, randomId: arc4random64(), startParam: payload))
|> mapToSignal { result -> Signal<Void, MTRpcError> in
account.stateManager.addUpdates(result)
return .complete()
@ -59,9 +57,7 @@ public func requestStartBotInGroup(account: Account, botPeerId: PeerId, groupPee
|> mapError { _ -> RequestStartBotInGroupError in return .generic }
|> mapToSignal { botPeer, groupPeer -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> in
if let botPeer = botPeer, let inputUser = apiInputUser(botPeer), let groupPeer = groupPeer, let inputGroup = apiInputPeer(groupPeer) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let request = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: inputGroup, randomId: randomId, startParam: payload ?? ""))
let request = account.network.request(Api.functions.messages.startBot(bot: inputUser, peer: inputGroup, randomId: arc4random64(), startParam: payload ?? ""))
|> mapError { _ -> RequestStartBotInGroupError in
return .generic
}

View File

@ -133,7 +133,7 @@ private func mergedState(transaction: Transaction, state: SearchMessagesPeerStat
return lhs.index > rhs.index
})
let completed = renderedMessages.isEmpty
let completed = renderedMessages.isEmpty || renderedMessages.count == totalCount
if let previous = state {
var currentIds = Set<MessageId>()
var mergedMessages: [Message] = []

View File

@ -215,8 +215,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
)
let message = PresentationThemeChatMessage(
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628))), primaryTextColor: .white, secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.4), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: accentColor, fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(.white, alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: UIColor(rgb: 0x000000), bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleHighlightedFillColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleHighlightedFillColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(.white, alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: outgoingPrimaryTextColor, highlight: outgoingPrimaryTextColor.withAlphaComponent(0.12), separator: outgoingSecondaryTextColor, bar: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628))), primaryTextColor: .white, secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.4), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: accentColor, fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(.white, alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: UIColor(rgb: 0x000000), bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleHighlightedFillColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleHighlightedFillColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(.white, alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: outgoingPrimaryTextColor, highlight: outgoingPrimaryTextColor.withAlphaComponent(0.12), separator: outgoingSecondaryTextColor, bar: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f))),
infoPrimaryTextColor: .white,
infoLinkTextColor: accentColor,

View File

@ -193,8 +193,8 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
let buttonStrokeColor = accentColor.withMultiplied(hue: 1.014, saturation: 0.56, brightness: 0.64).withAlphaComponent(0.15)
let message = PresentationThemeChatMessage(
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: .white, accentControlColor: .white, mediaActiveControlColor: .white, mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: .white, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: .white, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: .white), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: .white, accentControlColor: .white, mediaActiveControlColor: .white, mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: .white, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: .white, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: .white), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)),
infoPrimaryTextColor: UIColor(rgb: 0xffffff),
infoLinkTextColor: accentColor,

View File

@ -216,8 +216,8 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
)
let messageDay = PresentationThemeChatMessage(
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xf1f1f4), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4))), primaryTextColor: .black, secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), linkHighlightColor: accentColor.withAlphaComponent(0.3), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: UIColor(rgb: 0xcacaca), pendingActivityColor: UIColor(rgb: 0x525252, alpha: 0.6), fileTitleColor: accentColor, fileDescriptionColor: UIColor(rgb: 0x999999), fileDurationColor: UIColor(rgb: 0x525252, alpha: 0.6), mediaPlaceholderColor: UIColor(rgb: 0xffffff).withMultipliedBrightnessBy(0.95), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xc8c7cc), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: UIColor(rgb: 0xc8c7cc), bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0xffffff, alpha: 0.8)), actionButtonsStrokeColor: PresentationThemeVariableColor(withWallpaper: .clear, withoutWallpaper: accentColor), actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: .white, withoutWallpaper: accentColor), textSelectionColor: accentColor.withAlphaComponent(0.3), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleFillColor.withMultipliedBrightnessBy(0.7), stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleFillColor.withMultipliedBrightnessBy(0.7), stroke: outgoingBubbleStrokeColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.3), scamColor: outgoingPrimaryTextColor, textHighlightColor: UIColor(rgb: 0xffe438), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultipliedBrightnessBy(0.95), polls: PresentationThemeChatBubblePolls(radioButton: outgoingSecondaryTextColor, radioProgress: outgoingPrimaryTextColor, highlight: outgoingPrimaryTextColor.withAlphaComponent(0.12), separator: outgoingSecondaryTextColor, bar: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0xffffff, alpha: 0.8)), actionButtonsStrokeColor: PresentationThemeVariableColor(withWallpaper: .clear, withoutWallpaper: accentColor), actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: .white, withoutWallpaper: accentColor), textSelectionColor: outgoingSelectionBaseColor.withAlphaComponent(0.2), textSelectionKnobColor: outgoingSelectionBaseColor),
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xf1f1f4), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4))), primaryTextColor: .black, secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), linkHighlightColor: accentColor.withAlphaComponent(0.3), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xffc738), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: UIColor(rgb: 0xcacaca), pendingActivityColor: UIColor(rgb: 0x525252, alpha: 0.6), fileTitleColor: accentColor, fileDescriptionColor: UIColor(rgb: 0x999999), fileDurationColor: UIColor(rgb: 0x525252, alpha: 0.6), mediaPlaceholderColor: UIColor(rgb: 0xffffff).withMultipliedBrightnessBy(0.95), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xc8c7cc), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: UIColor(rgb: 0xc8c7cc), bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0xffffff, alpha: 0.8)), actionButtonsStrokeColor: PresentationThemeVariableColor(withWallpaper: .clear, withoutWallpaper: accentColor), actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: .white, withoutWallpaper: accentColor), textSelectionColor: accentColor.withAlphaComponent(0.3), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleFillColor.withMultipliedBrightnessBy(0.7), stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, highlightedFill: outgoingBubbleFillColor.withMultipliedBrightnessBy(0.7), stroke: outgoingBubbleStrokeColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.3), scamColor: outgoingPrimaryTextColor, textHighlightColor: UIColor(rgb: 0xffc738), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultipliedBrightnessBy(0.95), polls: PresentationThemeChatBubblePolls(radioButton: outgoingSecondaryTextColor, radioProgress: outgoingPrimaryTextColor, highlight: outgoingPrimaryTextColor.withAlphaComponent(0.12), separator: outgoingSecondaryTextColor, bar: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0xffffff, alpha: 0.8)), actionButtonsStrokeColor: PresentationThemeVariableColor(withWallpaper: .clear, withoutWallpaper: accentColor), actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: .white, withoutWallpaper: accentColor), textSelectionColor: outgoingSelectionBaseColor.withAlphaComponent(0.2), textSelectionKnobColor: outgoingSelectionBaseColor),
freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xE5E5EA), highlightedFill: UIColor(rgb: 0xDADADE), stroke: UIColor(rgb: 0xE5E5EA)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xE5E5EA), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xE5E5EA))),
infoPrimaryTextColor: UIColor(rgb: 0x000000),
infoLinkTextColor: UIColor(rgb: 0x004bad),

View File

@ -18,7 +18,7 @@ public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeRefe
return theme
}
public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, accentColor: UIColor?, serviceBackgroundColor: UIColor, baseColor: PresentationThemeBaseColor?, preview: Bool = false) -> PresentationTheme {
public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, accentColor: UIColor?, serviceBackgroundColor: UIColor, baseColor: PresentationThemeBaseColor?, preview: Bool = false) -> PresentationTheme? {
let theme: PresentationTheme
switch themeReference {
case let .builtin(reference):
@ -27,13 +27,13 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati
if let path = mediaBox.completedResourcePath(info.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) {
theme = loadedTheme
} else {
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)
return nil
}
case let .cloud(info):
if let file = info.theme.file, let path = mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) {
theme = loadedTheme
} else {
theme = makeDefaultPresentationTheme(reference: .dayClassic, accentColor: nil, serviceBackgroundColor: serviceBackgroundColor, baseColor: baseColor, preview: preview)
return nil
}
}
return theme

View File

@ -261,7 +261,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager) -
}
let effectiveAccentColor = themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.color
themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.baseColor ?? .blue)
themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor, baseColor: themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.baseColor ?? .blue) ?? defaultPresentationTheme
if effectiveTheme != themeSettings.theme {
switch effectiveChatWallpaper {
@ -514,7 +514,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI
}
let effectiveAccentColor = themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.color
let themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveAccentColor, serviceBackgroundColor: serviceBackgroundColor, baseColor: themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.baseColor ?? .blue)
let themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveAccentColor, serviceBackgroundColor: serviceBackgroundColor, baseColor: themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.baseColor ?? .blue) ?? defaultPresentationTheme
if effectiveTheme != themeSettings.theme && themeSettings.themeSpecificChatWallpapers[effectiveTheme.index] == nil {
switch effectiveChatWallpaper {

View File

@ -565,7 +565,7 @@ public struct PresentationResourcesChat {
public static func chatHistoryNavigationButtonBadgeImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatHistoryNavigationButtonBadgeImage.rawValue, { theme in
return generateFilledCircleImage(diameter: 18.0, color: theme.chat.historyNavigation.badgeBackgroundColor, strokeColor: theme.chat.historyNavigation.badgeStrokeColor, strokeWidth: 1.0, backgroundColor: nil)
return generateStretchableFilledCircleImage(diameter: 18.0, color: theme.chat.historyNavigation.badgeBackgroundColor, strokeColor: theme.chat.historyNavigation.badgeStrokeColor, strokeWidth: 1.0, backgroundColor: nil)
})
}

View File

@ -237,7 +237,12 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
let panelHeight = defaultHeight(metrics: metrics)
if self.discussButton.isHidden {
self.button.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: width - leftInset - rightInset, height: panelHeight))
if let action = self.action, action == .muteNotifications || action == .unmuteNotifications {
let buttonWidth = self.button.titleNode.calculateSizeThatFits(CGSize(width: width, height: panelHeight)).width + 24.0
self.button.frame = CGRect(origin: CGPoint(x: floor((width - buttonWidth) / 2.0), y: 0.0), size: CGSize(width: buttonWidth, height: panelHeight))
} else {
self.button.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: width - leftInset - rightInset, height: panelHeight))
}
} else {
let availableWidth = min(600.0, width - leftInset - rightInset)
let leftOffset = floor((width - availableWidth) / 2.0)

View File

@ -273,6 +273,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private weak var currentContextController: ContextController?
private weak var sendMessageActionsController: ChatSendMessageActionSheetController?
private var searchResultsController: ChatSearchResultsController?
private var screenCaptureEventsDisposable: Disposable?
private let chatAdditionalDataDisposable = MetaDisposable()
@ -413,7 +414,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, message: message, standalone: false, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.navigationController as? NavigationController, dismissInput: {
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, message: message, standalone: false, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.effectiveNavigationController, dismissInput: {
self?.chatDisplayNode.dismissInput()
}, present: { c, a in
self?.present(c, in: .window(.root), with: a, blockInteraction: true)
@ -760,7 +761,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case let .url(url):
if isGame {
strongSelf.chatDisplayNode.dismissInput()
(strongSelf.navigationController as? NavigationController)?.pushViewController(GameController(context: strongSelf.context, url: url, message: message))
strongSelf.effectiveNavigationController?.pushViewController(GameController(context: strongSelf.context, url: url, message: message))
} else {
strongSelf.openUrl(url, concealed: false)
}
@ -973,7 +974,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.sendMessages([.message(text: command, attributes: attributes, mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil)])
}
}, openInstantPage: { [weak self] message, associatedData in
if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.navigationController as? NavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) {
if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.effectiveNavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) {
openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController)
}
}, openWallpaper: { [weak self] message in
@ -1047,7 +1048,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> deliverOnMainQueue).start(next: { peer in
if let strongSelf = self, !hashtag.isEmpty {
let searchController = HashtagSearchController(context: strongSelf.context, peer: peer, query: hashtag)
(strongSelf.navigationController as? NavigationController)?.pushViewController(searchController)
strongSelf.effectiveNavigationController?.pushViewController(searchController)
}
}))
}, updateInputState: { [weak self] f in
@ -1280,7 +1281,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> deliverOnMainQueue).start(next: { peer in
if let strongSelf = self {
let searchController = HashtagSearchController(context: strongSelf.context, peer: peer, query: hashtag)
(strongSelf.navigationController as? NavigationController)?.pushViewController(searchController)
strongSelf.effectiveNavigationController?.pushViewController(searchController)
}
})
}
@ -1447,7 +1448,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.present(controller, in: .window(.root), with: arguments)
}, pushController: { [weak self] controller in
if let strongSelf = self {
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
strongSelf.effectiveNavigationController?.pushViewController(controller)
}
}, completed: {})
}
@ -1638,7 +1639,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
case .lookup:
let controller = UIReferenceLibraryViewController(term: text)
if let window = strongSelf.navigationController?.view.window {
if let window = strongSelf.effectiveNavigationController?.view.window {
controller.popoverPresentationController?.sourceView = window
controller.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0))
window.rootViewController?.present(controller, animated: true)
@ -1688,7 +1689,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatTitleView?.pressed = { [weak self] in
if let strongSelf = self {
if strongSelf.chatLocation == .peer(strongSelf.context.account.peerId) {
(strongSelf.navigationController as? NavigationController)?.pushViewController(PeerMediaCollectionController(context: strongSelf.context, peerId: strongSelf.context.account.peerId))
strongSelf.effectiveNavigationController?.pushViewController(PeerMediaCollectionController(context: strongSelf.context, peerId: strongSelf.context.account.peerId))
} else {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
return $0.updatedTitlePanelContext {
@ -1988,7 +1989,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
strongSelf.updateReminderActivity()
if let upgradedToPeerId = upgradedToPeerId {
if let navigationController = strongSelf.navigationController as? NavigationController {
if let navigationController = strongSelf.effectiveNavigationController {
var viewControllers = navigationController.viewControllers
if let index = viewControllers.firstIndex(where: { $0 === strongSelf }) {
viewControllers[index] = ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(upgradedToPeerId))
@ -3172,6 +3173,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return current.updatedSearch(nil)
})
strongSelf.updateItemNodesSearchTextHighlightStates()
strongSelf.searchResultsController = nil
}
}, updateMessageSearch: { [weak self] query in
if let strongSelf = self {
@ -3183,24 +3185,35 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
})
strongSelf.updateItemNodesSearchTextHighlightStates()
strongSelf.searchResultsController = nil
}
}, openSearchResults: { [weak self] in
if let strongSelf = self, let searchData = strongSelf.presentationInterfaceState.search, let results = searchData.resultsState {
let _ = (strongSelf.searchResult.get()
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] searchResult in
if let strongSelf = self, let searchResult = searchResult?.0 {
let controller = ChatSearchResultsController(context: strongSelf.context, searchQuery: searchData.query, messages: searchResult.messages, navigateToMessageIndex: { index in
strongSelf.interfaceInteraction?.navigateMessageSearch(.index(index))
})
strongSelf.chatDisplayNode.dismissInput()
if case let .inline(navigationController) = strongSelf.presentationInterfaceState.mode {
navigationController?.pushViewController(controller)
} else {
strongSelf.push(controller)
}
if let controller = strongSelf.searchResultsController {
strongSelf.chatDisplayNode.dismissInput()
if case let .inline(navigationController) = strongSelf.presentationInterfaceState.mode {
navigationController?.pushViewController(controller)
} else {
strongSelf.push(controller)
}
})
} else {
let _ = (strongSelf.searchResult.get()
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] searchResult in
if let strongSelf = self, let searchResult = searchResult?.0 {
let controller = ChatSearchResultsController(context: strongSelf.context, searchQuery: searchData.query, messages: searchResult.messages, navigateToMessageIndex: { index in
strongSelf.interfaceInteraction?.navigateMessageSearch(.index(index))
})
strongSelf.chatDisplayNode.dismissInput()
if case let .inline(navigationController) = strongSelf.presentationInterfaceState.mode {
navigationController?.pushViewController(controller)
} else {
strongSelf.push(controller)
}
strongSelf.searchResultsController = controller
}
})
}
}
}, navigateMessageSearch: { [weak self] action in
if let strongSelf = self {
@ -3286,7 +3299,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
if let navigationController = strongSelf.navigationController as? NavigationController {
if let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: nil, keepStack: .always))
}
}, openPeerInfo: { [weak self] in
@ -4803,11 +4816,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private func updateItemNodesSearchTextHighlightStates() {
var searchString: String?
var resultsMessageIndices: [MessageIndex]?
if let search = self.presentationInterfaceState.search, let resultsState = search.resultsState, !resultsState.messageIndices.isEmpty {
searchString = search.query
resultsMessageIndices = resultsState.messageIndices
}
if searchString != self.controllerInteraction?.searchTextHighightState {
self.controllerInteraction?.searchTextHighightState = searchString
if searchString != self.controllerInteraction?.searchTextHighightState?.0 || resultsMessageIndices?.count != self.controllerInteraction?.searchTextHighightState?.1.count {
var searchTextHighightState: (String, [MessageIndex])?
if let searchString = searchString, let resultsMessageIndices = resultsMessageIndices {
searchTextHighightState = (searchString, resultsMessageIndices)
}
self.controllerInteraction?.searchTextHighightState = searchTextHighightState
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView {
itemNode.updateSearchTextHighlightState()
@ -4940,7 +4959,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> deliverOnMainQueue).start(next: { [weak self] peerView in
if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios") == nil && !strongSelf.presentationInterfaceState.isNotAccessible {
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) {
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
strongSelf.effectiveNavigationController?.pushViewController(infoController)
}
}
}))
@ -5319,11 +5338,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, enqueueMediaMessages: { signals in
if let strongSelf = self {
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting)
if editingMedia {
strongSelf.editMessageMediaWithLegacySignals(signals)
} else {
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting)
}
}
})
}))
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
strongSelf.effectiveNavigationController?.pushViewController(controller)
}
}, presentSelectionLimitExceeded: {
guard let strongSelf = self else {
@ -5363,7 +5386,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
strongSelf.chatDisplayNode.dismissInput()
(strongSelf.navigationController as? NavigationController)?.pushViewController(legacyController)
strongSelf.effectiveNavigationController?.pushViewController(legacyController)
}
})
})
@ -5390,7 +5413,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, enqueueMediaMessages: { [weak self] signals in
if let strongSelf = self {
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting)
if editingMessage {
strongSelf.editMessageMediaWithLegacySignals(signals)
} else {
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting)
}
}
})
}))
@ -5418,7 +5445,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
strongSelf.chatDisplayNode.dismissInput()
(strongSelf.navigationController as? NavigationController)?.pushViewController(legacyLocationPickerController(context: strongSelf.context, selfPeer: selfPeer, peer: peer, sendLocation: { coordinate, venue, _ in
strongSelf.effectiveNavigationController?.pushViewController(legacyLocationPickerController(context: strongSelf.context, selfPeer: selfPeer, peer: peer, sendLocation: { coordinate, venue, _ in
guard let strongSelf = self else {
return
}
@ -5463,7 +5490,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let contactsController = ContactSelectionControllerImpl(ContactSelectionControllerParams(context: self.context, title: { $0.Contacts_Title }, displayDeviceContacts: true))
contactsController.navigationPresentation = .modal
self.chatDisplayNode.dismissInput()
(self.navigationController as? NavigationController)?.pushViewController(contactsController)
self.effectiveNavigationController?.pushViewController(contactsController)
self.controllerNavigationDisposable.set((contactsController.result
|> deliverOnMainQueue).start(next: { [weak self] peer in
if let strongSelf = self, let peer = peer {
@ -5542,7 +5569,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.sendMessages([message])
}
}), completed: nil, cancelled: nil)
(strongSelf.navigationController as? NavigationController)?.pushViewController(contactController)
strongSelf.effectiveNavigationController?.pushViewController(contactController)
}
}
}))
@ -5552,7 +5579,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private func presentPollCreation() {
if case let .peer(peerId) = self.chatLocation {
(self.navigationController as? NavigationController)?.pushViewController(createPollController(context: self.context, peerId: peerId, completion: { [weak self] message in
self.effectiveNavigationController?.pushViewController(createPollController(context: self.context, peerId: peerId, completion: { [weak self] message in
guard let strongSelf = self else {
return
}
@ -5834,10 +5861,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.recorderFeedback?.error()
strongSelf.recorderFeedback = nil
} else if let waveform = data.waveform {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let resource = LocalFileMediaResource(fileId: randomId, size: data.compressedData.count)
let resource = LocalFileMediaResource(fileId: arc4random64(), size: data.compressedData.count)
strongSelf.context.account.postbox.mediaBox.storeResourceData(resource.id, data: data.compressedData)
@ -6151,7 +6175,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (self.presentationInterfaceState.isScheduledMessages && messageId.id != 0 && !Namespaces.Message.allScheduled.contains(messageId.namespace)) {
if let navigationController = self.navigationController as? NavigationController {
if let navigationController = self.effectiveNavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(messageId), keepStack: .always))
}
} else if case let .peer(peerId) = self.chatLocation, (messageLocation.peerId == peerId || forceInCurrentChat) {
@ -6292,7 +6316,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition)
completion?()
} else {
(strongSelf.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message($0) }))
strongSelf.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message($0) }))
completion?()
}
}
@ -6380,14 +6404,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let parentController = strongSelf.parentController {
(parentController.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready)
} else {
(strongSelf.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready)
strongSelf.effectiveNavigationController?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready)
}
}
})
}
}
self.chatDisplayNode.dismissInput()
(self.navigationController as? NavigationController)?.pushViewController(controller)
self.effectiveNavigationController?.pushViewController(controller)
}
private func openPeer(peerId: PeerId?, navigation: ChatControllerInteractionNavigateToPeer, fromMessage: Message?) {
@ -6427,7 +6451,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.navigationActionDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peer in
if let strongSelf = self, let peer = peer {
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) {
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
strongSelf.effectiveNavigationController?.pushViewController(infoController)
}
}
}))
@ -6443,15 +6467,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
})
|> deliverOnMainQueue).start(completed: { [weak self] in
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
if let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, updateTextInputState: textInputState))
}
})
} else {
(self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), subject: subject))
self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), subject: subject))
}
case let .withBotStartPayload(botStart):
(self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), botStart: botStart))
self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), botStart: botStart))
default:
break
}
@ -6497,14 +6521,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}))
(strongSelf.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready)
strongSelf.effectiveNavigationController?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready)
}
})
}
}
}
self.chatDisplayNode.dismissInput()
(self.navigationController as? NavigationController)?.pushViewController(controller)
self.effectiveNavigationController?.pushViewController(controller)
}
default:
break
@ -6675,7 +6699,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
if deleteChat {
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
(strongSelf.navigationController as? NavigationController)?.filterController(strongSelf, animated: true)
strongSelf.effectiveNavigationController?.filterController(strongSelf, animated: true)
} else if reportSpam {
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam).start()
}
@ -6808,7 +6832,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.commitPurposefulAction()
self.chatDisplayNode.historyNode.disconnect()
let _ = removePeerChat(account: self.context.account, peerId: peerId, reportChatSpam: reportChatSpam).start()
(self.navigationController as? NavigationController)?.popToRoot(animated: true)
self.effectiveNavigationController?.popToRoot(animated: true)
let _ = requestUpdatePeerIsBlocked(account: self.context.account, peerId: peerId, isBlocked: true).start()
}
@ -6830,7 +6854,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
private func openResolved(_ result: ResolvedUrl) {
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat, navigationController: self.navigationController as? NavigationController, openPeer: { [weak self] peerId, navigation in
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat, navigationController: self.effectiveNavigationController, openPeer: { [weak self] peerId, navigation in
guard let strongSelf = self else {
return
}
@ -6840,7 +6864,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let subject = subject, case let .message(messageId) = subject {
strongSelf.navigateToMessage(from: nil, to: .id(messageId))
}
} else if let navigationController = strongSelf.navigationController as? NavigationController {
} else if let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always))
}
case .info:
@ -6849,7 +6873,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> deliverOnMainQueue).start(next: { [weak self] peer in
if let strongSelf = self, peer.restrictionText(platform: "ios") == nil {
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) {
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
strongSelf.effectiveNavigationController?.pushViewController(infoController)
}
}
}))
@ -6858,7 +6882,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
$0.updatedBotStartPayload(startPayload.payload)
})
} else if let navigationController = strongSelf.navigationController as? NavigationController {
} else if let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), botStart: startPayload))
}
default:
@ -6947,7 +6971,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private func openUrlIn(_ url: String) {
let actionSheet = OpenInActionSheetController(context: self.context, item: .url(url: url), openUrl: { [weak self] url in
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
if let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController {
strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: strongSelf.presentationData, navigationController: navigationController, dismissInput: {
self?.chatDisplayNode.dismissInput()
})
@ -7003,7 +7027,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
if let selectedTransitionNode = selectedTransitionNode {
if let previewData = chatMessagePreviewControllerData(context: self.context, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: self.navigationController as? NavigationController) {
if let previewData = chatMessagePreviewControllerData(context: self.context, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: self.effectiveNavigationController) {
switch previewData {
case let .gallery(gallery):
gallery.setHintWillBePresentedInPreviewingContext(true)
@ -7086,7 +7110,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
if let safariController = viewControllerToCommit as? SFSafariViewController {
if let window = self.navigationController?.view.window {
if let window = self.effectiveNavigationController?.view.window {
window.rootViewController?.present(safariController, animated: true)
}
}
@ -7171,9 +7195,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private func debugStreamSingleVideo(_ id: MessageId) {
let gallery = GalleryController(context: self.context, source: .peerMessagesAtId(id), streamSingleVideo: true, replaceRootController: { [weak self] controller, ready in
if let strongSelf = self {
(strongSelf.navigationController as? NavigationController)?.replaceTopController(controller, animated: false, ready: ready)
strongSelf.effectiveNavigationController?.replaceTopController(controller, animated: false, ready: ready)
}
}, baseNavigationController: self.navigationController as? NavigationController)
}, baseNavigationController: self.effectiveNavigationController)
self.chatDisplayNode.dismissInput()
self.present(gallery, in: .window(.root), with: GalleryControllerPresentationArguments(transitionArguments: { [weak self] messageId, media in
@ -7741,6 +7765,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private func openScheduledMessages() {
let controller = ChatControllerImpl(context: self.context, chatLocation: self.chatLocation, subject: .scheduledMessages)
controller.navigationPresentation = .modal
(self.navigationController as? NavigationController)?.pushViewController(controller)
self.effectiveNavigationController?.pushViewController(controller)
}
private var effectiveNavigationController: NavigationController? {
if let navigationController = self.navigationController as? NavigationController {
return navigationController
} else if case let .inline(navigationController) = self.presentationInterfaceState.mode {
return navigationController
} else {
return nil
}
}
}

View File

@ -110,7 +110,7 @@ public final class ChatControllerInteraction {
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
var pollActionState: ChatInterfacePollActionState
var stickerSettings: ChatInterfaceStickerSettings
var searchTextHighightState: String?
var searchTextHighightState: (String, [MessageIndex])?
var seenOneTimeAnimatedMedia = Set<MessageId>()
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String) -> Void, openMessageReactions: @escaping (MessageId) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {

View File

@ -149,7 +149,7 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
return false
}
func updateSearchTextHighlightState(text: String?) {
func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
}
func updateAutomaticMediaDownloadSettings(_ settings: MediaAutoDownloadSettings) {

View File

@ -2676,7 +2676,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
override func updateSearchTextHighlightState() {
for contentNode in self.contentNodes {
contentNode.updateSearchTextHighlightState(text: self.item?.controllerInteraction.searchTextHighightState)
contentNode.updateSearchTextHighlightState(text: self.item?.controllerInteraction.searchTextHighightState?.0, messages: self.item?.controllerInteraction.searchTextHighightState?.1)
}
}

View File

@ -496,12 +496,12 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
return nil
}
override func updateSearchTextHighlightState(text: String?) {
override func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
guard let item = self.item else {
return
}
let rectsSet: [[CGRect]]
if let text = text, !text.isEmpty {
if let text = text, let messages = messages, !text.isEmpty, messages.contains(item.message.index) {
rectsSet = self.textNode.textRangesRects(text: text)
} else {
rectsSet = []

View File

@ -160,9 +160,7 @@ private func fetchCachedStickerAJpegRepresentation(account: Account, resource: M
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = WebP.convert(fromWebP: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let colorData = NSMutableData()
@ -239,9 +237,7 @@ private func fetchCachedScaledImageRepresentation(resource: MediaResource, resou
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size: CGSize
@ -314,9 +310,7 @@ private func fetchCachedVideoFirstFrameRepresentation(account: Account, resource
let fullSizeImage = try imageGenerator.copyCGImage(at: CMTime(seconds: 0.0, preferredTimescale: asset.duration.timescale), actualTime: nil)
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
if let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
@ -350,9 +344,7 @@ private func fetchCachedScaledVideoFirstFrameRepresentation(account: Account, re
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: firstFrame.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = representation.size
@ -387,9 +379,7 @@ private func fetchCachedBlurredWallpaperRepresentation(resource: MediaResource,
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
if let colorImage = blurredImage(image, radius: 45.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
@ -416,9 +406,7 @@ private func fetchCachedPatternWallpaperMaskRepresentation(resource: MediaResour
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = representation.size != nil ? image.size.aspectFitted(representation.size!) : CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale)
@ -455,9 +443,7 @@ private func fetchCachedPatternWallpaperRepresentation(resource: MediaResource,
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale)
@ -541,9 +527,7 @@ private func fetchCachedBlurredWallpaperRepresentation(account: Account, resourc
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
if let colorImage = blurredImage(image, radius: 45.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
@ -570,9 +554,7 @@ private func fetchCachedPatternWallpaperMaskRepresentation(account: Account, res
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = representation.size != nil ? image.size.aspectFitted(representation.size!) : CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale)
@ -609,9 +591,7 @@ private func fetchCachedPatternWallpaperRepresentation(account: Account, resourc
return Signal({ subscriber in
if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) {
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale)
@ -663,9 +643,7 @@ private func fetchCachedAlbumArtworkRepresentation(account: Account, resource: M
switch result {
case let .artworkData(data):
if let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
var size = image.size
@ -707,9 +685,7 @@ private func fetchEmojiThumbnailRepresentation(account: Account, resource: Media
return .never()
}
return Signal({ subscriber in
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let nsString = (resource.emoji as NSString)
@ -818,9 +794,7 @@ private func fetchEmojiRepresentation(account: Account, resource: MediaResource,
|> mapToSignal { data in
return Signal({ subscriber in
if let data = data, let image = UIImage(data: data) {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let path = NSTemporaryDirectory() + "\(randomId)"
let path = NSTemporaryDirectory() + "\(arc4random64())"
let url = URL(fileURLWithPath: path)
let size = CGSize(width: 160.0, height: 160.0)

View File

@ -302,7 +302,7 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode {
return (layout, { [weak self] synchronousLoads in
if let strongSelf = self {
if item.topItems.count < Int(item.info.count) && item.topItems.count < 5 && strongSelf.item?.info.id != item.info.id {
if (item.topItems.count < Int(item.info.count) || item.topItems.count < 5) && strongSelf.item?.info.id != item.info.id {
strongSelf.preloadDisposable.set(preloadedFeaturedStickerSet(network: item.account.network, postbox: item.account.postbox, id: item.info.id).start())
}
strongSelf.item = item

View File

@ -18,6 +18,7 @@ import WalletUI
import LegacyMediaPickerUI
import LocalMediaResources
import OverlayStatusController
import AlertUI
private enum CallStatusText: Equatable {
case none
@ -1042,10 +1043,18 @@ public final class SharedAccountContextImpl: SharedAccountContext {
let tonContext = storedContext.context(config: config, blockchainName: blockchainName)
if wallets.wallets.isEmpty {
if let _ = currentPublicKey {
present(WalletSplashScreen(context: context, tonContext: tonContext, mode: .intro, walletCreatedPreloadState: nil))
if case .send = walletContext {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = textAlertController(context: context, title: presentationData.strings.Conversation_WalletRequiredTitle, text: presentationData.strings.Conversation_WalletRequiredText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Conversation_WalletRequiredNotNow, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Conversation_WalletRequiredSetup, action: { [weak self] in
self?.openWallet(context: context, walletContext: .generic, present: present)
})])
present(controller)
} else {
present(WalletSplashScreen(context: context, tonContext: tonContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil))
if let _ = currentPublicKey {
present(WalletSplashScreen(context: context, tonContext: tonContext, mode: .intro, walletCreatedPreloadState: nil))
} else {
present(WalletSplashScreen(context: context, tonContext: tonContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil))
}
}
} else {
let walletInfo = wallets.wallets[0].info

View File

@ -426,7 +426,6 @@ final class SharedMediaPlayer {
switch playbackItem {
case let .audio(player):
player.setBaseRate(rateValue)
case let .instantVideo(node):
node.setBaseRate(rateValue)
}

View File

@ -174,6 +174,10 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
}
func setup(item: StickerPaneSearchGlobalItem) {
if item.topItems.count < Int(item.info.count) && item.topItems.count < 5 && self.item?.info.id != item.info.id {
self.preloadDisposable.set(preloadedFeaturedStickerSet(network: item.account.network, postbox: item.account.postbox, id: item.info.id).start())
}
self.item = item
self.setNeedsLayout()
@ -210,17 +214,8 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.info.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - leftInset - rightInset - 20.0 - installLayout.size.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.strings.StickerPack_StickerCount(item.info.count), font: statusFont, textColor: item.theme.chat.inputMediaPanel.stickersSectionTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - leftInset - rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var topItems = item.topItems
if topItems.count > 5 {
topItems.removeSubrange(5 ..< topItems.count)
}
let strongSelf = self
if item.topItems.count < Int(item.info.count) && item.topItems.count < 5 && strongSelf.item?.info.id != item.info.id {
strongSelf.preloadDisposable.set(preloadedFeaturedStickerSet(network: item.account.network, postbox: item.account.postbox, id: item.info.id).start())
}
strongSelf.item = item
let _ = installApply()
let _ = titleApply()
@ -268,6 +263,11 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
var offset = sideInset
let itemSpacing = (max(0, availableWidth - 5.0 * itemSide - sideInset * 2.0)) / 4.0
var topItems = item.topItems
if topItems.count > 5 {
topItems.removeSubrange(5 ..< topItems.count)
}
for i in 0 ..< topItems.count {
let file = topItems[i].file
let node: TrendingTopItemNode

View File

@ -125,7 +125,7 @@ private final class WalletQrViewScreenNode: ViewControllerTracingNode {
self.imageNode = TransformImageNode()
self.imageNode.clipsToBounds = true
self.imageNode.cornerRadius = 12.0
self.imageNode.cornerRadius = 14.0
self.iconNode = AnimatedStickerNode()
if let path = getAppBundle().path(forResource: "WalletIntroStatic", ofType: "tgs") {

View File

@ -480,8 +480,8 @@ public func walletSendScreen(context: AccountContext, tonContext: TonContext, ra
var emptyItem: ItemListControllerEmptyStateItem?
if let walletState = walletState {
let textLength: Int = state.comment.data(using: .utf8, allowLossyConversion: true)?.count ?? 0
sendEnabled = isValidAddress(state.address, exactLength: true) && amount > 0 && amount <= walletState.balance && state.comment.count <= walletTextLimit
sendEnabled = isValidAddress(state.address, exactLength: true) && amount > 0 && amount <= walletState.balance && textLength <= walletTextLimit
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Wallet_Send_Send), style: .bold, enabled: sendEnabled, action: {
arguments.proceed()
})
@ -489,7 +489,7 @@ public func walletSendScreen(context: AccountContext, tonContext: TonContext, ra
rightNavigationButton = nil
emptyItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Wallet_Send_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(entries: walletSendScreenEntries(presentationData: presentationData, balance: walletState?.balance, state: state), style: .blocks, focusItemTag: focusItemTag, emptyStateItem: emptyItem, animateChanges: false)

View File

@ -140,14 +140,17 @@ public final class WalletSplashScreen: ViewController {
guard let strongSelf = self else {
return
}
var title: String?
let text: String
switch error {
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
case .network:
text = strongSelf.presentationData.strings.Wallet_Send_NetworkError
title = strongSelf.presentationData.strings.Wallet_Send_NetworkErrorTitle
text = strongSelf.presentationData.strings.Wallet_Send_NetworkErrorText
case .notEnoughFunds:
text = strongSelf.presentationData.strings.Wallet_Send_ErrorNotEnoughFunds
title = strongSelf.presentationData.strings.Wallet_Send_ErrorNotEnoughFundsTitle
text = strongSelf.presentationData.strings.Wallet_Send_ErrorNotEnoughFundsText
case .messageTooLong:
text = strongSelf.presentationData.strings.Login_UnknownError
case .invalidAddress:
@ -173,7 +176,7 @@ public final class WalletSplashScreen: ViewController {
text = strongSelf.presentationData.strings.Login_UnknownError
}
}
let controller = textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
let controller = textAlertController(context: strongSelf.context, title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
if let navigationController = strongSelf.navigationController as? NavigationController {
navigationController.popViewController(animated: true)
}