Various UI fixes

This commit is contained in:
Ilya Laktyushin 2019-08-23 06:55:33 +03:00
parent e3a669f489
commit cfb5d2027a
84 changed files with 860 additions and 806 deletions

View File

@ -21,7 +21,6 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
let apiId: Int32 = buildConfig.apiId
let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)"

View File

@ -19,7 +19,6 @@ class ShareRootController: UIViewController {
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
let apiId: Int32 = buildConfig.apiId
let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)"

View File

@ -4614,6 +4614,7 @@ Any member of this group will be able to see messages in the channel.";
"ScheduledMessages.DeleteMany" = "Delete Scheduled Messages";
"ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet...";
"ScheduledMessages.BotActionUnavailable" = "This action will become available after the message is published.";
"ScheduledMessages.PollUnavailable" = "Voting will become available after the message is published.";
"Conversation.SendMessage.SetReminder" = "Set a Reminder";

View File

@ -838,7 +838,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode<BotCheckoutEntry>,
}
if let shippingOptions = strongSelf.currentValidatedFormInfo?.shippingOptions, let shippingOptionId = strongSelf.currentShippingOptionId {
if let shippingOptionIndex = shippingOptions.index(where: { $0.id == shippingOptionId }) {
if let shippingOptionIndex = shippingOptions.firstIndex(where: { $0.id == shippingOptionId }) {
for price in shippingOptions[shippingOptionIndex].prices {
totalAmount += price.amount

View File

@ -154,6 +154,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
self.textFieldNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(12.0)]
self.textFieldNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textFieldNode.textField.isSecureTextEntry = true
self.textFieldNode.textField.tintColor = theme.list.itemAccentColor
super.init()

View File

@ -80,6 +80,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
self.textField.textField.textColor = theme.list.itemPrimaryTextColor
self.textField.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: titleFont, textColor: theme.list.itemPlaceholderTextColor)
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor
}
let leftInset: CGFloat = 16.0
@ -97,6 +98,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
self.theme = theme
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemPrimaryTextColor)
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor
}
let leftInset: CGFloat = 16.0

View File

