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 buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
let apiId: Int32 = buildConfig.apiId
let languagesCategory = "ios" let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)" let appGroupName = "group.\(baseAppBundleId)"

View File

@ -19,7 +19,6 @@ class ShareRootController: UIViewController {
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId) let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
let apiId: Int32 = buildConfig.apiId
let languagesCategory = "ios" let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)" 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.DeleteMany" = "Delete Scheduled Messages";
"ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet..."; "ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet...";
"ScheduledMessages.BotActionUnavailable" = "This action will become available after the message is published."; "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"; "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 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 { for price in shippingOptions[shippingOptionIndex].prices {
totalAmount += price.amount 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.typingAttributes = [NSAttributedString.Key.font: Font.regular(12.0)]
self.textFieldNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.textFieldNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textFieldNode.textField.isSecureTextEntry = true self.textFieldNode.textField.isSecureTextEntry = true
self.textFieldNode.textField.tintColor = theme.list.itemAccentColor
super.init() super.init()

View File

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

View File

@ -853,7 +853,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
} }
self.chatListDisplayNode.isEmptyUpdated = { [weak self] isEmpty in 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 { if isEmpty {
searchContentNode.updateListVisibleContentOffset(.known(0.0)) searchContentNode.updateListVisibleContentOffset(.known(0.0))
} }

View File

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

View File

@ -275,6 +275,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
if strongSelf.isNodeLoaded { if strongSelf.isNodeLoaded {
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor] 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) subscriber.putNext(.denied)
case .notDetermined: case .notDetermined:
subscriber.putNext(.notDetermined) subscriber.putNext(.notDetermined)
@unknown default:
fatalError()
} }
subscriber.putCompletion() subscriber.putCompletion()
return EmptyDisposable return EmptyDisposable
@ -333,6 +335,8 @@ public final class DeviceAccess {
value = false value = false
case .authorized: case .authorized:
value = true value = true
@unknown default:
fatalError()
} }
let _ = cachedMediaLibraryAccessStatus.swap(value) let _ = cachedMediaLibraryAccessStatus.swap(value)
continueWithValue(value) continueWithValue(value)
@ -376,7 +380,9 @@ public final class DeviceAccess {
} }
case .notDetermined: case .notDetermined:
completion(true) completion(true)
} @unknown default:
fatalError()
}
case .contacts: case .contacts:
let _ = (self.contactsPromise.get() let _ = (self.contactsPromise.get()
|> take(1) |> take(1)

View File

@ -63,7 +63,7 @@ final class InstantPageFeedbackNode: ASDisplayNode, InstantPageNode {
@objc func buttonPressed() { @objc func buttonPressed() {
self.resolveDisposable.set((resolvePeerByName(account: self.context.account, name: "previews") |> deliverOnMainQueue).start(next: { [weak self] peerId in 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)) 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 sideInset: CGFloat = leftInset + 8.0
let topInset: CGFloat = 0.0 let topInset: CGFloat = 0.0
let bottomInset: 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 var x = sideInset
if let hasRTL = self.textNode.cachedLayout?.hasRTL, hasRTL { if let hasRTL = self.textNode.cachedLayout?.hasRTL, hasRTL {

View File

@ -787,12 +787,12 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
} }
if requiresScroll { 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 { 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) items.append(scrollableItem)
} else { } else {
items.append(contentsOf: additionalItems) items.append(contentsOf: additionalItems)

View File

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

View File

@ -208,6 +208,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
if strongSelf.isNodeLoaded { if strongSelf.isNodeLoaded {
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor] 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 { if let item = self.item {
self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
self.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance 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.textField.accessibilityHint = item.placeholder
} }
self.textNode.clipsToBounds = true self.textNode.clipsToBounds = true
@ -210,6 +211,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
strongSelf.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance strongSelf.textNode.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
} }
let _ = titleApply() 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. @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; - (NSArray *)pop_animationKeys;

View File

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

View File

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

View File

@ -503,21 +503,10 @@ open class LegacyController: ViewController, PresentableController {
switch self.presentation { switch self.presentation {
case .modal: case .modal:
self.controllerNode.animateModalOut { [weak self] in 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) self?.presentingViewController?.dismiss(animated: false, completion: completion)
} }
case .custom: 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) self.presentingViewController?.dismiss(animated: false, completion: completion)
case .navigation: case .navigation:
break break
} }

View File

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

View File

@ -185,6 +185,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate {
self.textFieldNode.textField.tintColor = self.accentColor self.textFieldNode.textField.tintColor = self.accentColor
self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance
self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType self.textFieldNode.textField.keyboardType = self.fieldType.keyboardType
self.textFieldNode.textField.tintColor = self.accentColor
if self.useCustomNumpad { if self.useCustomNumpad {
switch self.fieldType { 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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textField.textField.tintColor = theme.list.itemAccentColor
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor) let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)
if !(self.textField.textField.attributedPlaceholder?.isEqual(to: attributedPlaceholder) ?? false) { 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 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 contentRect = CGRect(origin: CGPoint(), size: wrappingContentRect.size)
let overscrollY = self.scrollNode.view.bounds.minY
transition.updateFrame(node: self.scrollNode, frame: wrappingContentRect) transition.updateFrame(node: self.scrollNode, frame: wrappingContentRect)
if let contentNode = self.contentNode { if let contentNode = self.contentNode {
@ -608,7 +607,7 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
} }
let completionImpl: (SecureIdDocumentFormRequestedData) -> Void = { [weak self] requestedData in 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 return
} }

View File

@ -60,6 +60,7 @@ final class SecureIdAuthPasswordOptionContentNode: ASDisplayNode, SecureIdAuthCo
self.inputField.textField.textColor = theme.list.freeInputField.primaryColor 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.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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputField.textField.tintColor = theme.list.itemAccentColor
self.buttonNode = HighlightableButtonNode() self.buttonNode = HighlightableButtonNode()

View File

@ -2953,7 +2953,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
} }
index += 1 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 { for itemDocument in innerState.documents {
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: "")) entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
if document.id == itemDocument.id { if document.id == itemDocument.id {
@ -2962,7 +2962,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
index += 1 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 { for itemDocument in innerState.translations {
entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: "")) entries.append(SecureIdDocumentGalleryEntry(index: Int32(index), resource: itemDocument.resource, location: SecureIdDocumentGalleryEntryLocation(position: Int32(index), totalCount: totalCount), error: ""))
if document.id == itemDocument.id { 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.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.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 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.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(22.0), textColor: theme.list.itemPlaceholderTextColor)
self.inputNode.textField.textAlignment = .center self.inputNode.textField.textAlignment = .center
self.inputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance self.inputNode.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputNode.textField.tintColor = theme.list.itemAccentColor
switch inputType { switch inputType {
case .password: case .password:
self.inputNode.textField.isSecureTextEntry = true self.inputNode.textField.isSecureTextEntry = true
@ -127,6 +128,7 @@ final class SetupTwoStepVerificationContentNode: ASDisplayNode, UITextFieldDeleg
self.theme = presentationData.theme self.theme = presentationData.theme
self.inputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.inputNode.textField.keyboardAppearance = self.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor self.inputSeparator.backgroundColor = self.theme.list.itemPlainSeparatorColor
self.inputNode.textField.tintColor = self.theme.list.itemAccentColor
} }
func updateIsEnabled(_ isEnabled: Bool) { 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.imageNode.setSignal(chatAvatarGalleryPhoto(account: self.context.account, representations: representations), dispatchOnDisplayLink: false)
self.zoomableContent = (largestSize.dimensions, self.imageNode) 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()) 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.statusNode.isHidden = false
strongSelf.statusNodeContainer.isUserInteractionEnabled = true strongSelf.statusNodeContainer.isUserInteractionEnabled = true
strongSelf.statusNode.transitionToState(.download(.white), completion: {}) strongSelf.statusNode.transitionToState(.download(.white), completion: {})
case let .Fetching(isActive, progress): case let .Fetching(_, progress):
strongSelf.statusNode.isHidden = false strongSelf.statusNode.isHidden = false
strongSelf.statusNodeContainer.isUserInteractionEnabled = true strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027) let adjustedProgress = max(progress, 0.027)
@ -345,7 +345,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
representations = imageRepresentations 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()) self.fetchDisposable.set(fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, reference: representations[largestIndex].reference).start())
} }
default: default:

View File

@ -80,11 +80,12 @@ private final class ChannelOwnershipTransferPasswordFieldNode: ASDisplayNode, UI
self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor self.textInputNode.textField.textColor = self.theme.list.itemPrimaryTextColor
self.textInputNode.textField.isSecureTextEntry = true self.textInputNode.textField.isSecureTextEntry = true
self.textInputNode.textField.returnKeyType = .done 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.clipsToBounds = true
self.textInputNode.textField.delegate = self self.textInputNode.textField.delegate = self
self.textInputNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged) 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.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) { 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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.textColor = theme.list.itemPrimaryTextColor 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.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) 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 { if let item = self.item {
self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor
self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.chatList.searchBarKeyboardColor.keyboardAppearance 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.textColor = updatedTheme.list.itemPrimaryTextColor
strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.chatList.searchBarKeyboardColor.keyboardAppearance 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: []) 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) let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
var sideBlurredImage: UIImage? var sideBlurredImage: UIImage?
if true { let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize) let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) thumbnailContext.withFlippedContext { c in
thumbnailContext.withFlippedContext { c in c.interpolationQuality = .none
c.interpolationQuality = .none c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
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)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
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 {
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 { thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0)) }
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
if thumbnailContextFittingSize.width > thumbnailContextSize.width { let additionalContextSize = thumbnailContextFittingSize
let additionalContextSize = thumbnailContextFittingSize let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0) additionalBlurContext.withFlippedContext { c in
additionalBlurContext.withFlippedContext { c in c.interpolationQuality = .default
c.interpolationQuality = .default if let image = thumbnailContext.generateImage()?.cgImage {
if let image = thumbnailContext.generateImage()?.cgImage { c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
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 { } 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() 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> { 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 maybeFullSize = postbox.mediaBox.resourceData(largestRepresentation.resource)
let signal = maybeFullSize let signal = maybeFullSize
@ -1670,45 +1658,33 @@ public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: File
if let fullSizeImage = blurSourceImage { if let fullSizeImage = blurSourceImage {
var sideBlurredImage: UIImage? var sideBlurredImage: UIImage?
let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height) let thumbnailSize = CGSize(width: fullSizeImage.width, height: fullSizeImage.height)
if true { let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
let initialThumbnailContextFittingSize = drawingSize.fitted(CGSize(width: 100.0, height: 100.0))
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize)
let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize) let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0)
let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) thumbnailContext.withFlippedContext { c in
thumbnailContext.withFlippedContext { c in c.interpolationQuality = .none
c.interpolationQuality = .none c.draw(fullSizeImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
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)
var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5))
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 {
if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 { thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0))
thumbnailContextFittingSize = thumbnailContextFittingSize.aspectFilled(CGSize(width: 150.0, height: 150.0)) }
}
if thumbnailContextFittingSize.width > thumbnailContextSize.width {
if thumbnailContextFittingSize.width > thumbnailContextSize.width { let additionalContextSize = thumbnailContextFittingSize
let additionalContextSize = thumbnailContextFittingSize let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0)
let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0) additionalBlurContext.withFlippedContext { c in
additionalBlurContext.withFlippedContext { c in c.interpolationQuality = .default
c.interpolationQuality = .default if let image = thumbnailContext.generateImage()?.cgImage {
if let image = thumbnailContext.generateImage()?.cgImage { c.draw(image, in: CGRect(origin: CGPoint(), size: additionalContextSize))
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 { } 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() 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> { 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) let maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource)

View File

@ -103,4 +103,5 @@ public protocol ItemCollectionItem: PostboxCoding {
public enum ItemCollectionSearchQuery { public enum ItemCollectionSearchQuery {
case exact(ValueBoxKey) case exact(ValueBoxKey)
case matching([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) references = self.reverseIndexTable.exactReferences(namespace: ReverseIndexNamespace(namespace), token: token)
case let .matching(tokens): case let .matching(tokens):
references = Array(self.reverseIndexTable.matchingReferences(namespace: ReverseIndexNamespace(namespace), tokens: 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)]] = [:] var resultsByCollectionId: [ItemCollectionId: [(ItemCollectionItemIndex, ItemCollectionItem)]] = [:]
for reference in references { 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) 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]) { 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) 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) 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) self.postbox?.withAllMessages(peerId: peerId, namespace: namespace, f)
} }
public func clearHistory(_ peerId: PeerId) { public func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
assert(!self.disposed) assert(!self.disposed)
self.postbox?.clearHistory(peerId) self.postbox?.clearHistory(peerId, namespaces: namespaces)
} }
public func removeAllMessagesWithAuthor(_ peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { public func removeAllMessagesWithAuthor(_ peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) {
@ -1519,9 +1519,9 @@ public final class Postbox {
} }
} }
fileprivate func clearHistory(_ peerId: PeerId) { fileprivate func clearHistory(_ peerId: PeerId, namespaces: MessageIdNamespaces) {
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) 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) { 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) 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>? var references: Set<T>?
for token in tokens { for token in tokens {
if let references = references, references.isEmpty { if let references = references, references.isEmpty {
@ -208,7 +208,11 @@ final class ReverseIndexReferenceTable<T: ReverseIndexReference>: Table {
return true return true
}, limit: 0) }, limit: 0)
if let previousReferences = references { if let previousReferences = references {
references = previousReferences.intersection(currentReferences) if union {
references = previousReferences.union(currentReferences)
} else {
references = previousReferences.intersection(currentReferences)
}
} else { } else {
references = currentReferences references = currentReferences
} }

View File

@ -398,6 +398,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.clearButton.setImage(generateClearIcon(color: theme.inputClear), for: []) self.clearButton.setImage(generateClearIcon(color: theme.inputClear), for: [])
self.iconNode.image = generateLoupeIcon(color: theme.inputIcon) self.iconNode.image = generateLoupeIcon(color: theme.inputIcon)
self.textField.keyboardAppearance = theme.keyboard.keyboardAppearance self.textField.keyboardAppearance = theme.keyboard.keyboardAppearance
self.textField.tintColor = theme.accent
if let activityIndicator = self.activityIndicator { if let activityIndicator = self.activityIndicator {
activityIndicator.type = .custom(theme.inputIcon, 13.0, 1.0, false) 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 = PhoneInputNode(fontSize: 17.0)
self.phoneInputNode.countryCodeField.textField.textColor = self.presentationData.theme.list.itemPrimaryTextColor 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.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.textColor = self.presentationData.theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance self.phoneInputNode.numberField.textField.keyboardAppearance = self.presentationData.theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.numberField.textField.tintColor = self.presentationData.theme.list.itemAccentColor
super.init() super.init()

View File

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

View File

@ -384,7 +384,7 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
updateProxySettingsInteractively(transaction: transaction, { settings in updateProxySettingsInteractively(transaction: transaction, { settings in
currentSettings = settings currentSettings = settings
var settings = 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.servers[index] = proxyServerSettings
settings.activeServer = proxyServerSettings settings.activeServer = proxyServerSettings
} else { } else {

View File

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

View File

@ -344,7 +344,7 @@ private func recentSessionsControllerEntries(presentationData: PresentationData,
if !sessionsState.sessions.isEmpty { if !sessionsState.sessions.isEmpty {
var existingSessionIds = Set<Int64>() var existingSessionIds = Set<Int64>()
entries.append(.currentSessionHeader(presentationData.theme, presentationData.strings.AuthSessions_CurrentSession)) 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) existingSessionIds.insert(sessionsState.sessions[index].hash)
entries.append(.currentSession(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, sessionsState.sessions[index])) 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.delegate = self
self.textFieldNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged) 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.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) { 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.textColor = self.theme.chat.inputPanel.inputTextColor
self.textFieldNode.textField.keyboardAppearance = self.theme.chat.inputPanel.keyboardColor.keyboardAppearance 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) { private func setColor(_ color: UIColor, updatePicker: Bool = true, ended: Bool = true) {

View File

@ -179,7 +179,7 @@ public class WallpaperGalleryController: ViewController {
switch source { switch source {
case let .list(wallpapers, central, type): case let .list(wallpapers, central, type):
entries = wallpapers.map { .wallpaper($0, nil) } 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 { if case let .wallpapers(wallpaperOptions) = type, let options = wallpaperOptions {
self.initialOptions = options self.initialOptions = options

View File

@ -267,7 +267,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
} }
} }
return 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 return
} }
else { else {
@ -314,7 +314,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(resource: $0.resource)) }) 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) 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) fetchSignal = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: convertedRepresentations[largestIndex].reference)
} else { } else {
fetchSignal = .complete() fetchSignal = .complete()

View File

@ -13,13 +13,15 @@ final class ShareInputFieldNodeTheme: Equatable {
let textColor: UIColor let textColor: UIColor
let placeholderColor: UIColor let placeholderColor: UIColor
let clearButtonColor: UIColor let clearButtonColor: UIColor
let accentColor: UIColor
let keyboard: PresentationThemeKeyboardColor 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.backgroundColor = backgroundColor
self.textColor = textColor self.textColor = textColor
self.placeholderColor = placeholderColor self.placeholderColor = placeholderColor
self.clearButtonColor = clearButtonColor self.clearButtonColor = clearButtonColor
self.accentColor = accentColor
self.keyboard = keyboard self.keyboard = keyboard
} }
@ -36,6 +38,9 @@ final class ShareInputFieldNodeTheme: Equatable {
if lhs.clearButtonColor != rhs.clearButtonColor { if lhs.clearButtonColor != rhs.clearButtonColor {
return false return false
} }
if lhs.accentColor != rhs.accentColor {
return false
}
if lhs.keyboard != rhs.keyboard { if lhs.keyboard != rhs.keyboard {
return false return false
} }
@ -45,7 +50,7 @@ final class ShareInputFieldNodeTheme: Equatable {
extension ShareInputFieldNodeTheme { extension ShareInputFieldNodeTheme {
convenience init(presentationTheme theme: PresentationTheme) { 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.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.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
self.textInputNode.keyboardAppearance = theme.keyboard.keyboardAppearance self.textInputNode.keyboardAppearance = theme.keyboard.keyboardAppearance
self.textInputNode.tintColor = theme.accentColor
self.placeholderNode = ASTextNode() self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false self.placeholderNode.isUserInteractionEnabled = false

View File

@ -287,7 +287,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToItem: GridNodeScrollToItem? var scrollToItem: GridNodeScrollToItem?
if let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout { if let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil 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) 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 self.textInputNode.fixOffset = false
let textColor: UIColor = theme.actionSheet.inputTextColor let textColor: UIColor = theme.actionSheet.inputTextColor
let keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default let keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default
textInputNode.textField.font = Font.regular(16.0) self.textInputNode.textField.font = Font.regular(16.0)
textInputNode.textField.textColor = textColor self.textInputNode.textField.textColor = textColor
textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor] self.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) self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
textInputNode.textField.keyboardAppearance = keyboardAppearance self.textInputNode.textField.keyboardAppearance = keyboardAppearance
textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor) self.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.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
super.init() super.init()

View File

@ -71,7 +71,7 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable {
return false return false
} }
case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings): 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 return true
} else { } else {
return false return false
@ -436,7 +436,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToItem: GridNodeScrollToItem? var scrollToItem: GridNodeScrollToItem?
if !self.contentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout { if !self.contentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil 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) scrollToItem = GridNodeScrollToItem(index: index, position: .visible, transition: transition, directionHint: .up, adjustForSection: false)
} }
} }
@ -444,7 +444,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
var scrollToRecentItem: GridNodeScrollToItem? var scrollToRecentItem: GridNodeScrollToItem?
if !self.recentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout { if !self.recentGridNode.isHidden, let ensurePeerVisibleOnLayout = self.ensurePeerVisibleOnLayout {
self.ensurePeerVisibleOnLayout = nil self.ensurePeerVisibleOnLayout = nil
if let index = self.recentEntries.index(where: { if let index = self.recentEntries.firstIndex(where: {
switch $0 { switch $0 {
case .topPeers: case .topPeers:
return false return false

View File

@ -71,9 +71,12 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
} }
public func updateTheme(_ theme: PresentationTheme) { public func updateTheme(_ theme: PresentationTheme) {
guard theme !== self.theme else {
return
}
self.theme = theme 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.buttonGlossNode.color = theme.list.itemCheckColors.foregroundColor
self.labelNode.attributedText = NSAttributedString(string: self.title ?? "", font: Font.medium(17.0), textColor: 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 { deinit {
stickerFetchedDisposable.dispose() self.stickerFetchedDisposable.dispose()
} }
override func didLoad() { override func didLoad() {

View File

@ -29,12 +29,12 @@ public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [M
transaction.deleteMessages(ids) 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 { if peerId.namespace == Namespaces.Peer.SecretChat {
transaction.withAllMessages(peerId: peerId, { message in transaction.withAllMessages(peerId: peerId, { message in
removeMessageMedia(message: message, mediaBox: mediaBox) removeMessageMedia(message: message, mediaBox: mediaBox)
return true 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 return postbox.transaction { transaction -> Void in
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel { 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)) 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? var topIndex: MessageIndex?
if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) { if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) {
topIndex = topMessage.index 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 { 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)) 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 let topIndex = topIndex {
if peerId.namespace == Namespaces.Peer.CloudUser { 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 { } 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 { if let state = transaction.getPeerChatState(peerId) as? SecretChatState {
var layer: SecretChatLayer? var layer: SecretChatLayer?

View File

@ -309,7 +309,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net
|> then(deleteUser) |> then(deleteUser)
|> then(reportSignal) |> then(reportSignal)
|> then(postbox.transaction { transaction -> Void in |> 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 { } else if peer.id.namespace == Namespaces.Peer.CloudUser {
if let inputPeer = apiInputPeer(peer) { 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) 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(reportSignal)
|> then(postbox.transaction { transaction -> Void in |> 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 { } else {
return .complete() return .complete()

View File

@ -282,7 +282,7 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds) deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds)
} }
case .clearHistory: case .clearHistory:
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId) clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
case let .markMessagesContentAsConsumed(globallyUniqueIds): case let .markMessagesContentAsConsumed(globallyUniqueIds):
var messageIds: [MessageId] = [] var messageIds: [MessageId] = []
for id in globallyUniqueIds { 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.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue) transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue)
} else { } else {
cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible) cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
if peerId.namespace == Namespaces.Peer.CloudUser { if peerId.namespace == Namespaces.Peer.CloudUser {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) 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 { } else if peerId.namespace == Namespaces.Peer.CloudGroup {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId) clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all)
} else { } else {
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
} }

View File

@ -106,7 +106,11 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId,
case _ as TelegramMediaImage, _ as TelegramMediaFile: case _ as TelegramMediaImage, _ as TelegramMediaFile:
break break
default: 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)) var searchQuery: ItemCollectionSearchQuery = .exact(ValueBoxKey(query))
if query == "\u{2764}" { 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] = [] var installedItems: [FoundStickerItem] = []

View File

@ -3,50 +3,50 @@ import UIKit
import Display import Display
public extension TabBarControllerTheme { public extension TabBarControllerTheme {
convenience public init(rootControllerTheme: PresentationTheme) { convenience init(rootControllerTheme: PresentationTheme) {
let theme = rootControllerTheme.rootController.tabBar 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) 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 { public extension NavigationBarTheme {
convenience public init(rootControllerTheme: PresentationTheme) { convenience init(rootControllerTheme: PresentationTheme) {
let theme = rootControllerTheme.rootController.navigationBar 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) 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 { public extension NavigationBarStrings {
convenience public init(presentationStrings: PresentationStrings) { convenience init(presentationStrings: PresentationStrings) {
self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close) self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close)
} }
} }
public extension NavigationBarPresentationData { public extension NavigationBarPresentationData {
convenience public init(presentationData: PresentationData) { convenience init(presentationData: PresentationData) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings)) 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)) self.init(theme: NavigationBarTheme(rootControllerTheme: presentationTheme), strings: NavigationBarStrings(presentationStrings: presentationStrings))
} }
} }
public extension ActionSheetControllerTheme { public extension ActionSheetControllerTheme {
convenience public init(presentationTheme: PresentationTheme) { convenience init(presentationTheme: PresentationTheme) {
let actionSheet = presentationTheme.actionSheet 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) 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 { public extension ActionSheetController {
convenience public init(presentationTheme: PresentationTheme) { convenience init(presentationTheme: PresentationTheme) {
self.init(theme: ActionSheetControllerTheme(presentationTheme: presentationTheme)) self.init(theme: ActionSheetControllerTheme(presentationTheme: presentationTheme))
} }
} }
public extension AlertControllerTheme { public extension AlertControllerTheme {
convenience public init(presentationTheme: PresentationTheme) { convenience init(presentationTheme: PresentationTheme) {
let actionSheet = presentationTheme.actionSheet 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) 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 outgoingBubbleFillColor = accentColor
let hsv = accentColor.hsv 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 { } else {
outgoingPrimaryTextColor = .white outgoingPrimaryTextColor = .white
outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.65) outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.65)

View File

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

View File

@ -1,7 +1,6 @@
import Foundation import Foundation
import UIKit import UIKit
import Display import Display
import TelegramPresentationData
private func generateShareButtonImage(theme: PresentationTheme) -> UIImage? { private func generateShareButtonImage(theme: PresentationTheme) -> UIImage? {
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/NavigationShare"), color: theme.rootController.navigationBar.accentTextColor) 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 return .many
case .other: case .other:
return .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.numberField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor self.phoneInputNode.countryCodeField.textField.textColor = theme.list.itemPrimaryTextColor
self.phoneInputNode.numberField.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.countryCodeField.textField.tintColor = theme.list.itemAccentColor
self.phoneInputNode.numberField.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, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.firstNameField.textField.textContentType = .givenName 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 = TextFieldNode()
self.lastNameField.textField.font = Font.regular(20.0) 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, *) { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.lastNameField.textField.textContentType = .familyName 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 = ASImageNode()
self.currentPhotoNode.isUserInteractionEnabled = false 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)) 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) 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 strongSelf.currentContextController = controller
controller.reactionSelected = { [weak controller] value in 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 { guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else {
return 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 { if controllerInteraction.pollActionState.pollMessageIdsInProgress[id] == nil {
controllerInteraction.pollActionState.pollMessageIdsInProgress[id] = opaqueIdentifier controllerInteraction.pollActionState.pollMessageIdsInProgress[id] = opaqueIdentifier
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id) strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
@ -2804,7 +2811,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else { } else {
text = "\(count) messages selected" text = "\(count) messages selected"
} }
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text) UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
} }
} }
}, deleteSelectedMessages: { [weak self] in }, deleteSelectedMessages: { [weak self] in
@ -4547,6 +4554,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.updateChatPresentationInterfaceState(updatedChatPresentationInterfaceState, transition: transition, interactive: interactive) 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 let button = leftNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.leftNavigationButton, target: self, selector: #selector(self.leftNavigationButtonAction)) {
if self.leftNavigationButton != button { if self.leftNavigationButton != button {
var animated = transition.isAnimated var animated = transition.isAnimated
@ -4586,7 +4599,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
switch updatedChatPresentationInterfaceState.mode { switch updatedChatPresentationInterfaceState.mode {
case .standard: case .standard:
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.deferScreenEdgeGestures = [] self.deferScreenEdgeGestures = []
case .overlay: case .overlay:
self.statusBar.statusBarStyle = .Hide self.statusBar.statusBarStyle = .Hide
self.deferScreenEdgeGestures = [.top] self.deferScreenEdgeGestures = [.top]
@ -7383,9 +7396,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let peer = peer as? TelegramUser { if let peer = peer as? TelegramUser {
let recipientHandle = INPersonHandle(value: "tg\(peerId.id)", type: .unknown) 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 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 intent = INSendMessageIntent(recipients: [recipient], content: nil, groupName: nil, serviceName: nil, sender: nil)
let interaction = INInteraction(intent: intent, response: nil) let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .outgoing interaction.direction = .outgoing
interaction.donate { error in interaction.donate { error in

View File

@ -258,7 +258,8 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
accessoryItems.append(.messageAutoremoveTimeout(peer.messageAutoremoveTimeout)) 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 { if chatPresentationInterfaceState.hasScheduledMessages {
accessoryItems.append(.scheduledMessages) accessoryItems.append(.scheduledMessages)
} }

View File

@ -169,13 +169,15 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
} }
var displayBotStartPanel = false var displayBotStartPanel = false
if let _ = chatPresentationInterfaceState.botStartPayload { if !chatPresentationInterfaceState.isScheduledMessages {
if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil { if let _ = chatPresentationInterfaceState.botStartPayload {
displayBotStartPanel = true 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 { } else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState {
displayBotStartPanel = true 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) let reactionRecognizer = ReactionSwipeGestureRecognizer(target: nil, action: nil)
self.reactionRecognizer = reactionRecognizer self.reactionRecognizer = reactionRecognizer
reactionRecognizer.availableReactions = { [weak self] in 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 [] return []
} }
if strongSelf.selectionNode != nil { if strongSelf.selectionNode != nil {

View File

@ -773,6 +773,9 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
canVote = true canVote = true
} }
} }
if Namespaces.Message.allScheduled.contains(item.message.id.namespace) {
canVote = true
}
return (boundingSize.width, { boundingWidth in return (boundingSize.width, { boundingWidth in
var resultSize = CGSize(width: max(boundingSize.width, boundingWidth), height: boundingSize.height) 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 currentTime: Int32?
private let completion: (Int32) -> Void private let completion: (Int32) -> Void
private var presentationDataDisposable: Disposable?
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, completion: @escaping (Int32) -> Void) { init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, completion: @escaping (Int32) -> Void) {
self.context = context self.context = context
self.mode = mode self.mode = mode
@ -32,6 +34,13 @@ final class ChatScheduleTimeController: ViewController {
super.init(navigationBarPresentationData: nil) 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 self.statusBar.statusBarStyle = .Ignore
} }
@ -39,6 +48,10 @@ final class ChatScheduleTimeController: ViewController {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit {
self.presentationDataDisposable?.dispose()
}
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime) self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime)
self.controllerNode.completion = { [weak self] time in self.controllerNode.completion = { [weak self] time in

View File

@ -20,7 +20,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
private let contentContainerNode: ASDisplayNode private let contentContainerNode: ASDisplayNode
private let contentBackgroundNode: ASImageNode private let contentBackgroundNode: ASImageNode
private let titleNode: ASTextNode private let titleNode: ASTextNode
private let separatorNode: ASDisplayNode
private let cancelButton: HighlightableButtonNode private let cancelButton: HighlightableButtonNode
private let doneButton: SolidRoundedButtonNode private let doneButton: SolidRoundedButtonNode
@ -46,8 +45,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5) 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 = ASDisplayNode()
self.contentContainerNode.isOpaque = false self.contentContainerNode.isOpaque = false
self.contentContainerNode.clipsToBounds = true self.contentContainerNode.clipsToBounds = true
@ -55,7 +52,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.contentBackgroundNode = ASImageNode() self.contentBackgroundNode = ASImageNode()
self.contentBackgroundNode.displaysAsynchronously = false self.contentBackgroundNode.displaysAsynchronously = false
self.contentBackgroundNode.displayWithoutProcessing = true self.contentBackgroundNode.displayWithoutProcessing = true
self.contentBackgroundNode.image = roundedBackground self.contentBackgroundNode.image = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
let title: String let title: String
switch mode { switch mode {
@ -68,9 +65,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.titleNode = ASTextNode() self.titleNode = ASTextNode()
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor) 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 = HighlightableButtonNode()
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal) 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.timeZone = TimeZone.current
self.pickerView.minuteInterval = 1 self.pickerView.minuteInterval = 1
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor") self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
self.contentContainerNode.view.addSubview(self.pickerView) self.contentContainerNode.view.addSubview(self.pickerView)
self.pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged) self.pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
@ -116,6 +109,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
if let strongSelf = self { if let strongSelf = self {
if strongSelf.pickerView.date < Date() { if strongSelf.pickerView.date < Date() {
strongSelf.updateMinimumDate() strongSelf.updateMinimumDate()
strongSelf.updateButtonTitle()
strongSelf.pickerView.layer.addShakeAnimation() strongSelf.pickerView.layer.addShakeAnimation()
} else { } else {
strongSelf.doneButton.isUserInteractionEnabled = false strongSelf.doneButton.isUserInteractionEnabled = false
@ -128,6 +122,17 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.updateButtonTitle() 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) { private func updateMinimumDate(currentTime: Int32? = nil) {
let timeZone = TimeZone(secondsFromGMT: 0)! let timeZone = TimeZone(secondsFromGMT: 0)!
var calendar = Calendar(identifier: .gregorian) var calendar = Calendar(identifier: .gregorian)
@ -137,16 +142,19 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
components.second = 0 components.second = 0
let minute = (components.minute ?? 0) % 5 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) { if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) {
self.pickerView.maximumDate = date self.pickerView.maximumDate = date
} }
if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) { if let next1MinDate = next1MinDate, let next5MinDate = next5MinDate {
self.pickerView.minimumDate = date self.pickerView.minimumDate = next1MinDate
if let currentTime = currentTime { if let currentTime = currentTime, Double(currentTime) > currentDate.timeIntervalSince1970 {
self.pickerView.date = Date(timeIntervalSince1970: Double(currentTime)) self.pickerView.date = Date(timeIntervalSince1970: Double(currentTime))
} else { } 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)) 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.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.autocapitalizationType = .none
self.textInputNode.returnKeyType = .done self.textInputNode.returnKeyType = .done
self.textInputNode.autocorrectionType = .no self.textInputNode.autocorrectionType = .no
self.textInputNode.tintColor = theme.actionSheet.controlAccentColor
self.placeholderNode = ASTextNode() self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false self.placeholderNode.isUserInteractionEnabled = false
@ -75,9 +76,10 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
func updateTheme(_ theme: PresentationTheme) { func updateTheme(_ theme: PresentationTheme) {
self.theme = theme self.theme = theme
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0) self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance 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.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 { func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@ import PhotoResources
import LocalMediaResources 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> { 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> let maybeFullSize: Signal<MediaResourceData, NoError>
if thumbnail, let file = fileReference?.media { 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> { 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? let size: CGSize?
switch mode { switch mode {

View File

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

View File

@ -618,20 +618,15 @@ class WebSearchControllerNode: ASDisplayNode {
} }
private func dequeueTransition() { private func dequeueTransition() {
if let (transition, firstTime) = self.enqueuedTransitions.first { if let (transition, _) = self.enqueuedTransitions.first {
self.enqueuedTransitions.remove(at: 0) self.enqueuedTransitions.remove(at: 0)
let completion: (GridNodeDisplayedItemRange) -> Void = { [weak self] visibleRange in
if let strongSelf = self {
}
}
if let state = self.webSearchInterfaceState.state { if let state = self.webSearchInterfaceState.state {
self.recentQueriesNode.isHidden = !state.query.isEmpty self.recentQueriesNode.isHidden = !state.query.isEmpty
} }
self.hasMore = transition.hasMore 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 })
} }
} }