@ -853,7 +853,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
}
self.chatListDisplayNode.isEmptyUpdated = { [weak self] isEmpty in
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, let validLayout = strongSelf.validLayout {
if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, let _ = strongSelf.validLayout {
if isEmpty {
searchContentNode.updateListVisibleContentOffset(.known(0.0))
}

View File

@ -1402,7 +1402,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let titlePosition = strongSelf.titleNode.position
transition.animatePosition(node: strongSelf.titleNode, from: CGPoint(x: titlePosition.x - contentDelta.x, y: titlePosition.y - contentDelta.y))
let textPosition = strongSelf.textNode.position
transition.animatePositionAdditive(node: strongSelf.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
let authorPosition = strongSelf.authorNode.position

View File

@ -275,6 +275,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
if strongSelf.isNodeLoaded {
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
}
}

View File

@ -223,6 +223,8 @@ public final class DeviceAccess {
subscriber.putNext(.denied)
case .notDetermined:
subscriber.putNext(.notDetermined)
@unknown default:
fatalError()
}
subscriber.putCompletion()
return EmptyDisposable
@ -333,6 +335,8 @@ public final class DeviceAccess {
value = false
case .authorized:
value = true
@unknown default:
fatalError()
}
let _ = cachedMediaLibraryAccessStatus.swap(value)
continueWithValue(value)
@ -376,7 +380,9 @@ public final class DeviceAccess {
}
case .notDetermined:
completion(true)
}
@unknown default:
fatalError()
}
case .contacts:
let _ = (self.contactsPromise.get()
|> take(1)

View File

@ -63,7 +63,7 @@ final class InstantPageFeedbackNode: ASDisplayNode, InstantPageNode {
@objc func buttonPressed() {
self.resolveDisposable.set((resolvePeerByName(account: self.context.account, name: "previews") |> deliverOnMainQueue).start(next: { [weak self] peerId in
if let strongSelf = self, let peerId = peerId, let webPageId = strongSelf.webPage.id?.id {
if let strongSelf = self, let _ = peerId, let webPageId = strongSelf.webPage.id?.id {
strongSelf.openUrl(InstantPageUrlItem(url: "https://t.me/previews?start=webpage\(webPageId)", webpageId: nil))
}
}))

View File

@ -112,7 +112,7 @@ final class InstantPageGalleryFooterContentNode: GalleryFooterContentNode {
let sideInset: CGFloat = leftInset + 8.0
let topInset: CGFloat = 0.0
let bottomInset: CGFloat = 0.0
var textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
var x = sideInset
if let hasRTL = self.textNode.cachedLayout?.hasRTL, hasRTL {

View File

@ -787,12 +787,12 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
}
if requiresScroll {
textItem.frame = textItem.frame.offsetBy(dx: 0.0, dy: fabs(topInset))
textItem.frame = textItem.frame.offsetBy(dx: 0.0, dy: abs(topInset))
for var item in additionalItems {
item.frame = item.frame.offsetBy(dx: 0.0, dy: fabs(topInset))
item.frame = item.frame.offsetBy(dx: 0.0, dy: abs(topInset))
}
let scrollableItem = InstantPageScrollableTextItem(frame: CGRect(x: 0.0, y: 0.0, width: boundingWidth + horizontalInset * 2.0, height: height + fabs(topInset) + bottomInset), item: textItem, additionalItems: additionalItems, totalWidth: textWidth, horizontalInset: horizontalInset, rtl: textItem.containsRTL)
let scrollableItem = InstantPageScrollableTextItem(frame: CGRect(x: 0.0, y: 0.0, width: boundingWidth + horizontalInset * 2.0, height: height + abs(topInset) + bottomInset), item: textItem, additionalItems: additionalItems, totalWidth: textWidth, horizontalInset: horizontalInset, rtl: textItem.containsRTL)
items.append(scrollableItem)
} else {
items.append(contentsOf: additionalItems)

View File

@ -523,13 +523,11 @@ open class ItemListControllerNode<Entry: ItemListNodeEntry>: ASDisplayNode, UISc
}
if updatedFocusItemTag {
if let focusItemTag = focusItemTag {
var applied = false
strongSelf.listNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ItemListItemNode {
if let itemTag = itemNode.tag {
if itemTag.isEqual(to: focusItemTag) {
if let focusableNode = itemNode as? ItemListItemFocusableNode {
applied = true
focusableNode.focus()
}
}

View File

@ -208,6 +208,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
if strongSelf.isNodeLoaded {
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
}
}

View File

@ -154,6 +154,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
if let item = self.item {
self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
self.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textNode.textField.tintColor = item.theme.list.itemAccentColor
self.textNode.textField.accessibilityHint = item.placeholder
}
self.textNode.clipsToBounds = true
@ -210,6 +211,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
strongSelf.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
}
let _ = titleApply()

View File

@ -163,7 +163,7 @@ When combined with the autoreverses property, a singular animation is effectivel
/**
@abstract Returns an array containing the keys of all animations currently attached to the receiver.
@param The order of keys reflects the order in which animations will be applied.
@discussion The order of keys reflects the order in which animations will be applied.
*/
- (NSArray *)pop_animationKeys;

View File

@ -1330,8 +1330,9 @@ static UIImage *startImage = nil;
{
NSTimeInterval timestamp = timestampVal.doubleValue;
NSNumber *closestTimestamp = [self closestTimestampForTimestamp:timestamp timestamps:thumbnailTimestamps start:i finalIndex:&i];
[thumbnails addObject:_thumbnails[closestTimestamp]];
if (closestTimestamp != nil) {
[thumbnails addObject:_thumbnails[closestTimestamp]];
}
}];
return thumbnails;
@ -1339,6 +1340,9 @@ static UIImage *startImage = nil;
- (NSNumber *)closestTimestampForTimestamp:(NSTimeInterval)timestamp timestamps:(NSArray *)timestamps start:(NSUInteger)start finalIndex:(NSUInteger *)finalIndex
{
if (start >= timestamps.count) {
return nil;
}
NSTimeInterval leftTimestamp = [timestamps[start - 1] doubleValue];
NSTimeInterval rightTimestamp = [timestamps[start] doubleValue];

View File

@ -183,7 +183,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String?
return result
}
} else if (dict["type"] as! NSString) == "video" {
var thumbnail = dict["previewImage"] as? UIImage
let thumbnail = dict["previewImage"] as? UIImage
var asFile = false
if let document = dict["document"] as? NSNumber, document.boolValue {
asFile = true

View File

@ -503,21 +503,10 @@ open class LegacyController: ViewController, PresentableController {
switch self.presentation {
case .modal:
self.controllerNode.animateModalOut { [weak self] in
if let controller = self?.legacyController as? TGViewController {
//controller.didDismiss()
} else if let controller = self?.legacyController as? TGNavigationController {
//controller.didDismiss()
}
self?.presentingViewController?.dismiss(animated: false, completion: completion)
}
case .custom:
if let controller = self.legacyController as? TGViewController {
//controller.didDismiss()
} else if let controller = self.legacyController as? TGNavigationController {
//controller.didDismiss()
}
self.presentingViewController?.dismiss(animated: false, completion: completion)
case .navigation:
break
}

View File

@ -73,7 +73,7 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
return { [weak self] account, theme, peer, liveActive in
let backgroundImage: UIImage?
var hasPulse = false
if let peer = peer {
if let _ = peer {
backgroundImage = avatarBackgroundImage
if let liveActive = liveActive {

View File

@ -185,6 +185,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.tintColor = self.accentColor
self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
self.textFieldNode.textField.tintColor = self.accentColor
if self.useCustomNumpad {
switch self.fieldType {

View File

@ -144,6 +144,7 @@ final class FormControllerTextInputItemNode: FormBlockItemNode<FormControllerTex
}
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)
if !(self.textField.textField.attributedPlaceholder?.isEqual(to: attributedPlaceholder) ?? false) {

View File

@ -163,7 +163,6 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
let wrappingContentRect = CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - insets.bottom - navigationBarHeight))
let contentRect = CGRect(origin: CGPoint(), size: wrappingContentRect.size)
let overscrollY = self.scrollNode.view.bounds.minY
transition.updateFrame(node: self.scrollNode, frame: wrappingContentRect)
if let contentNode = self.contentNode {
@ -608,7 +607,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
}
let completionImpl: (SecureIdDocumentFormRequestedData) -> Void = { [weak self] requestedData in
guard let strongSelf = self, let state = strongSelf.state, let verificationState = state.verificationState, case let .verified(context) = verificationState, let formData = form.formData, let validLayout = strongSelf.validLayout?.0 else {
guard let strongSelf = self, let state = strongSelf.state, let verificationState = state.verificationState, case .verified = verificationState, let formData = form.formData, let validLayout = strongSelf.validLayout?.0 else {
return
}

View File

@ -60,6 +60,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
self.inputField.textField.textColor = theme.list.freeInputField.primaryColor
self.inputField.textField.attributedPlaceholder = NSAttributedString(string: hint.isEmpty ? strings.LoginPassword_PasswordPlaceholder : hint, font: passwordFont, textColor: theme.list.freeInputField.placeholderColor)
self.inputField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputField.textField.tintColor = theme.list.itemAccentColor
self.buttonNode = HighlightableButtonNode()

View File

@ -2953,7 +2953,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
}
index += 1
}
if let _ = innerState.documents.index(where: { $0.id == document.id }) {
if let _ = innerState.documents.firstIndex(where: { $0.id == document.id }) {
for itemDocument in innerState.documents {
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
if document.id == itemDocument.id {
@ -2962,7 +2962,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
index += 1
}
}
if let _ = innerState.translations.index(where: { $0.id == document.id }) {
if let _ = innerState.translations.firstIndex(where: { $0.id == document.id }) {
for itemDocument in innerState.translations {
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
if document.id == itemDocument.id {

View File

@ -123,8 +123,10 @@ final class SecureIdValueFormPhoneItemNode: FormBlockItemNode<SecureIdValueFormP
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
}

View File

@ -60,6 +60,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor)
self.inputNode.textField.textAlignment = .center
self.inputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputNode.textField.tintColor = theme.list.itemAccentColor
switch inputType {
case .password:
self.inputNode.textField.isSecureTextEntry = true
@ -127,6 +128,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
self.theme = presentationData.theme
self.inputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor
self.inputNode.textField.tintColor = self.theme.list.itemAccentColor
}
func updateIsEnabled(_ isEnabled: Bool) {

View File

@ -178,7 +178,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
}
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: self.context.account, representations: representations), dispatchOnDisplayLink: false)
self.zoomableContent = (largestSize.dimensions, self.imageNode)
if let largestIndex = representations.index(where: { $0.representation == largestSize }) {
if let largestIndex = representations.firstIndex(where: { $0.representation == largestSize }) {
self.fetchDisposable.set(fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, reference: representations[largestIndex].reference).start())
}
@ -192,7 +192,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
strongSelf.statusNode.isHidden = false
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
strongSelf.statusNode.transitionToState(.download(.white), completion: {})
case let .Fetching(isActive, progress):
case let .Fetching(_, progress):
strongSelf.statusNode.isHidden = false
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027)
@ -345,7 +345,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
representations = imageRepresentations
}
if let largestIndex = representations.index(where: { $0.representation == largestSize }) {
if let largestIndex = representations.firstIndex(where: { $0.representation == largestSize }) {
self.fetchDisposable.set(fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, reference: representations[largestIndex].reference).start())
}
default:

View File

@ -80,11 +80,12 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor
self.textInputNode.textField.isSecureTextEntry = true
self.textInputNode.textField.returnKeyType = .done
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.clipsToBounds = true
self.textInputNode.textField.delegate = self
self.textInputNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textField.tintColor = self.theme.list.itemAccentColor
}
func updateTheme(_ theme: PresentationTheme) {
@ -94,6 +95,7 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.textColor = theme.list.itemPrimaryTextColor
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(14.0), NSAttributedString.Key.foregroundColor: theme.actionSheet.inputTextColor]
self.textInputNode.textField.tintColor = theme.list.itemAccentColor
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(14.0), textColor: theme.actionSheet.inputPlaceholderColor)
}

View File

@ -184,6 +184,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
if let item = self.item {
self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor
self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
}
}
@ -233,6 +234,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor
strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.chatList.searchBarKeyboardColor.keyboardAppearance
strongSelf.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: [])
}

View File

@ -805,45 +805,33 @@ public func chatMessagePhotoInternal(photoData: Signal<Tuple3<Data?, Data?, Bool
let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
var sideBlurredImage: UIImage?
if true {
let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
let additionalContextSize = thumbnailContextFittingSize
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
additionalBlurContext.withFlippedContext { c in
c.interpolationQuality = .default
if let image = thumbnailContext.generateImage()?.cgImage {
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
}
let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
let additionalContextSize = thumbnailContextFittingSize
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
additionalBlurContext.withFlippedContext { c in
c.interpolationQuality = .default
if let image = thumbnailContext.generateImage()?.cgImage {
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
}
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
sideBlurredImage = additionalBlurContext.generateImage()
} else {
sideBlurredImage = thumbnailContext.generateImage()
}
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
sideBlurredImage = additionalBlurContext.generateImage()
} else {
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 74.0, height: 74.0))
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
sideBlurredImage = thumbnailContext.generateImage()
}
@ -1230,7 +1218,7 @@ public func chatSecretPhoto(account: Account, photoReference: ImageMediaReferenc
}
private func avatarGalleryThumbnailDatas(postbox: Postbox, representations: [ImageRepresentationWithReference], fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0), autoFetchFullSize: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = imageRepresentationLargerThan(representations.map({ $0.representation }), size: fullRepresentationSize), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = imageRepresentationLargerThan(representations.map({ $0.representation }), size: fullRepresentationSize), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
let maybeFullSize = postbox.mediaBox.resourceData(largestRepresentation.resource)
let signal = maybeFullSize
@ -1670,45 +1658,33 @@ public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: File
if let fullSizeImage = blurSourceImage {
var sideBlurredImage: UIImage?
let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
if true {
let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
let additionalContextSize = thumbnailContextFittingSize
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
additionalBlurContext.withFlippedContext { c in
c.interpolationQuality = .default
if let image = thumbnailContext.generateImage()?.cgImage {
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
}
let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 {
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
let additionalContextSize = thumbnailContextFittingSize
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
additionalBlurContext.withFlippedContext { c in
c.interpolationQuality = .default
if let image = thumbnailContext.generateImage()?.cgImage {
c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
}
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
sideBlurredImage = additionalBlurContext.generateImage()
} else {
sideBlurredImage = thumbnailContext.generateImage()
}
imageFastBlur(Int32(additionalContextSize.width), Int32(additionalContextSize.height), Int32(additionalBlurContext.bytesPerRow), additionalBlurContext.bytes)
sideBlurredImage = additionalBlurContext.generateImage()
} else {
let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 74.0, height: 74.0))
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
thumbnailContext.withFlippedContext { c in
c.interpolationQuality = .none
c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
}
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
sideBlurredImage = thumbnailContext.generateImage()
}
@ -2307,7 +2283,7 @@ public func instantPageImageFile(account: Account, fileReference: FileMediaRefer
}
private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
let maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource)

View File

@ -103,4 +103,5 @@ public protocol ItemCollectionItem: PostboxCoding {
public enum ItemCollectionSearchQuery {
case exact(ValueBoxKey)
case matching([ValueBoxKey])
case any([ValueBoxKey])
}

View File

@ -229,6 +229,8 @@ final class ItemCollectionItemTable: Table {
references = self.reverseIndexTable.exactReferences(namespace: ReverseIndexNamespace(namespace), token: token)
case let .matching(tokens):
references = Array(self.reverseIndexTable.matchingReferences(namespace: ReverseIndexNamespace(namespace), tokens: tokens))
case let .any(tokens):
references = Array(self.reverseIndexTable.matchingReferences(namespace: ReverseIndexNamespace(namespace), tokens: tokens, union: true))
}
var resultsByCollectionId: [ItemCollectionId: [(ItemCollectionItemIndex, ItemCollectionItem)]] = [:]
for reference in references {

View File

@ -426,8 +426,8 @@ final class MessageHistoryTable: Table {
self.processIndexOperations(peerId, operations: operations, processedOperationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations)
}
func clearHistory(peerId: PeerId, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
let indices = self.allMessageIndices(peerId: peerId)
func clearHistory(peerId: PeerId, namespaces: MessageIdNamespaces, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
let indices = self.allMessageIndices(peerId: peerId).filter { namespaces.contains($0.id.namespace) }
self.removeMessages(indices.map { $0.id }, operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations)
}

View File

@ -86,9 +86,9 @@ public final class Transaction {
self.postbox?.withAllMessages(peerId: peerId, namespace: namespace, f)
}
public func clearHistory(_ peerId: PeerId) {
public func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
assert(!self.disposed)
self.postbox?.clearHistory(peerId)
self.postbox?.clearHistory(peerId, namespaces: namespaces)
}
public func removeAllMessagesWithAuthor(_ peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) {
@ -1519,9 +1519,9 @@ public final class Postbox {
}
}
fileprivate func clearHistory(_ peerId: PeerId) {
self.messageHistoryTable.clearHistory(peerId: peerId, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: &currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations)
for namespace in self.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: .everywhere) {
fileprivate func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
self.messageHistoryTable.clearHistory(peerId: peerId, namespaces: namespaces, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: &currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations)
for namespace in self.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: .everywhere) where namespaces.contains(namespace) {
self.messageHistoryHoleIndexTable.remove(peerId: peerId, namespace: namespace, space: .everywhere, range: 1 ... Int32.max - 1, operations: &self.currentPeerHoleOperations)
}
}

View File

@ -188,7 +188,7 @@ final class ReverseIndexReferenceTable<T: ReverseIndexReference>: Table {
}
}
func matchingReferences(namespace: ReverseIndexNamespace, tokens: [ValueBoxKey]) -> Set<T> {
func matchingReferences(namespace: ReverseIndexNamespace, tokens: [ValueBoxKey], union: Bool = false) -> Set<T> {
var references: Set<T>?
for token in tokens {
if let references = references, references.isEmpty {
@ -208,7 +208,11 @@ final class ReverseIndexReferenceTable<T: ReverseIndexReference>: Table {
return true
}, limit: 0)
if let previousReferences = references {
references = previousReferences.intersection(currentReferences)
if union {
references = previousReferences.union(currentReferences)
} else {
references = previousReferences.intersection(currentReferences)
}
} else {
references = currentReferences
}

View File

@ -398,6 +398,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.clearButton.setImage(generateClearIcon(color: theme.inputClear), for: [])
self.iconNode.image = generateLoupeIcon(color: theme.inputIcon)
self.textField.keyboardAppearance = theme.keyboard.keyboardAppearance
self.textField.tintColor = theme.accent
if let activityIndicator = self.activityIndicator {
activityIndicator.type = .custom(theme.inputIcon, 13.0, 1.0, false)

View File

@ -128,8 +128,10 @@ final class ChangePhoneNumberControllerNode: ASDisplayNode {
self.phoneInputNode = PhoneInputNode(fontSize: 17.0)
self.phoneInputNode.countryCodeField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
self.phoneInputNode.countryCodeField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
super.init()

View File

@ -340,7 +340,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
var current = current
if current.activeServer != server {
if let _ = current.servers.index(of: server) {
if let _ = current.servers.firstIndex(of: server) {
current.activeServer = server
current.enabled = true
}
@ -352,7 +352,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
}, removeServer: { server in
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
var current = current
if let index = current.servers.index(of: server) {
if let index = current.servers.firstIndex(of: server) {
current.servers.remove(at: index)
if current.activeServer == server {
current.activeServer = nil
@ -462,7 +462,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
var current = current
if let index = current.servers.index(of: fromServer) {
if let index = current.servers.firstIndex(of: fromServer) {
current.servers.remove(at: index)
}
if let referenceServer = referenceServer {

View File

@ -384,7 +384,7 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
updateProxySettingsInteractively(transaction: transaction, { settings in
currentSettings = settings
var settings = settings
if let index = settings.servers.index(of: proxyServerSettings) {
if let index = settings.servers.firstIndex(of: proxyServerSettings) {
settings.servers[index] = proxyServerSettings
settings.activeServer = proxyServerSettings
} else {

View File

@ -343,7 +343,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
let _ = (updateProxySettingsInteractively(accountManager: accountManager, { settings in
var settings = settings
if let currentSettings = currentSettings {
if let index = settings.servers.index(of: currentSettings) {
if let index = settings.servers.firstIndex(of: currentSettings) {
settings.servers[index] = proxyServerSettings
if settings.activeServer == currentSettings {
settings.activeServer = proxyServerSettings
@ -375,7 +375,6 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
dismissImpl = { [weak controller] in
let _ = controller?.dismiss()
}
shareImpl = { [weak controller] in
let state = stateValue.with { $0 }
guard let server = proxyServerSettings(with: state), let strongController = controller else {
@ -383,6 +382,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
}
let link = shareLink(for: server)
controller?.view.endEditing(true)
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
let controller = ShareProxyServerActionSheetController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, link: link)
presentImpl?(controller, nil)

View File

@ -344,7 +344,7 @@ private func recentSessionsControllerEntries(presentationData: PresentationData,
if !sessionsState.sessions.isEmpty {
var existingSessionIds = Set<Int64>()
entries.append(.currentSessionHeader(presentationData.theme, presentationData.strings.AuthSessions_CurrentSession))
if let index = sessionsState.sessions.index(where: { $0.hash == 0 }) {
if let index = sessionsState.sessions.firstIndex(where: { $0.hash == 0 }) {
existingSessionIds.insert(sessionsState.sessions[index].hash)
entries.append(.currentSession(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, sessionsState.sessions[index]))
}

View File

@ -112,6 +112,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.delegate = self
self.textFieldNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
self.textFieldNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor
}
func updateTheme(_ theme: PresentationTheme) {
@ -123,6 +124,7 @@ final class WallpaperColorPanelNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.textColor = self.theme.chat.inputPanel.inputTextColor
self.textFieldNode.textField.keyboardAppearance = self.theme.chat.inputPanel.keyboardColor.keyboardAppearance
self.textFieldNode.textField.tintColor = self.theme.list.itemAccentColor
}
private func setColor(_ color: UIColor, updatePicker: Bool = true, ended: Bool = true) {

View File

@ -179,7 +179,7 @@ public class WallpaperGalleryController: ViewController {
switch source {
case let .list(wallpapers, central, type):
entries = wallpapers.map { .wallpaper($0, nil) }
centralEntryIndex = wallpapers.index(of: central)!
centralEntryIndex = wallpapers.firstIndex(of: central)!
if case let .wallpapers(wallpaperOptions) = type, let options = wallpaperOptions {
self.initialOptions = options

View File

@ -267,7 +267,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
}
}
return
} else if let offset = self.validOffset, self.arguments.colorPreview && fabs(offset) > 0.0 {
} else if let offset = self.validOffset, self.arguments.colorPreview && abs(offset) > 0.0 {
return
}
else {
@ -314,7 +314,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(resource: $0.resource)) })
signal = wallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, representations: convertedRepresentations, alwaysShowThumbnailFirst: true, autoFetchFullSize: false)
if let largestIndex = convertedRepresentations.index(where: { $0.representation == largestSize }) {
if let largestIndex = convertedRepresentations.firstIndex(where: { $0.representation == largestSize }) {
fetchSignal = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: convertedRepresentations[largestIndex].reference)
} else {
fetchSignal = .complete()

View File

@ -13,13 +13,15 @@ final class ShareInputFieldNodeTheme: Equatable {
let textColor: UIColor
let placeholderColor: UIColor
let clearButtonColor: UIColor
let accentColor: UIColor
let keyboard: PresentationThemeKeyboardColor
public init(backgroundColor: UIColor, textColor: UIColor, placeholderColor: UIColor, clearButtonColor: UIColor, keyboard: PresentationThemeKeyboardColor) {
public init(backgroundColor: UIColor, textColor: UIColor, placeholderColor: UIColor, clearButtonColor: UIColor, accentColor: UIColor, keyboard: PresentationThemeKeyboardColor) {
self.backgroundColor = backgroundColor
self.textColor = textColor
self.placeholderColor = placeholderColor
self.clearButtonColor = clearButtonColor
self.accentColor = accentColor
self.keyboard = keyboard
}
@ -36,6 +38,9 @@ final class ShareInputFieldNodeTheme: Equatable {
if lhs.clearButtonColor != rhs.clearButtonColor {
return false
}
if lhs.accentColor != rhs.accentColor {
return false
}
if lhs.keyboard != rhs.keyboard {
return false
}
@ -45,7 +50,7 @@ final class ShareInputFieldNodeTheme: Equatable {
extension ShareInputFieldNodeTheme {
convenience init(presentationTheme theme: PresentationTheme) {
self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, keyboard: theme.chatList.searchBarKeyboardColor)
self.init(backgroundColor: theme.actionSheet.inputBackgroundColor, textColor: theme.actionSheet.inputTextColor, placeholderColor: theme.actionSheet.inputPlaceholderColor, clearButtonColor: theme.actionSheet.inputClearButtonColor, accentColor: theme.actionSheet.controlAccentColor, keyboard: theme.chatList.searchBarKeyboardColor)
}
}
@ -95,6 +100,7 @@ final class ShareInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate {
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
self.textInputNode.keyboardAppearance = theme.keyboard.keyboardAppearance
self.textInputNode.tintColor = theme.accentColor
self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false

View File

@ -287,7 +287,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToItem: GridNodeScrollToItem?
if let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil
if let index = self.entries.index(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
if let index = self.entries.firstIndex(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
scrollToItem = GridNodeScrollToItem(index: index, position: .visible, transition: transition, directionHint: .up, adjustForSection: false)
}
}

View File

@ -42,13 +42,14 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.textInputNode.fixOffset = false
let textColor: UIColor = theme.actionSheet.inputTextColor
let keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default
textInputNode.textField.font = Font.regular(16.0)
textInputNode.textField.textColor = textColor
textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
textInputNode.textField.keyboardAppearance = keyboardAppearance
textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.font = Font.regular(16.0)
self.textInputNode.textField.textColor = textColor
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textField.keyboardAppearance = keyboardAppearance
self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
self.textInputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
super.init()

View File

@ -71,7 +71,7 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable {
return false
}
case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings):
if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme {
if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer.isEqual(rhsPeer) && arePeersEqual(lhsAssociatedPeer, rhsAssociatedPeer) && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && arePeerPresencesEqual(lhsPresence, rhsPresence) {
return true
} else {
return false
@ -436,7 +436,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToItem: GridNodeScrollToItem?
if !self.contentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil
if let index = self.entries.index(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
if let index = self.entries.firstIndex(where: { $0.peer.peerId == ensurePeerVisibleOnLayout }) {
scrollToItem = GridNodeScrollToItem(index: index, position: .visible, transition: transition, directionHint: .up, adjustForSection: false)
}
}
@ -444,7 +444,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToRecentItem: GridNodeScrollToItem?
if !self.recentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil
if let index = self.recentEntries.index(where: {
if let index = self.recentEntries.firstIndex(where: {
switch $0 {
case .topPeers:
return false

View File

@ -71,9 +71,12 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
}
public func updateTheme(_ theme: PresentationTheme) {
guard theme !== self.theme else {
return
}
self.theme = theme
self.buttonBackgroundNode.image = generateStretchableFilledCircleImage(radius: cornerRadius, color: theme.list.itemCheckColors.fillColor)
self.buttonBackgroundNode.image = generateStretchableFilledCircleImage(radius: self.buttonCornerRadius, color: theme.list.itemCheckColors.fillColor)
self.buttonGlossNode.color = theme.list.itemCheckColors.foregroundColor
self.labelNode.attributedText = NSAttributedString(string: self.title ?? "", font: Font.medium(17.0), textColor: theme.list.itemCheckColors.foregroundColor)
}

View File

@ -81,7 +81,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
}
deinit {
stickerFetchedDisposable.dispose()
self.stickerFetchedDisposable.dispose()
}
override func didLoad() {

View File

@ -29,12 +29,12 @@ public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [M
transaction.deleteMessages(ids)
}
public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId) {
public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, namespaces: MessageIdNamespaces) {
if peerId.namespace == Namespaces.Peer.SecretChat {
transaction.withAllMessages(peerId: peerId, { message in
removeMessageMedia(message: message, mediaBox: mediaBox)
return true
})
}
transaction.clearHistory(peerId)
transaction.clearHistory(peerId, namespaces: namespaces)
}

View File

@ -90,16 +90,18 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In
return postbox.transaction { transaction -> Void in
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
cloudChatAddClearHistoryOperation(transaction: transaction, peerId: peerId, explicitTopMessageId: nil, type: CloudChatClearHistoryType(type))
if type != .scheduledMessages {
if type == .scheduledMessages {
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .just(Namespaces.Message.allScheduled))
} else {
var topIndex: MessageIndex?
if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) {
topIndex = topMessage.index
}
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .not(Namespaces.Message.allScheduled))
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference {
cloudChatAddClearHistoryOperation(transaction: transaction, peerId: migrationReference.maxMessageId.peerId, explicitTopMessageId: MessageId(peerId: migrationReference.maxMessageId.peerId, namespace: migrationReference.maxMessageId.namespace, id: migrationReference.maxMessageId.id + 1), type: CloudChatClearHistoryType(type))
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId)
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId, namespaces: .all)
}
if let topIndex = topIndex {
if peerId.namespace == Namespaces.Peer.CloudUser {
@ -110,7 +112,7 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In
}
}
} else if peerId.namespace == Namespaces.Peer.SecretChat {
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .all)
if let state = transaction.getPeerChatState(peerId) as? SecretChatState {
var layer: SecretChatLayer?

View File

@ -309,7 +309,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net
|> then(deleteUser)
|> then(reportSignal)
|> then(postbox.transaction { transaction -> Void in
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id)
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .all)
})
} else if peer.id.namespace == Namespaces.Peer.CloudUser {
if let inputPeer = apiInputPeer(peer) {
@ -328,7 +328,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net
return requestClearHistory(postbox: postbox, network: network, stateManager: stateManager, inputPeer: inputPeer, maxId: operation.topMessageId?.id ?? Int32.max - 1, justClear: false, type: operation.deleteGloballyIfPossible ? .forEveryone : .forLocalPeer)
|> then(reportSignal)
|> then(postbox.transaction { transaction -> Void in
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id)
clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .not(Namespaces.Message.allScheduled))
})
} else {
return .complete()

View File

@ -282,7 +282,7 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds)
}
case .clearHistory:
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
case let .markMessagesContentAsConsumed(globallyUniqueIds):
var messageIds: [MessageId] = []
for id in globallyUniqueIds {

View File

@ -49,17 +49,17 @@ public func removePeerChat(account: Account, transaction: Transaction, mediaBox:
}
}
}
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue)
} else {
cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
if peerId.namespace == Namespaces.Peer.CloudUser {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
} else {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
}

View File

@ -106,7 +106,11 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId,
case _ as TelegramMediaImage, _ as TelegramMediaFile:
break
default:
return (nil, nil, SimpleDictionary())
if let _ = scheduleTime {
break
} else {
return (nil, nil, SimpleDictionary())
}
}
}
}

View File

@ -132,7 +132,7 @@ public func searchStickers(account: Account, query: String, scope: SearchSticker
var searchQuery: ItemCollectionSearchQuery = .exact(ValueBoxKey(query))
if query == "\u{2764}" {
searchQuery = .matching([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{fe0f}")])
searchQuery = .any([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{FE0F}")])
}
var installedItems: [FoundStickerItem] = []

View File

@ -3,50 +3,50 @@ import UIKit
import Display
public extension TabBarControllerTheme {
convenience public init(rootControllerTheme: PresentationTheme) {
convenience init(rootControllerTheme: PresentationTheme) {
let theme = rootControllerTheme.rootController.tabBar
self.init(backgroundColor: rootControllerTheme.list.plainBackgroundColor, tabBarBackgroundColor: theme.backgroundColor, tabBarSeparatorColor: theme.separatorColor, tabBarTextColor: theme.textColor, tabBarSelectedTextColor: theme.selectedIconColor, tabBarBadgeBackgroundColor: theme.badgeBackgroundColor, tabBarBadgeStrokeColor: theme.badgeStrokeColor, tabBarBadgeTextColor: theme.badgeTextColor)
}
}
public extension NavigationBarTheme {
convenience public init(rootControllerTheme: PresentationTheme) {
convenience init(rootControllerTheme: PresentationTheme) {
let theme = rootControllerTheme.rootController.navigationBar
self.init(buttonColor: theme.buttonColor, disabledButtonColor: theme.disabledButtonColor, primaryTextColor: theme.primaryTextColor, backgroundColor: theme.backgroundColor, separatorColor: theme.separatorColor, badgeBackgroundColor: theme.badgeBackgroundColor, badgeStrokeColor: theme.badgeStrokeColor, badgeTextColor: theme.badgeTextColor)
}
}
public extension NavigationBarStrings {
convenience public init(presentationStrings: PresentationStrings) {
convenience init(presentationStrings: PresentationStrings) {
self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close)
}
}
public extension NavigationBarPresentationData {
convenience public init(presentationData: PresentationData) {
convenience init(presentationData: PresentationData) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
}
convenience public init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings) {
convenience init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationTheme), strings: NavigationBarStrings(presentationStrings: presentationStrings))
}
}
public extension ActionSheetControllerTheme {
convenience public init(presentationTheme: PresentationTheme) {
convenience init(presentationTheme: PresentationTheme) {
let actionSheet = presentationTheme.actionSheet
self.init(dimColor: actionSheet.dimColor, backgroundType: actionSheet.backgroundType == .light ? .light : .dark, itemBackgroundColor: actionSheet.itemBackgroundColor, itemHighlightedBackgroundColor: actionSheet.itemHighlightedBackgroundColor, standardActionTextColor: actionSheet.standardActionTextColor, destructiveActionTextColor: actionSheet.destructiveActionTextColor, disabledActionTextColor: actionSheet.disabledActionTextColor, primaryTextColor: actionSheet.primaryTextColor, secondaryTextColor: actionSheet.secondaryTextColor, controlAccentColor: actionSheet.controlAccentColor, controlColor: presentationTheme.list.disclosureArrowColor, switchFrameColor: presentationTheme.list.itemSwitchColors.frameColor, switchContentColor: presentationTheme.list.itemSwitchColors.contentColor, switchHandleColor: presentationTheme.list.itemSwitchColors.handleColor)
}
}
public extension ActionSheetController {
convenience public init(presentationTheme: PresentationTheme) {
convenience init(presentationTheme: PresentationTheme) {
self.init(theme: ActionSheetControllerTheme(presentationTheme: presentationTheme))
}
}
public extension AlertControllerTheme {
convenience public init(presentationTheme: PresentationTheme) {
convenience init(presentationTheme: PresentationTheme) {
let actionSheet = presentationTheme.actionSheet
self.init(backgroundType: actionSheet.backgroundType == .light ? .light : .dark, backgroundColor: actionSheet.itemBackgroundColor, separatorColor: actionSheet.itemHighlightedBackgroundColor, highlightedItemColor: actionSheet.itemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor)
}

View File

@ -25,7 +25,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
outgoingBubbleFillColor = accentColor
let hsv = accentColor.hsv
accentColor = UIColor(hue: hsv.0, saturation: hsv.1 * 1.1, brightness: min(hsv.2, 0.77), alpha: 1.0)
accentColor = UIColor(hue: hsv.0, saturation: hsv.1 * 1.1, brightness: min(hsv.2, 0.7), alpha: 1.0)
} else {
outgoingPrimaryTextColor = .white
outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.65)

View File

@ -1,7 +1,6 @@
import Foundation
import UIKit
import Display
import TelegramPresentationData
private func generateStatusCheckImage(theme: PresentationTheme, single: Bool) -> UIImage? {
return generateImage(CGSize(width: single ? 13.0 : 18.0, height: 13.0), rotatedContext: { size, context in

View File

@ -1,7 +1,6 @@
import Foundation
import UIKit
import Display
import TelegramPresentationData
private func generateArrowImage(_ theme: PresentationTheme) -> UIImage? {
return generateImage(CGSize(width: 7.0, height: 13.0), rotatedContext: { size, context in

View File

@ -1,7 +1,6 @@
import Foundation
import UIKit
import Display
import TelegramPresentationData
private func generateShareButtonImage(theme: PresentationTheme) -> UIImage? {
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/NavigationShare"), color: theme.rootController.navigationBar.accentTextColor)

View File

@ -40,5 +40,7 @@ func presentationStringsPluralizationForm(_ lc: UInt32, _ value: Int32) -> Plura
return .many
case .other:
return .other
@unknown default:
fatalError()
}
}

View File

@ -107,6 +107,8 @@ private final class PhoneAndCountryNode: ASDisplayNode {
self.phoneInputNode.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor

View File

@ -108,6 +108,8 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.firstNameField.textField.textContentType = .givenName
}
self.firstNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.firstNameField.textField.tintColor = theme.list.itemAccentColor
self.lastNameField = TextFieldNode()
self.lastNameField.textField.font = Font.regular(20.0)
@ -120,6 +122,8 @@ final class AuthorizationSequenceSignUpControllerNode: ASDisplayNode, UITextFiel
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.lastNameField.textField.textContentType = .familyName
}
self.lastNameField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.lastNameField.textField.tintColor = theme.list.itemAccentColor
self.currentPhotoNode = ASImageNode()
self.currentPhotoNode.isUserInteractionEnabled = false

View File

@ -543,6 +543,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
reactionItems.append(ReactionContextItem(value: value, text: text, path: path))
}
}
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
reactionItems = []
}
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: reactionItems, recognizer: recognizer)
strongSelf.currentContextController = controller
controller.reactionSelected = { [weak controller] value in
@ -1395,6 +1398,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else {
return
}
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_PollUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
if controllerInteraction.pollActionState.pollMessageIdsInProgress[id] == nil {
controllerInteraction.pollActionState.pollMessageIdsInProgress[id] = opaqueIdentifier
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
@ -2804,7 +2811,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else {
text = "\(count) messages selected"
}
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
}
}
}, deleteSelectedMessages: { [weak self] in
@ -4547,6 +4554,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.updateChatPresentationInterfaceState(updatedChatPresentationInterfaceState, transition: transition, interactive: interactive)
}
if let selectionState = self.presentationInterfaceState.interfaceState.selectionState, !selectionState.selectedIds.isEmpty {
self.chatTitleView?.titleContent = .custom(self.presentationData.strings.Conversation_SelectedMessages(Int32(selectionState.selectedIds.count)))
} else {
}
if let button = leftNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.leftNavigationButton, target: self, selector: #selector(self.leftNavigationButtonAction)) {
if self.leftNavigationButton != button {
var animated = transition.isAnimated
@ -4586,7 +4599,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
switch updatedChatPresentationInterfaceState.mode {
case .standard:
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.deferScreenEdgeGestures = []
self.deferScreenEdgeGestures = []
case .overlay:
self.statusBar.statusBarStyle = .Hide
self.deferScreenEdgeGestures = [.top]
@ -7383,9 +7396,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let peer = peer as? TelegramUser {
let recipientHandle = INPersonHandle(value: "tg\(peerId.id)", type: .unknown)
let recipient = INPerson(personHandle: recipientHandle, nameComponents: nil, displayName: peer.displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peerId.id)")
let intent = INSendMessageIntent(recipients: [recipient], content: nil, groupName: nil, serviceName: nil, sender: nil)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .outgoing
interaction.donate { error in

View File

@ -258,7 +258,8 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout))
}
}
if chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 {
if chatPresentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 && chatPresentationInterfaceState.interfaceState.forwardMessageIds == nil {
if chatPresentationInterfaceState.hasScheduledMessages {
accessoryItems.append(.scheduledMessages)
}

View File

@ -169,13 +169,15 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
}
var displayBotStartPanel = false
if let _ = chatPresentationInterfaceState.botStartPayload {
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
displayBotStartPanel = true
}
} else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState {
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
displayBotStartPanel = true
if !chatPresentationInterfaceState.isScheduledMessages {
if let _ = chatPresentationInterfaceState.botStartPayload {
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
displayBotStartPanel = true
}
} else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState {
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
displayBotStartPanel = true
}
}
}

View File

@ -400,7 +400,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
let reactionRecognizer = ReactionSwipeGestureRecognizer(target: nil, action: nil)
self.reactionRecognizer = reactionRecognizer
reactionRecognizer.availableReactions = { [weak self] in
guard let strongSelf = self, let item = strongSelf.item else {
guard let strongSelf = self, let item = strongSelf.item, !Namespaces.Message.allScheduled.contains(item.message.id.namespace) else {
return []
}
if strongSelf.selectionNode != nil {

View File

@ -773,6 +773,9 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
canVote = true
}
}
if Namespaces.Message.allScheduled.contains(item.message.id.namespace) {
canVote = true
}
return (boundingSize.width, { boundingWidth in
var resultSize = CGSize(width: max(boundingSize.width, boundingWidth), height: boundingSize.height)

View File

@ -24,6 +24,8 @@ final class ChatScheduleTimeController: ViewController {
private let currentTime: Int32?
private let completion: (Int32) -> Void
private var presentationDataDisposable: Disposable?
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, completion: @escaping (Int32) -> Void) {
self.context = context
self.mode = mode
@ -32,6 +34,13 @@ final class ChatScheduleTimeController: ViewController {
super.init(navigationBarPresentationData: nil)
self.presentationDataDisposable = (context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self {
strongSelf.controllerNode.updatePresentationData(presentationData)
}
})
self.statusBar.statusBarStyle = .Ignore
}
@ -39,6 +48,10 @@ final class ChatScheduleTimeController: ViewController {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.presentationDataDisposable?.dispose()
}
override public func loadDisplayNode() {
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime)
self.controllerNode.completion = { [weak self] time in

View File

@ -20,7 +20,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
private let contentContainerNode: ASDisplayNode
private let contentBackgroundNode: ASImageNode
private let titleNode: ASTextNode
private let separatorNode: ASDisplayNode
private let cancelButton: HighlightableButtonNode
private let doneButton: SolidRoundedButtonNode
@ -46,8 +45,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
self.contentContainerNode = ASDisplayNode()
self.contentContainerNode.isOpaque = false
self.contentContainerNode.clipsToBounds = true
@ -55,7 +52,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.contentBackgroundNode = ASImageNode()
self.contentBackgroundNode.displaysAsynchronously = false
self.contentBackgroundNode.displayWithoutProcessing = true
self.contentBackgroundNode.image = roundedBackground
self.contentBackgroundNode.image = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
let title: String
switch mode {
@ -68,9 +65,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.titleNode = ASTextNode()
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
self.separatorNode = ASDisplayNode()
//self.separatorNode.backgroundColor = self.theme.controlColor
self.cancelButton = HighlightableButtonNode()
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
@ -107,7 +101,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.pickerView.timeZone = TimeZone.current
self.pickerView.minuteInterval = 1
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
self.contentContainerNode.view.addSubview(self.pickerView)
self.pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
@ -116,6 +109,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
if let strongSelf = self {
if strongSelf.pickerView.date < Date() {
strongSelf.updateMinimumDate()
strongSelf.updateButtonTitle()
strongSelf.pickerView.layer.addShakeAnimation()
} else {
strongSelf.doneButton.isUserInteractionEnabled = false
@ -128,6 +122,17 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.updateButtonTitle()
}
func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData
self.contentBackgroundNode.image = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
self.doneButton.updateTheme(self.presentationData.theme)
}
private func updateMinimumDate(currentTime: Int32? = nil) {
let timeZone = TimeZone(secondsFromGMT: 0)!
var calendar = Calendar(identifier: .gregorian)
@ -137,16 +142,19 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
components.second = 0
let minute = (components.minute ?? 0) % 5
let next1MinDate = calendar.date(byAdding: .minute, value: 1, to: calendar.date(from: components)!)
let next5MinDate = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!)
if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) {
self.pickerView.maximumDate = date
}
if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) {
self.pickerView.minimumDate = date
if let currentTime = currentTime {
if let next1MinDate = next1MinDate, let next5MinDate = next5MinDate {
self.pickerView.minimumDate = next1MinDate
if let currentTime = currentTime, Double(currentTime) > currentDate.timeIntervalSince1970 {
self.pickerView.date = Date(timeIntervalSince1970: Double(currentTime))
} else {
self.pickerView.date = date
self.pickerView.date = next5MinDate
}
}
}
@ -300,6 +308,5 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.pickerView.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: titleHeight), size: CGSize(width: contentContainerFrame.size.width, height: UIScreenPixel)))
}
}

View File

@ -57,6 +57,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.textInputNode.autocapitalizationType = .none
self.textInputNode.returnKeyType = .done
self.textInputNode.autocorrectionType = .no
self.textInputNode.tintColor = theme.actionSheet.controlAccentColor
self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false
@ -75,9 +76,10 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor
}
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {

View File

@ -16,6 +16,7 @@ import ChatTitleActivityNode
enum ChatTitleContent {
case peer(peerView: PeerView, onlineMemberCount: Int32?, isScheduledMessages: Bool)
case group([Peer])
case custom(String)
}
private final class ChatTitleNetworkStatusNode: ASDisplayNode {
@ -182,7 +183,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
switch titleContent {
case let .peer(peerView, _, isScheduledMessages):
if isScheduledMessages {
if let peer = peerViewMainPeer(peerView), peerView.peerId == self.account.peerId {
if peerView.peerId == self.account.peerId {
string = NSAttributedString(string: self.strings.ScheduledMessages_RemindersTitle, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
} else {
string = NSAttributedString(string: self.strings.ScheduledMessages_Title, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
@ -212,6 +213,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
}
case .group:
string = NSAttributedString(string: "Feed", font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
case let .custom(text):
string = NSAttributedString(string: text, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
}
if let string = string, self.titleNode.attributedText == nil || !self.titleNode.attributedText!.isEqual(to: string) {
@ -263,7 +266,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
}
}
default:
break
inputActivitiesAllowed = false
}
}
@ -429,7 +432,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
}
}
}
case .group:
default:
break
}

View File

@ -67,7 +67,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
}
self.contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList)), filters: filters, selectionState: ContactListNodeGroupSelectionState())
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: placeholder)
self.tokenListNode = EditableTokenListNode(theme: EditableTokenListNodeTheme(backgroundColor: self.presentationData.theme.rootController.navigationBar.backgroundColor, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, selectedTextColor: self.presentationData.theme.list.itemAccentColor, accentColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.chatList.searchBarKeyboardColor), placeholder: placeholder)
super.init()

View File

@ -32,14 +32,16 @@ final class EditableTokenListNodeTheme {
let placeholderTextColor: UIColor
let primaryTextColor: UIColor
let selectedTextColor: UIColor
let accentColor: UIColor
let keyboardColor: PresentationThemeKeyboardColor
init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, selectedTextColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, selectedTextColor: UIColor, accentColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
self.backgroundColor = backgroundColor
self.separatorColor = separatorColor
self.placeholderTextColor = placeholderTextColor
self.primaryTextColor = primaryTextColor
self.selectedTextColor = selectedTextColor
self.accentColor = accentColor
self.keyboardColor = keyboardColor
}
}
@ -123,12 +125,8 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.textColor = theme.primaryTextColor
self.textFieldNode.textField.autocorrectionType = .no
self.textFieldNode.textField.returnKeyType = .done
switch theme.keyboardColor {
case .light:
self.textFieldNode.textField.keyboardAppearance = .default
case .dark:
self.textFieldNode.textField.keyboardAppearance = .dark
}
self.textFieldNode.textField.keyboardAppearance = theme.keyboardColor.keyboardAppearance
self.textFieldNode.textField.tintColor = theme.accentColor
self.caretIndicatorNode = CaretIndicatorNode()
self.caretIndicatorNode.isLayerBacked = true

View File

@ -263,13 +263,8 @@ class PaneSearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.iconNode.image = generateLoupeIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor)
self.clearButton.setImage(generateClearIcon(color: theme.chat.inputMediaPanel.stickersSearchControlColor), for: [])
self.cancelButton.setAttributedTitle(NSAttributedString(string: strings.Common_Cancel, font: Font.regular(17.0), textColor: theme.chat.inputPanel.panelControlAccentColor), for: [])
switch theme.chatList.searchBarKeyboardColor {
case .light:
self.textField.keyboardAppearance = .default
case .dark:
self.textField.keyboardAppearance = .dark
}
self.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textField.tintColor = theme.list.itemAccentColor
if let (boundingSize, leftInset, rightInset) = self.validLayout {
self.updateLayout(boundingSize: boundingSize, leftInset: leftInset, rightInset: rightInset, transition: .immediate)

View File

@ -11,7 +11,7 @@ import PhotoResources
import LocalMediaResources
private func wallpaperDatas(account: Account, accountManager: AccountManager, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], alwaysShowThumbnailFirst: Bool = false, thumbnail: Bool = false, autoFetchFullSize: Bool = false, synchronousLoad: Bool = false) -> Signal<(Data?, Data?, Bool), NoError> {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
let maybeFullSize: Signal<MediaResourceData, NoError>
if thumbnail, let file = fileReference?.media {
@ -284,7 +284,7 @@ public enum PatternWallpaperDrawMode {
}
private func patternWallpaperDatas(account: Account, accountManager: AccountManager, representations: [ImageRepresentationWithReference], mode: PatternWallpaperDrawMode, autoFetchFullSize: Bool = false) -> Signal<(Data?, Data?, Bool), NoError> {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
let size: CGSize?
switch mode {

View File

@ -379,6 +379,8 @@ final class WatchMediaHandler: WatchRequestHandler {
round = true
case .large:
targetSize = CGSize(width: 150, height: 150);
@unknown default:
fatalError()
}
return SSignal { subscriber in

View File

@ -618,20 +618,15 @@ class WebSearchControllerNode: ASDisplayNode {
}
private func dequeueTransition() {
if let (transition, firstTime) = self.enqueuedTransitions.first {
if let (transition, _) = self.enqueuedTransitions.first {
self.enqueuedTransitions.remove(at: 0)
let completion: (GridNodeDisplayedItemRange) -> Void = { [weak self] visibleRange in
if let strongSelf = self {
}
}
if let state = self.webSearchInterfaceState.state {
self.recentQueriesNode.isHidden = !state.query.isEmpty
}
self.hasMore = transition.hasMore
self.gridNode.transaction(GridNodeTransaction(deleteItems: transition.deleteItems, insertItems: transition.insertItems, updateItems: transition.updateItems, scrollToItem: nil, updateLayout: nil, itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, synchronousLoads: true), completion: completion)
self.gridNode.transaction(GridNodeTransaction(deleteItems: transition.deleteItems, insertItems: transition.insertItems, updateItems: transition.updateItems, scrollToItem: nil, updateLayout: nil, itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, synchronousLoads: true), completion: { _ in })
}
}